12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556 |
- // Copyright 2013 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "base/strings/string_util.h"
- #include <math.h>
- #include <stdarg.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <algorithm>
- #include <string>
- #include <type_traits>
- #include "base/bits.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/utf_string_conversions.h"
- #include "build/build_config.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using ::testing::ElementsAre;
- namespace base {
- static const struct trim_case {
- const wchar_t* input;
- const TrimPositions positions;
- const wchar_t* output;
- const TrimPositions return_value;
- } trim_cases[] = {
- {L" Google Video ", TRIM_LEADING, L"Google Video ", TRIM_LEADING},
- {L" Google Video ", TRIM_TRAILING, L" Google Video", TRIM_TRAILING},
- {L" Google Video ", TRIM_ALL, L"Google Video", TRIM_ALL},
- {L"Google Video", TRIM_ALL, L"Google Video", TRIM_NONE},
- {L"", TRIM_ALL, L"", TRIM_NONE},
- {L" ", TRIM_LEADING, L"", TRIM_LEADING},
- {L" ", TRIM_TRAILING, L"", TRIM_TRAILING},
- {L" ", TRIM_ALL, L"", TRIM_ALL},
- {L"\t\rTest String\n", TRIM_ALL, L"Test String", TRIM_ALL},
- {L"\x2002Test String\x00A0\x3000", TRIM_ALL, L"Test String", TRIM_ALL},
- };
- static const struct trim_case_ascii {
- const char* input;
- const TrimPositions positions;
- const char* output;
- const TrimPositions return_value;
- } trim_cases_ascii[] = {
- {" Google Video ", TRIM_LEADING, "Google Video ", TRIM_LEADING},
- {" Google Video ", TRIM_TRAILING, " Google Video", TRIM_TRAILING},
- {" Google Video ", TRIM_ALL, "Google Video", TRIM_ALL},
- {"Google Video", TRIM_ALL, "Google Video", TRIM_NONE},
- {"", TRIM_ALL, "", TRIM_NONE},
- {" ", TRIM_LEADING, "", TRIM_LEADING},
- {" ", TRIM_TRAILING, "", TRIM_TRAILING},
- {" ", TRIM_ALL, "", TRIM_ALL},
- {"\t\rTest String\n", TRIM_ALL, "Test String", TRIM_ALL},
- };
- namespace {
- // Helper used to test TruncateUTF8ToByteSize.
- bool Truncated(const std::string& input,
- const size_t byte_size,
- std::string* output) {
- size_t prev = input.length();
- TruncateUTF8ToByteSize(input, byte_size, output);
- return prev != output->length();
- }
- using TestFunction = bool (*)(StringPiece str);
- // Helper used to test IsStringUTF8{,AllowingNoncharacters}.
- void TestStructurallyValidUtf8(TestFunction fn) {
- EXPECT_TRUE(fn("abc"));
- EXPECT_TRUE(fn("\xC2\x81"));
- EXPECT_TRUE(fn("\xE1\x80\xBF"));
- EXPECT_TRUE(fn("\xF1\x80\xA0\xBF"));
- EXPECT_TRUE(fn("\xF1\x80\xA0\xBF"));
- EXPECT_TRUE(fn("a\xC2\x81\xE1\x80\xBF\xF1\x80\xA0\xBF"));
- // U+FEFF used as UTF-8 BOM.
- // clang-format off
- EXPECT_TRUE(fn("\xEF\xBB\xBF" "abc"));
- // clang-format on
- // Embedded nulls in canonical UTF-8 representation.
- using std::string_literals::operator""s;
- const std::string kEmbeddedNull = "embedded\0null"s;
- EXPECT_TRUE(fn(kEmbeddedNull));
- }
- // Helper used to test IsStringUTF8{,AllowingNoncharacters}.
- void TestStructurallyInvalidUtf8(TestFunction fn) {
- // Invalid encoding of U+1FFFE (0x8F instead of 0x9F)
- EXPECT_FALSE(fn("\xF0\x8F\xBF\xBE"));
- // Surrogate code points
- EXPECT_FALSE(fn("\xED\xA0\x80\xED\xBF\xBF"));
- EXPECT_FALSE(fn("\xED\xA0\x8F"));
- EXPECT_FALSE(fn("\xED\xBF\xBF"));
- // Overlong sequences
- EXPECT_FALSE(fn("\xC0\x80")); // U+0000
- EXPECT_FALSE(fn("\xC1\x80\xC1\x81")); // "AB"
- EXPECT_FALSE(fn("\xE0\x80\x80")); // U+0000
- EXPECT_FALSE(fn("\xE0\x82\x80")); // U+0080
- EXPECT_FALSE(fn("\xE0\x9F\xBF")); // U+07FF
- EXPECT_FALSE(fn("\xF0\x80\x80\x8D")); // U+000D
- EXPECT_FALSE(fn("\xF0\x80\x82\x91")); // U+0091
- EXPECT_FALSE(fn("\xF0\x80\xA0\x80")); // U+0800
- EXPECT_FALSE(fn("\xF0\x8F\xBB\xBF")); // U+FEFF (BOM)
- EXPECT_FALSE(fn("\xF8\x80\x80\x80\xBF")); // U+003F
- EXPECT_FALSE(fn("\xFC\x80\x80\x80\xA0\xA5")); // U+00A5
- // Beyond U+10FFFF (the upper limit of Unicode codespace)
- EXPECT_FALSE(fn("\xF4\x90\x80\x80")); // U+110000
- EXPECT_FALSE(fn("\xF8\xA0\xBF\x80\xBF")); // 5 bytes
- EXPECT_FALSE(fn("\xFC\x9C\xBF\x80\xBF\x80")); // 6 bytes
- // BOM in UTF-16(BE|LE)
- EXPECT_FALSE(fn("\xFE\xFF"));
- EXPECT_FALSE(fn("\xFF\xFE"));
- // Strings in legacy encodings. We can certainly make up strings
- // in a legacy encoding that are valid in UTF-8, but in real data,
- // most of them are invalid as UTF-8.
- // cafe with U+00E9 in ISO-8859-1
- EXPECT_FALSE(fn("caf\xE9"));
- // U+AC00, U+AC001 in EUC-KR
- EXPECT_FALSE(fn("\xB0\xA1\xB0\xA2"));
- // U+4F60 U+597D in Big5
- EXPECT_FALSE(fn("\xA7\x41\xA6\x6E"));
- // "abc" with U+201[CD] in windows-125[0-8]
- // clang-format off
- EXPECT_FALSE(fn("\x93" "abc\x94"));
- // clang-format on
- // U+0639 U+064E U+0644 U+064E in ISO-8859-6
- EXPECT_FALSE(fn("\xD9\xEE\xE4\xEE"));
- // U+03B3 U+03B5 U+03B9 U+03AC in ISO-8859-7
- EXPECT_FALSE(fn("\xE3\xE5\xE9\xDC"));
- // BOM in UTF-32(BE|LE)
- using std::string_literals::operator""s;
- const std::string kUtf32BeBom = "\x00\x00\xFE\xFF"s;
- EXPECT_FALSE(fn(kUtf32BeBom));
- const std::string kUtf32LeBom = "\xFF\xFE\x00\x00"s;
- EXPECT_FALSE(fn(kUtf32LeBom));
- }
- // Helper used to test IsStringUTF8{,AllowingNoncharacters}.
- void TestNoncharacters(TestFunction fn, bool expected_result) {
- EXPECT_EQ(fn("\xEF\xB7\x90"), expected_result); // U+FDD0
- EXPECT_EQ(fn("\xEF\xB7\x9F"), expected_result); // U+FDDF
- EXPECT_EQ(fn("\xEF\xB7\xAF"), expected_result); // U+FDEF
- EXPECT_EQ(fn("\xEF\xBF\xBE"), expected_result); // U+FFFE
- EXPECT_EQ(fn("\xEF\xBF\xBF"), expected_result); // U+FFFF
- EXPECT_EQ(fn("\xF0\x9F\xBF\xBE"), expected_result); // U+01FFFE
- EXPECT_EQ(fn("\xF0\x9F\xBF\xBF"), expected_result); // U+01FFFF
- EXPECT_EQ(fn("\xF0\xAF\xBF\xBE"), expected_result); // U+02FFFE
- EXPECT_EQ(fn("\xF0\xAF\xBF\xBF"), expected_result); // U+02FFFF
- EXPECT_EQ(fn("\xF0\xBF\xBF\xBE"), expected_result); // U+03FFFE
- EXPECT_EQ(fn("\xF0\xBF\xBF\xBF"), expected_result); // U+03FFFF
- EXPECT_EQ(fn("\xF1\x8F\xBF\xBE"), expected_result); // U+04FFFE
- EXPECT_EQ(fn("\xF1\x8F\xBF\xBF"), expected_result); // U+04FFFF
- EXPECT_EQ(fn("\xF1\x9F\xBF\xBE"), expected_result); // U+05FFFE
- EXPECT_EQ(fn("\xF1\x9F\xBF\xBF"), expected_result); // U+05FFFF
- EXPECT_EQ(fn("\xF1\xAF\xBF\xBE"), expected_result); // U+06FFFE
- EXPECT_EQ(fn("\xF1\xAF\xBF\xBF"), expected_result); // U+06FFFF
- EXPECT_EQ(fn("\xF1\xBF\xBF\xBE"), expected_result); // U+07FFFE
- EXPECT_EQ(fn("\xF1\xBF\xBF\xBF"), expected_result); // U+07FFFF
- EXPECT_EQ(fn("\xF2\x8F\xBF\xBE"), expected_result); // U+08FFFE
- EXPECT_EQ(fn("\xF2\x8F\xBF\xBF"), expected_result); // U+08FFFF
- EXPECT_EQ(fn("\xF2\x9F\xBF\xBE"), expected_result); // U+09FFFE
- EXPECT_EQ(fn("\xF2\x9F\xBF\xBF"), expected_result); // U+09FFFF
- EXPECT_EQ(fn("\xF2\xAF\xBF\xBE"), expected_result); // U+0AFFFE
- EXPECT_EQ(fn("\xF2\xAF\xBF\xBF"), expected_result); // U+0AFFFF
- EXPECT_EQ(fn("\xF2\xBF\xBF\xBE"), expected_result); // U+0BFFFE
- EXPECT_EQ(fn("\xF2\xBF\xBF\xBF"), expected_result); // U+0BFFFF
- EXPECT_EQ(fn("\xF3\x8F\xBF\xBE"), expected_result); // U+0CFFFE
- EXPECT_EQ(fn("\xF3\x8F\xBF\xBF"), expected_result); // U+0CFFFF
- EXPECT_EQ(fn("\xF3\x9F\xBF\xBE"), expected_result); // U+0DFFFE
- EXPECT_EQ(fn("\xF3\x9F\xBF\xBF"), expected_result); // U+0DFFFF
- EXPECT_EQ(fn("\xF3\xAF\xBF\xBE"), expected_result); // U+0EFFFE
- EXPECT_EQ(fn("\xF3\xAF\xBF\xBF"), expected_result); // U+0EFFFF
- EXPECT_EQ(fn("\xF3\xBF\xBF\xBE"), expected_result); // U+0FFFFE
- EXPECT_EQ(fn("\xF3\xBF\xBF\xBF"), expected_result); // U+0FFFFF
- EXPECT_EQ(fn("\xF4\x8F\xBF\xBE"), expected_result); // U+10FFFE
- EXPECT_EQ(fn("\xF4\x8F\xBF\xBF"), expected_result); // U+10FFFF
- }
- } // namespace
- TEST(StringUtilTest, TruncateUTF8ToByteSize) {
- std::string output;
- // Empty strings and invalid byte_size arguments
- EXPECT_FALSE(Truncated(std::string(), 0, &output));
- EXPECT_EQ(output, "");
- EXPECT_TRUE(Truncated("\xe1\x80\xbf", 0, &output));
- EXPECT_EQ(output, "");
- EXPECT_FALSE(Truncated("\xe1\x80\xbf", static_cast<size_t>(-1), &output));
- EXPECT_FALSE(Truncated("\xe1\x80\xbf", 4, &output));
- // Testing the truncation of valid UTF8 correctly
- EXPECT_TRUE(Truncated("abc", 2, &output));
- EXPECT_EQ(output, "ab");
- EXPECT_TRUE(Truncated("\xc2\x81\xc2\x81", 2, &output));
- EXPECT_EQ(output.compare("\xc2\x81"), 0);
- EXPECT_TRUE(Truncated("\xc2\x81\xc2\x81", 3, &output));
- EXPECT_EQ(output.compare("\xc2\x81"), 0);
- EXPECT_FALSE(Truncated("\xc2\x81\xc2\x81", 4, &output));
- EXPECT_EQ(output.compare("\xc2\x81\xc2\x81"), 0);
- {
- const char array[] = "\x00\x00\xc2\x81\xc2\x81";
- const std::string array_string(array, std::size(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\x00\x00\xc2\x81", 4)), 0);
- }
- {
- const char array[] = "\x00\xc2\x81\xc2\x81";
- const std::string array_string(array, std::size(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\x00\xc2\x81", 3)), 0);
- }
- // Testing invalid UTF8
- EXPECT_TRUE(Truncated("\xed\xa0\x80\xed\xbf\xbf", 6, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xed\xa0\x8f", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xed\xbf\xbf", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- // Testing invalid UTF8 mixed with valid UTF8
- EXPECT_FALSE(Truncated("\xe1\x80\xbf", 3, &output));
- EXPECT_EQ(output.compare("\xe1\x80\xbf"), 0);
- EXPECT_FALSE(Truncated("\xf1\x80\xa0\xbf", 4, &output));
- EXPECT_EQ(output.compare("\xf1\x80\xa0\xbf"), 0);
- EXPECT_FALSE(Truncated("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf",
- 10, &output));
- EXPECT_EQ(output.compare("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"), 0);
- EXPECT_TRUE(Truncated("a\xc2\x81\xe1\x80\xbf\xf1""a""\x80\xa0",
- 10, &output));
- EXPECT_EQ(output.compare("a\xc2\x81\xe1\x80\xbf\xf1""a"), 0);
- EXPECT_FALSE(Truncated("\xef\xbb\xbf" "abc", 6, &output));
- EXPECT_EQ(output.compare("\xef\xbb\xbf" "abc"), 0);
- // Overlong sequences
- EXPECT_TRUE(Truncated("\xc0\x80", 2, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xc1\x80\xc1\x81", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xe0\x80\x80", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xe0\x82\x80", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xe0\x9f\xbf", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x80\x80\x8D", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x80\x82\x91", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x80\xa0\x80", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x8f\xbb\xbf", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf8\x80\x80\x80\xbf", 5, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xfc\x80\x80\x80\xa0\xa5", 6, &output));
- EXPECT_EQ(output.compare(""), 0);
- // Beyond U+10FFFF (the upper limit of Unicode codespace)
- EXPECT_TRUE(Truncated("\xf4\x90\x80\x80", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf8\xa0\xbf\x80\xbf", 5, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xfc\x9c\xbf\x80\xbf\x80", 6, &output));
- EXPECT_EQ(output.compare(""), 0);
- // BOMs in UTF-16(BE|LE) and UTF-32(BE|LE)
- EXPECT_TRUE(Truncated("\xfe\xff", 2, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xff\xfe", 2, &output));
- EXPECT_EQ(output.compare(""), 0);
- {
- const char array[] = "\x00\x00\xfe\xff";
- const std::string array_string(array, std::size(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\x00\x00", 2)), 0);
- }
- // Variants on the previous test
- {
- const char array[] = "\xff\xfe\x00\x00";
- const std::string array_string(array, 4);
- EXPECT_FALSE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\xff\xfe\x00\x00", 4)), 0);
- }
- {
- const char array[] = "\xff\x00\x00\xfe";
- const std::string array_string(array, std::size(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\xff\x00\x00", 3)), 0);
- }
- // Non-characters : U+xxFFF[EF] where xx is 0x00 through 0x10 and <FDD0,FDEF>
- EXPECT_TRUE(Truncated("\xef\xbf\xbe", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x8f\xbf\xbe", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf3\xbf\xbf\xbf", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xef\xb7\x90", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xef\xb7\xaf", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- // Strings in legacy encodings that are valid in UTF-8, but
- // are invalid as UTF-8 in real data.
- EXPECT_TRUE(Truncated("caf\xe9", 4, &output));
- EXPECT_EQ(output.compare("caf"), 0);
- EXPECT_TRUE(Truncated("\xb0\xa1\xb0\xa2", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_FALSE(Truncated("\xa7\x41\xa6\x6e", 4, &output));
- EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
- EXPECT_TRUE(Truncated("\xa7\x41\xa6\x6e\xd9\xee\xe4\xee", 7,
- &output));
- EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
- // Testing using the same string as input and output.
- EXPECT_FALSE(Truncated(output, 4, &output));
- EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
- EXPECT_TRUE(Truncated(output, 3, &output));
- EXPECT_EQ(output.compare("\xa7\x41"), 0);
- // "abc" with U+201[CD] in windows-125[0-8]
- EXPECT_TRUE(Truncated("\x93" "abc\x94", 5, &output));
- EXPECT_EQ(output.compare("\x93" "abc"), 0);
- // U+0639 U+064E U+0644 U+064E in ISO-8859-6
- EXPECT_TRUE(Truncated("\xd9\xee\xe4\xee", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- // U+03B3 U+03B5 U+03B9 U+03AC in ISO-8859-7
- EXPECT_TRUE(Truncated("\xe3\xe5\xe9\xdC", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- }
- #if defined(WCHAR_T_IS_UTF16)
- TEST(StringUtilTest, as_wcstr) {
- char16_t rw_buffer[10] = {};
- static_assert(
- std::is_same<wchar_t*, decltype(as_writable_wcstr(rw_buffer))>::value,
- "");
- EXPECT_EQ(static_cast<void*>(rw_buffer), as_writable_wcstr(rw_buffer));
- std::u16string rw_str(10, '\0');
- static_assert(
- std::is_same<wchar_t*, decltype(as_writable_wcstr(rw_str))>::value, "");
- EXPECT_EQ(static_cast<const void*>(rw_str.data()), as_writable_wcstr(rw_str));
- const char16_t ro_buffer[10] = {};
- static_assert(
- std::is_same<const wchar_t*, decltype(as_wcstr(ro_buffer))>::value, "");
- EXPECT_EQ(static_cast<const void*>(ro_buffer), as_wcstr(ro_buffer));
- const std::u16string ro_str(10, '\0');
- static_assert(std::is_same<const wchar_t*, decltype(as_wcstr(ro_str))>::value,
- "");
- EXPECT_EQ(static_cast<const void*>(ro_str.data()), as_wcstr(ro_str));
- StringPiece16 piece = ro_buffer;
- static_assert(std::is_same<const wchar_t*, decltype(as_wcstr(piece))>::value,
- "");
- EXPECT_EQ(static_cast<const void*>(piece.data()), as_wcstr(piece));
- }
- TEST(StringUtilTest, as_u16cstr) {
- wchar_t rw_buffer[10] = {};
- static_assert(
- std::is_same<char16_t*, decltype(as_writable_u16cstr(rw_buffer))>::value,
- "");
- EXPECT_EQ(static_cast<void*>(rw_buffer), as_writable_u16cstr(rw_buffer));
- std::wstring rw_str(10, '\0');
- static_assert(
- std::is_same<char16_t*, decltype(as_writable_u16cstr(rw_str))>::value,
- "");
- EXPECT_EQ(static_cast<const void*>(rw_str.data()),
- as_writable_u16cstr(rw_str));
- const wchar_t ro_buffer[10] = {};
- static_assert(
- std::is_same<const char16_t*, decltype(as_u16cstr(ro_buffer))>::value,
- "");
- EXPECT_EQ(static_cast<const void*>(ro_buffer), as_u16cstr(ro_buffer));
- const std::wstring ro_str(10, '\0');
- static_assert(
- std::is_same<const char16_t*, decltype(as_u16cstr(ro_str))>::value, "");
- EXPECT_EQ(static_cast<const void*>(ro_str.data()), as_u16cstr(ro_str));
- WStringPiece piece = ro_buffer;
- static_assert(
- std::is_same<const char16_t*, decltype(as_u16cstr(piece))>::value, "");
- EXPECT_EQ(static_cast<const void*>(piece.data()), as_u16cstr(piece));
- }
- #endif // defined(WCHAR_T_IS_UTF16)
- TEST(StringUtilTest, TrimWhitespace) {
- std::u16string output; // Allow contents to carry over to next testcase
- for (const auto& value : trim_cases) {
- EXPECT_EQ(value.return_value,
- TrimWhitespace(WideToUTF16(value.input), value.positions,
- &output));
- EXPECT_EQ(WideToUTF16(value.output), output);
- }
- // Test that TrimWhitespace() can take the same string for input and output
- output = u" This is a test \r\n";
- EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
- EXPECT_EQ(u"This is a test", output);
- // Once more, but with a string of whitespace
- output = u" \r\n";
- EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
- EXPECT_EQ(std::u16string(), output);
- std::string output_ascii;
- for (const auto& value : trim_cases_ascii) {
- EXPECT_EQ(value.return_value,
- TrimWhitespaceASCII(value.input, value.positions, &output_ascii));
- EXPECT_EQ(value.output, output_ascii);
- }
- }
- static const struct collapse_case {
- const wchar_t* input;
- const bool trim;
- const wchar_t* output;
- } collapse_cases[] = {
- {L" Google Video ", false, L"Google Video"},
- {L"Google Video", false, L"Google Video"},
- {L"", false, L""},
- {L" ", false, L""},
- {L"\t\rTest String\n", false, L"Test String"},
- {L"\x2002Test String\x00A0\x3000", false, L"Test String"},
- {L" Test \n \t String ", false, L"Test String"},
- {L"\x2002Test\x1680 \x2028 \tString\x00A0\x3000", false, L"Test String"},
- {L" Test String", false, L"Test String"},
- {L"Test String ", false, L"Test String"},
- {L"Test String", false, L"Test String"},
- {L"", true, L""},
- {L"\n", true, L""},
- {L" \r ", true, L""},
- {L"\nFoo", true, L"Foo"},
- {L"\r Foo ", true, L"Foo"},
- {L" Foo bar ", true, L"Foo bar"},
- {L" \tFoo bar \n", true, L"Foo bar"},
- {L" a \r b\n c \r\n d \t\re \t f \n ", true, L"abcde f"},
- };
- TEST(StringUtilTest, CollapseWhitespace) {
- for (const auto& value : collapse_cases) {
- EXPECT_EQ(WideToUTF16(value.output),
- CollapseWhitespace(WideToUTF16(value.input), value.trim));
- }
- }
- static const struct collapse_case_ascii {
- const char* input;
- const bool trim;
- const char* output;
- } collapse_cases_ascii[] = {
- {" Google Video ", false, "Google Video"},
- {"Google Video", false, "Google Video"},
- {"", false, ""},
- {" ", false, ""},
- {"\t\rTest String\n", false, "Test String"},
- {" Test \n \t String ", false, "Test String"},
- {" Test String", false, "Test String"},
- {"Test String ", false, "Test String"},
- {"Test String", false, "Test String"},
- {"", true, ""},
- {"\n", true, ""},
- {" \r ", true, ""},
- {"\nFoo", true, "Foo"},
- {"\r Foo ", true, "Foo"},
- {" Foo bar ", true, "Foo bar"},
- {" \tFoo bar \n", true, "Foo bar"},
- {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
- };
- TEST(StringUtilTest, CollapseWhitespaceASCII) {
- for (const auto& value : collapse_cases_ascii) {
- EXPECT_EQ(value.output, CollapseWhitespaceASCII(value.input, value.trim));
- }
- }
- TEST(StringUtilTest, IsStringUTF8) {
- {
- SCOPED_TRACE("IsStringUTF8");
- TestStructurallyValidUtf8(&IsStringUTF8);
- TestStructurallyInvalidUtf8(&IsStringUTF8);
- TestNoncharacters(&IsStringUTF8, false);
- }
- {
- SCOPED_TRACE("IsStringUTF8AllowingNoncharacters");
- TestStructurallyValidUtf8(&IsStringUTF8AllowingNoncharacters);
- TestStructurallyInvalidUtf8(&IsStringUTF8AllowingNoncharacters);
- TestNoncharacters(&IsStringUTF8AllowingNoncharacters, true);
- }
- }
- TEST(StringUtilTest, IsStringASCII) {
- static char char_ascii[] =
- "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
- static char16_t char16_ascii[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
- '9', '0', 'A', 'B', 'C', 'D', 'E', 'F', '0',
- '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', 'A', 'B', 'C', 'D', 'E', 'F', 0};
- static std::wstring wchar_ascii(
- L"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
- // Test a variety of the fragment start positions and lengths in order to make
- // sure that bit masking in IsStringASCII works correctly.
- // Also, test that a non-ASCII character will be detected regardless of its
- // position inside the string.
- {
- const size_t string_length = std::size(char_ascii) - 1;
- for (size_t offset = 0; offset < 8; ++offset) {
- for (size_t len = 0, max_len = string_length - offset; len < max_len;
- ++len) {
- EXPECT_TRUE(IsStringASCII(StringPiece(char_ascii + offset, len)));
- for (size_t char_pos = offset; char_pos < len; ++char_pos) {
- char_ascii[char_pos] |= '\x80';
- EXPECT_FALSE(IsStringASCII(StringPiece(char_ascii + offset, len)));
- char_ascii[char_pos] &= ~'\x80';
- }
- }
- }
- }
- {
- const size_t string_length = std::size(char16_ascii) - 1;
- for (size_t offset = 0; offset < 4; ++offset) {
- for (size_t len = 0, max_len = string_length - offset; len < max_len;
- ++len) {
- EXPECT_TRUE(IsStringASCII(StringPiece16(char16_ascii + offset, len)));
- for (size_t char_pos = offset; char_pos < len; ++char_pos) {
- char16_ascii[char_pos] |= 0x80;
- EXPECT_FALSE(
- IsStringASCII(StringPiece16(char16_ascii + offset, len)));
- char16_ascii[char_pos] &= ~0x80;
- // Also test when the upper half is non-zero.
- char16_ascii[char_pos] |= 0x100;
- EXPECT_FALSE(
- IsStringASCII(StringPiece16(char16_ascii + offset, len)));
- char16_ascii[char_pos] &= ~0x100;
- }
- }
- }
- }
- #if defined(WCHAR_T_IS_UTF32)
- {
- const size_t string_length = wchar_ascii.length();
- for (size_t len = 0; len < string_length; ++len) {
- EXPECT_TRUE(IsStringASCII(wchar_ascii.substr(0, len)));
- for (size_t char_pos = 0; char_pos < len; ++char_pos) {
- wchar_ascii[char_pos] |= 0x80;
- EXPECT_FALSE(IsStringASCII(wchar_ascii.substr(0, len)));
- wchar_ascii[char_pos] &= ~0x80;
- wchar_ascii[char_pos] |= 0x100;
- EXPECT_FALSE(IsStringASCII(wchar_ascii.substr(0, len)));
- wchar_ascii[char_pos] &= ~0x100;
- wchar_ascii[char_pos] |= 0x10000;
- EXPECT_FALSE(IsStringASCII(wchar_ascii.substr(0, len)));
- wchar_ascii[char_pos] &= ~0x10000;
- }
- }
- }
- #endif // WCHAR_T_IS_UTF32
- }
- TEST(StringUtilTest, ConvertASCII) {
- static const char* const char_cases[] = {
- "Google Video",
- "Hello, world\n",
- "0123ABCDwxyz \a\b\t\r\n!+,.~"
- };
- static const wchar_t* const wchar_cases[] = {
- L"Google Video",
- L"Hello, world\n",
- L"0123ABCDwxyz \a\b\t\r\n!+,.~"
- };
- for (size_t i = 0; i < std::size(char_cases); ++i) {
- EXPECT_TRUE(IsStringASCII(char_cases[i]));
- std::u16string utf16 = ASCIIToUTF16(char_cases[i]);
- EXPECT_EQ(WideToUTF16(wchar_cases[i]), utf16);
- std::string ascii = UTF16ToASCII(WideToUTF16(wchar_cases[i]));
- EXPECT_EQ(char_cases[i], ascii);
- }
- EXPECT_FALSE(IsStringASCII("Google \x80Video"));
- // Convert empty strings.
- std::u16string empty16;
- std::string empty;
- EXPECT_EQ(empty, UTF16ToASCII(empty16));
- EXPECT_EQ(empty16, ASCIIToUTF16(empty));
- // Convert strings with an embedded NUL character.
- const char chars_with_nul[] = "test\0string";
- const int length_with_nul = std::size(chars_with_nul) - 1;
- std::string string_with_nul(chars_with_nul, length_with_nul);
- std::u16string string16_with_nul = ASCIIToUTF16(string_with_nul);
- EXPECT_EQ(static_cast<std::u16string::size_type>(length_with_nul),
- string16_with_nul.length());
- std::string narrow_with_nul = UTF16ToASCII(string16_with_nul);
- EXPECT_EQ(static_cast<std::string::size_type>(length_with_nul),
- narrow_with_nul.length());
- EXPECT_EQ(0, string_with_nul.compare(narrow_with_nul));
- }
- TEST(StringUtilTest, ToLowerASCII) {
- EXPECT_EQ('c', ToLowerASCII('C'));
- EXPECT_EQ('c', ToLowerASCII('c'));
- EXPECT_EQ('2', ToLowerASCII('2'));
- EXPECT_EQ(u'c', ToLowerASCII(u'C'));
- EXPECT_EQ(u'c', ToLowerASCII(u'c'));
- EXPECT_EQ(u'2', ToLowerASCII(u'2'));
- EXPECT_EQ("cc2", ToLowerASCII("Cc2"));
- EXPECT_EQ(u"cc2", ToLowerASCII(u"Cc2"));
- }
- TEST(StringUtilTest, ToUpperASCII) {
- EXPECT_EQ('C', ToUpperASCII('C'));
- EXPECT_EQ('C', ToUpperASCII('c'));
- EXPECT_EQ('2', ToUpperASCII('2'));
- EXPECT_EQ(u'C', ToUpperASCII(u'C'));
- EXPECT_EQ(u'C', ToUpperASCII(u'c'));
- EXPECT_EQ(u'2', ToUpperASCII(u'2'));
- EXPECT_EQ("CC2", ToUpperASCII("Cc2"));
- EXPECT_EQ(u"CC2", ToUpperASCII(u"Cc2"));
- }
- TEST(StringUtilTest, FormatBytesUnlocalized) {
- static const struct {
- int64_t bytes;
- const char* expected;
- } cases[] = {
- // Expected behavior: we show one post-decimal digit when we have
- // under two pre-decimal digits, except in cases where it makes no
- // sense (zero or bytes).
- // Since we switch units once we cross the 1000 mark, this keeps
- // the display of file sizes or bytes consistently around three
- // digits.
- {0, "0 B"},
- {512, "512 B"},
- {1024 * 1024, "1.0 MB"},
- {1024 * 1024 * 1024, "1.0 GB"},
- {10LL * 1024 * 1024 * 1024, "10.0 GB"},
- {99LL * 1024 * 1024 * 1024, "99.0 GB"},
- {105LL * 1024 * 1024 * 1024, "105 GB"},
- {105LL * 1024 * 1024 * 1024 + 500LL * 1024 * 1024, "105 GB"},
- {~(bits::LeftmostBit<int64_t>()), "8192 PB"},
- {99 * 1024 + 103, "99.1 kB"},
- {1024 * 1024 + 103, "1.0 MB"},
- {1024 * 1024 + 205 * 1024, "1.2 MB"},
- {1024 * 1024 * 1024 + (927 * 1024 * 1024), "1.9 GB"},
- {10LL * 1024 * 1024 * 1024, "10.0 GB"},
- {100LL * 1024 * 1024 * 1024, "100 GB"},
- };
- for (const auto& i : cases) {
- EXPECT_EQ(ASCIIToUTF16(i.expected), FormatBytesUnlocalized(i.bytes));
- }
- }
- TEST(StringUtilTest, ReplaceSubstringsAfterOffset) {
- static const struct {
- StringPiece str;
- size_t start_offset;
- StringPiece find_this;
- StringPiece replace_with;
- StringPiece expected;
- } cases[] = {
- {"aaa", 0, "", "b", "aaa"},
- {"aaa", 1, "", "b", "aaa"},
- {"aaa", 0, "a", "b", "bbb"},
- {"aaa", 0, "aa", "b", "ba"},
- {"aaa", 0, "aa", "bbb", "bbba"},
- {"aaaaa", 0, "aa", "b", "bba"},
- {"ababaaababa", 0, "aba", "", "baaba"},
- {"ababaaababa", 0, "aba", "_", "_baa_ba"},
- {"ababaaababa", 0, "aba", "__", "__baa__ba"},
- {"ababaaababa", 0, "aba", "___", "___baa___ba"},
- {"ababaaababa", 0, "aba", "____", "____baa____ba"},
- {"ababaaababa", 0, "aba", "_____", "_____baa_____ba"},
- {"abb", 0, "ab", "a", "ab"},
- {"Removing some substrings inging", 0, "ing", "", "Remov some substrs "},
- {"Not found", 0, "x", "0", "Not found"},
- {"Not found again", 5, "x", "0", "Not found again"},
- {" Making it much longer ", 0, " ", "Four score and seven years ago",
- "Four score and seven years agoMakingFour score and seven years agoit"
- "Four score and seven years agomuchFour score and seven years agolonger"
- "Four score and seven years ago"},
- {" Making it much much much much shorter ", 0,
- "Making it much much much much shorter", "", " "},
- {"so much much much much much very much much much shorter", 0, "much ",
- "", "so very shorter"},
- {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
- {"Replace me only me once", 9, "me ", "", "Replace me only once"},
- {"abababab", 2, "ab", "c", "abccc"},
- {"abababab", 1, "ab", "c", "abccc"},
- {"abababab", 1, "aba", "c", "abcbab"},
- };
- // std::u16string variant
- for (const auto& scenario : cases) {
- std::u16string str = ASCIIToUTF16(scenario.str);
- ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
- ASCIIToUTF16(scenario.find_this),
- ASCIIToUTF16(scenario.replace_with));
- EXPECT_EQ(ASCIIToUTF16(scenario.expected), str);
- }
- // std::string with insufficient capacity: expansion must realloc the buffer.
- for (const auto& scenario : cases) {
- std::string str(scenario.str);
- str.shrink_to_fit(); // This is nonbinding, but it's the best we've got.
- ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
- scenario.find_this, scenario.replace_with);
- EXPECT_EQ(scenario.expected, str);
- }
- // std::string with ample capacity: should be possible to grow in-place.
- for (const auto& scenario : cases) {
- std::string str(scenario.str);
- str.reserve(std::max(scenario.str.length(), scenario.expected.length()) *
- 2);
- ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
- scenario.find_this, scenario.replace_with);
- EXPECT_EQ(scenario.expected, str);
- }
- }
- TEST(StringUtilTest, ReplaceFirstSubstringAfterOffset) {
- static const struct {
- const char* str;
- std::u16string::size_type start_offset;
- const char* find_this;
- const char* replace_with;
- const char* expected;
- } cases[] = {
- {"aaa", 0, "a", "b", "baa"},
- {"abb", 0, "ab", "a", "ab"},
- {"Removing some substrings inging", 0, "ing", "",
- "Remov some substrings inging"},
- {"Not found", 0, "x", "0", "Not found"},
- {"Not found again", 5, "x", "0", "Not found again"},
- {" Making it much longer ", 0, " ", "Four score and seven years ago",
- "Four score and seven years agoMaking it much longer "},
- {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
- {"Replace me only me once", 4, "me ", "", "Replace only me once"},
- {"abababab", 2, "ab", "c", "abcabab"},
- };
- for (const auto& i : cases) {
- std::u16string str = ASCIIToUTF16(i.str);
- ReplaceFirstSubstringAfterOffset(&str, i.start_offset,
- ASCIIToUTF16(i.find_this),
- ASCIIToUTF16(i.replace_with));
- EXPECT_EQ(ASCIIToUTF16(i.expected), str);
- }
- }
- TEST(StringUtilTest, HexDigitToInt) {
- EXPECT_EQ(0, HexDigitToInt('0'));
- EXPECT_EQ(1, HexDigitToInt('1'));
- EXPECT_EQ(2, HexDigitToInt('2'));
- EXPECT_EQ(3, HexDigitToInt('3'));
- EXPECT_EQ(4, HexDigitToInt('4'));
- EXPECT_EQ(5, HexDigitToInt('5'));
- EXPECT_EQ(6, HexDigitToInt('6'));
- EXPECT_EQ(7, HexDigitToInt('7'));
- EXPECT_EQ(8, HexDigitToInt('8'));
- EXPECT_EQ(9, HexDigitToInt('9'));
- EXPECT_EQ(10, HexDigitToInt('A'));
- EXPECT_EQ(11, HexDigitToInt('B'));
- EXPECT_EQ(12, HexDigitToInt('C'));
- EXPECT_EQ(13, HexDigitToInt('D'));
- EXPECT_EQ(14, HexDigitToInt('E'));
- EXPECT_EQ(15, HexDigitToInt('F'));
- // Verify the lower case as well.
- EXPECT_EQ(10, HexDigitToInt('a'));
- EXPECT_EQ(11, HexDigitToInt('b'));
- EXPECT_EQ(12, HexDigitToInt('c'));
- EXPECT_EQ(13, HexDigitToInt('d'));
- EXPECT_EQ(14, HexDigitToInt('e'));
- EXPECT_EQ(15, HexDigitToInt('f'));
- }
- TEST(StringUtilTest, JoinString) {
- std::string separator(", ");
- std::vector<std::string> parts;
- EXPECT_EQ(std::string(), JoinString(parts, separator));
- parts.push_back(std::string());
- EXPECT_EQ(std::string(), JoinString(parts, separator));
- parts.clear();
- parts.push_back("a");
- EXPECT_EQ("a", JoinString(parts, separator));
- parts.push_back("b");
- parts.push_back("c");
- EXPECT_EQ("a, b, c", JoinString(parts, separator));
- parts.push_back(std::string());
- EXPECT_EQ("a, b, c, ", JoinString(parts, separator));
- parts.push_back(" ");
- EXPECT_EQ("a|b|c|| ", JoinString(parts, "|"));
- }
- TEST(StringUtilTest, JoinString16) {
- std::u16string separator = u", ";
- std::vector<std::u16string> parts;
- EXPECT_EQ(std::u16string(), JoinString(parts, separator));
- parts.push_back(std::u16string());
- EXPECT_EQ(std::u16string(), JoinString(parts, separator));
- parts.clear();
- parts.push_back(u"a");
- EXPECT_EQ(u"a", JoinString(parts, separator));
- parts.push_back(u"b");
- parts.push_back(u"c");
- EXPECT_EQ(u"a, b, c", JoinString(parts, separator));
- parts.push_back(u"");
- EXPECT_EQ(u"a, b, c, ", JoinString(parts, separator));
- parts.push_back(u" ");
- EXPECT_EQ(u"a|b|c|| ", JoinString(parts, u"|"));
- }
- TEST(StringUtilTest, JoinStringPiece) {
- std::string separator(", ");
- std::vector<StringPiece> parts;
- EXPECT_EQ(std::string(), JoinString(parts, separator));
- // Test empty first part (https://crbug.com/698073).
- parts.push_back(StringPiece());
- EXPECT_EQ(std::string(), JoinString(parts, separator));
- parts.clear();
- parts.push_back("a");
- EXPECT_EQ("a", JoinString(parts, separator));
- parts.push_back("b");
- parts.push_back("c");
- EXPECT_EQ("a, b, c", JoinString(parts, separator));
- parts.push_back(StringPiece());
- EXPECT_EQ("a, b, c, ", JoinString(parts, separator));
- parts.push_back(" ");
- EXPECT_EQ("a|b|c|| ", JoinString(parts, "|"));
- }
- TEST(StringUtilTest, JoinStringPiece16) {
- std::u16string separator = u", ";
- std::vector<StringPiece16> parts;
- EXPECT_EQ(std::u16string(), JoinString(parts, separator));
- // Test empty first part (https://crbug.com/698073).
- parts.push_back(StringPiece16());
- EXPECT_EQ(std::u16string(), JoinString(parts, separator));
- parts.clear();
- const std::u16string kA = u"a";
- parts.push_back(kA);
- EXPECT_EQ(u"a", JoinString(parts, separator));
- const std::u16string kB = u"b";
- parts.push_back(kB);
- const std::u16string kC = u"c";
- parts.push_back(kC);
- EXPECT_EQ(u"a, b, c", JoinString(parts, separator));
- parts.push_back(StringPiece16());
- EXPECT_EQ(u"a, b, c, ", JoinString(parts, separator));
- const std::u16string kSpace = u" ";
- parts.push_back(kSpace);
- EXPECT_EQ(u"a|b|c|| ", JoinString(parts, u"|"));
- }
- TEST(StringUtilTest, JoinStringInitializerList) {
- std::string separator(", ");
- EXPECT_EQ(std::string(), JoinString({}, separator));
- // Test empty first part (https://crbug.com/698073).
- EXPECT_EQ(std::string(), JoinString({StringPiece()}, separator));
- // With const char*s.
- EXPECT_EQ("a", JoinString({"a"}, separator));
- EXPECT_EQ("a, b, c", JoinString({"a", "b", "c"}, separator));
- EXPECT_EQ("a, b, c, ", JoinString({"a", "b", "c", StringPiece()}, separator));
- EXPECT_EQ("a|b|c|| ", JoinString({"a", "b", "c", StringPiece(), " "}, "|"));
- // With std::strings.
- const std::string kA = "a";
- const std::string kB = "b";
- EXPECT_EQ("a, b", JoinString({kA, kB}, separator));
- // With StringPieces.
- const StringPiece kPieceA = kA;
- const StringPiece kPieceB = kB;
- EXPECT_EQ("a, b", JoinString({kPieceA, kPieceB}, separator));
- }
- TEST(StringUtilTest, JoinStringInitializerList16) {
- std::u16string separator = u", ";
- EXPECT_EQ(std::u16string(), JoinString({}, separator));
- // Test empty first part (https://crbug.com/698073).
- EXPECT_EQ(std::u16string(), JoinString({StringPiece16()}, separator));
- // With string16s.
- const std::u16string kA = u"a";
- EXPECT_EQ(u"a", JoinString({kA}, separator));
- const std::u16string kB = u"b";
- const std::u16string kC = u"c";
- EXPECT_EQ(u"a, b, c", JoinString({kA, kB, kC}, separator));
- EXPECT_EQ(u"a, b, c, ", JoinString({kA, kB, kC, StringPiece16()}, separator));
- const std::u16string kSpace = u" ";
- EXPECT_EQ(u"a|b|c|| ",
- JoinString({kA, kB, kC, StringPiece16(), kSpace}, u"|"));
- // With StringPiece16s.
- const StringPiece16 kPieceA = kA;
- const StringPiece16 kPieceB = kB;
- EXPECT_EQ(u"a, b", JoinString({kPieceA, kPieceB}, separator));
- }
- TEST(StringUtilTest, StartsWith) {
- EXPECT_TRUE(StartsWith("javascript:url", "javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(StartsWith("JavaScript:url", "javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith("javascript:url", "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(StartsWith("JavaScript:url", "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith("java", "javascript", base::CompareCase::SENSITIVE));
- EXPECT_FALSE(StartsWith("java", "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(std::string(), "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(std::string(), "javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith("java", std::string(),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(StartsWith("java", std::string(), base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith(u"javascript:url", u"javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(StartsWith(u"JavaScript:url", u"javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith(u"javascript:url", u"javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(StartsWith(u"JavaScript:url", u"javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(
- StartsWith(u"java", u"javascript", base::CompareCase::SENSITIVE));
- EXPECT_FALSE(
- StartsWith(u"java", u"javascript", base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(std::u16string(), u"javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(std::u16string(), u"javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith(u"java", std::u16string(),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(
- StartsWith(u"java", std::u16string(), base::CompareCase::SENSITIVE));
- }
- TEST(StringUtilTest, EndsWith) {
- EXPECT_TRUE(
- EndsWith(u"Foo.plugin", u".plugin", base::CompareCase::SENSITIVE));
- EXPECT_FALSE(
- EndsWith(u"Foo.Plugin", u".plugin", base::CompareCase::SENSITIVE));
- EXPECT_TRUE(EndsWith(u"Foo.plugin", u".plugin",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(EndsWith(u"Foo.Plugin", u".plugin",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(EndsWith(u".plug", u".plugin", base::CompareCase::SENSITIVE));
- EXPECT_FALSE(
- EndsWith(u".plug", u".plugin", base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(
- EndsWith(u"Foo.plugin Bar", u".plugin", base::CompareCase::SENSITIVE));
- EXPECT_FALSE(EndsWith(u"Foo.plugin Bar", u".plugin",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(EndsWith(std::u16string(), u".plugin",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(
- EndsWith(std::u16string(), u".plugin", base::CompareCase::SENSITIVE));
- EXPECT_TRUE(EndsWith(u"Foo.plugin", std::u16string(),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(
- EndsWith(u"Foo.plugin", std::u16string(), base::CompareCase::SENSITIVE));
- EXPECT_TRUE(
- EndsWith(u".plugin", u".plugin", base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(EndsWith(u".plugin", u".plugin", base::CompareCase::SENSITIVE));
- EXPECT_TRUE(EndsWith(std::u16string(), std::u16string(),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(EndsWith(std::u16string(), std::u16string(),
- base::CompareCase::SENSITIVE));
- }
- TEST(StringUtilTest, GetStringFWithOffsets) {
- std::vector<std::u16string> subst;
- subst.push_back(u"1");
- subst.push_back(u"2");
- std::vector<size_t> offsets;
- ReplaceStringPlaceholders(u"Hello, $1. Your number is $2.", subst, &offsets);
- EXPECT_EQ(2U, offsets.size());
- EXPECT_EQ(7U, offsets[0]);
- EXPECT_EQ(25U, offsets[1]);
- offsets.clear();
- ReplaceStringPlaceholders(u"Hello, $2. Your number is $1.", subst, &offsets);
- EXPECT_EQ(2U, offsets.size());
- EXPECT_EQ(25U, offsets[0]);
- EXPECT_EQ(7U, offsets[1]);
- offsets.clear();
- }
- TEST(StringUtilTest, ReplaceStringPlaceholdersTooFew) {
- // Test whether replacestringplaceholders works as expected when there
- // are fewer inputs than outputs.
- std::vector<std::u16string> subst;
- subst.push_back(u"9a");
- subst.push_back(u"8b");
- subst.push_back(u"7c");
- std::u16string formatted = ReplaceStringPlaceholders(
- u"$1a,$2b,$3c,$4d,$5e,$6f,$1g,$2h,$3i", subst, nullptr);
- EXPECT_EQ(u"9aa,8bb,7cc,d,e,f,9ag,8bh,7ci", formatted);
- }
- TEST(StringUtilTest, ReplaceStringPlaceholders) {
- std::vector<std::u16string> subst;
- subst.push_back(u"9a");
- subst.push_back(u"8b");
- subst.push_back(u"7c");
- subst.push_back(u"6d");
- subst.push_back(u"5e");
- subst.push_back(u"4f");
- subst.push_back(u"3g");
- subst.push_back(u"2h");
- subst.push_back(u"1i");
- std::u16string formatted = ReplaceStringPlaceholders(
- u"$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i", subst, nullptr);
- EXPECT_EQ(u"9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii", formatted);
- }
- TEST(StringUtilTest, ReplaceStringPlaceholdersNetExpansionWithContraction) {
- // In this test, some of the substitutions are shorter than the placeholders,
- // but overall the string gets longer.
- std::vector<std::u16string> subst;
- subst.push_back(u"9a____");
- subst.push_back(u"B");
- subst.push_back(u"7c___");
- subst.push_back(u"d");
- subst.push_back(u"5e____");
- subst.push_back(u"F");
- subst.push_back(u"3g___");
- subst.push_back(u"h");
- subst.push_back(u"1i_____");
- std::u16string original = u"$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i";
- std::u16string expected =
- u"9a____a,Bb,7c___c,dd,5e____e,Ff,3g___g,hh,1i_____i";
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, nullptr));
- std::vector<size_t> offsets;
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, &offsets));
- std::vector<size_t> expected_offsets = {0, 8, 11, 18, 21, 29, 32, 39, 42};
- EXPECT_EQ(offsets.size(), subst.size());
- EXPECT_EQ(expected_offsets, offsets);
- for (size_t i = 0; i < offsets.size(); i++) {
- EXPECT_EQ(expected.substr(expected_offsets[i], subst[i].length()),
- subst[i]);
- }
- }
- TEST(StringUtilTest, ReplaceStringPlaceholdersNetContractionWithExpansion) {
- // In this test, some of the substitutions are longer than the placeholders,
- // but overall the string gets smaller. Additionally, the placeholders appear
- // in a permuted order.
- std::vector<std::u16string> subst;
- subst.push_back(u"z");
- subst.push_back(u"y");
- subst.push_back(u"XYZW");
- subst.push_back(u"x");
- subst.push_back(u"w");
- std::u16string formatted =
- ReplaceStringPlaceholders(u"$3_$4$2$1$5", subst, nullptr);
- EXPECT_EQ(u"XYZW_xyzw", formatted);
- }
- TEST(StringUtilTest, ReplaceStringPlaceholdersOneDigit) {
- std::vector<std::u16string> subst;
- subst.push_back(u"1a");
- std::u16string formatted =
- ReplaceStringPlaceholders(u" $16 ", subst, nullptr);
- EXPECT_EQ(u" 1a6 ", formatted);
- }
- TEST(StringUtilTest, ReplaceStringPlaceholdersInvalidPlaceholder) {
- std::vector<std::u16string> subst;
- subst.push_back(u"1a");
- std::u16string formatted =
- ReplaceStringPlaceholders(u"+$-+$A+$1+", subst, nullptr);
- EXPECT_EQ(u"+++1a+", formatted);
- }
- TEST(StringUtilTest, StdStringReplaceStringPlaceholders) {
- std::vector<std::string> subst;
- subst.push_back("9a");
- subst.push_back("8b");
- subst.push_back("7c");
- subst.push_back("6d");
- subst.push_back("5e");
- subst.push_back("4f");
- subst.push_back("3g");
- subst.push_back("2h");
- subst.push_back("1i");
- std::string formatted =
- ReplaceStringPlaceholders(
- "$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i", subst, nullptr);
- EXPECT_EQ("9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii", formatted);
- }
- TEST(StringUtilTest, StdStringReplaceStringPlaceholdersMultipleMatches) {
- std::vector<std::string> subst;
- subst.push_back("4"); // Referenced twice.
- subst.push_back("?"); // Unreferenced.
- subst.push_back("!"); // Unreferenced.
- subst.push_back("16"); // Referenced once.
- std::string original = "$1 * $1 == $4";
- std::string expected = "4 * 4 == 16";
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, nullptr));
- std::vector<size_t> offsets;
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, &offsets));
- std::vector<size_t> expected_offsets = {0, 4, 9};
- EXPECT_EQ(expected_offsets, offsets);
- }
- TEST(StringUtilTest, ReplaceStringPlaceholdersConsecutiveDollarSigns) {
- std::vector<std::string> subst;
- subst.push_back("a");
- subst.push_back("b");
- subst.push_back("c");
- EXPECT_EQ(ReplaceStringPlaceholders("$$1 $$$2 $$$$3", subst, nullptr),
- "$1 $$2 $$$3");
- }
- TEST(StringUtilTest, LcpyTest) {
- // Test the normal case where we fit in our buffer.
- {
- char dst[10];
- wchar_t wdst[10];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
- EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
- }
- // Test dst_size == 0, nothing should be written to |dst| and we should
- // have the equivalent of strlen(src).
- {
- char dst[2] = {1, 2};
- wchar_t wdst[2] = {1, 2};
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", 0));
- EXPECT_EQ(1, dst[0]);
- EXPECT_EQ(2, dst[1]);
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", 0));
- EXPECT_EQ(static_cast<wchar_t>(1), wdst[0]);
- EXPECT_EQ(static_cast<wchar_t>(2), wdst[1]);
- }
- // Test the case were we _just_ competely fit including the null.
- {
- char dst[8];
- wchar_t wdst[8];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
- EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
- }
- // Test the case were we we are one smaller, so we can't fit the null.
- {
- char dst[7];
- wchar_t wdst[7];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
- EXPECT_EQ(0, memcmp(dst, "abcdef", 7));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"abcdef", sizeof(wchar_t) * 7));
- }
- // Test the case were we are just too small.
- {
- char dst[3];
- wchar_t wdst[3];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst)));
- EXPECT_EQ(0, memcmp(dst, "ab", 3));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"ab", sizeof(wchar_t) * 3));
- }
- }
- TEST(StringUtilTest, WprintfFormatPortabilityTest) {
- static const struct {
- const wchar_t* input;
- bool portable;
- } cases[] = {
- { L"%ls", true },
- { L"%s", false },
- { L"%S", false },
- { L"%lS", false },
- { L"Hello, %s", false },
- { L"%lc", true },
- { L"%c", false },
- { L"%C", false },
- { L"%lC", false },
- { L"%ls %s", false },
- { L"%s %ls", false },
- { L"%s %ls %s", false },
- { L"%f", true },
- { L"%f %F", false },
- { L"%d %D", false },
- { L"%o %O", false },
- { L"%u %U", false },
- { L"%f %d %o %u", true },
- { L"%-8d (%02.1f%)", true },
- { L"% 10s", false },
- { L"% 10ls", true }
- };
- for (const auto& i : cases)
- EXPECT_EQ(i.portable, IsWprintfFormatPortable(i.input));
- }
- TEST(StringUtilTest, MakeBasicStringPieceTest) {
- constexpr char kFoo[] = "Foo";
- static_assert(MakeStringPiece(kFoo, kFoo + 3) == kFoo, "");
- static_assert(MakeStringPiece(kFoo, kFoo + 3).data() == kFoo, "");
- static_assert(MakeStringPiece(kFoo, kFoo + 3).size() == 3, "");
- static_assert(MakeStringPiece(kFoo + 3, kFoo + 3).empty(), "");
- static_assert(MakeStringPiece(kFoo + 4, kFoo + 4).empty(), "");
- std::string foo = kFoo;
- EXPECT_EQ(MakeStringPiece(foo.begin(), foo.end()), foo);
- EXPECT_EQ(MakeStringPiece(foo.begin(), foo.end()).data(), foo.data());
- EXPECT_EQ(MakeStringPiece(foo.begin(), foo.end()).size(), foo.size());
- EXPECT_TRUE(MakeStringPiece(foo.end(), foo.end()).empty());
- constexpr char16_t kBar[] = u"Bar";
- static_assert(MakeStringPiece16(kBar, kBar + 3) == kBar, "");
- static_assert(MakeStringPiece16(kBar, kBar + 3).data() == kBar, "");
- static_assert(MakeStringPiece16(kBar, kBar + 3).size() == 3, "");
- static_assert(MakeStringPiece16(kBar + 3, kBar + 3).empty(), "");
- static_assert(MakeStringPiece16(kBar + 4, kBar + 4).empty(), "");
- std::u16string bar = kBar;
- EXPECT_EQ(MakeStringPiece16(bar.begin(), bar.end()), bar);
- EXPECT_EQ(MakeStringPiece16(bar.begin(), bar.end()).data(), bar.data());
- EXPECT_EQ(MakeStringPiece16(bar.begin(), bar.end()).size(), bar.size());
- EXPECT_TRUE(MakeStringPiece16(bar.end(), bar.end()).empty());
- constexpr wchar_t kBaz[] = L"Baz";
- static_assert(MakeWStringPiece(kBaz, kBaz + 3) == kBaz, "");
- static_assert(MakeWStringPiece(kBaz, kBaz + 3).data() == kBaz, "");
- static_assert(MakeWStringPiece(kBaz, kBaz + 3).size() == 3, "");
- static_assert(MakeWStringPiece(kBaz + 3, kBaz + 3).empty(), "");
- static_assert(MakeWStringPiece(kBaz + 4, kBaz + 4).empty(), "");
- std::wstring baz = kBaz;
- EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()), baz);
- EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()).data(), baz.data());
- EXPECT_EQ(MakeWStringPiece(baz.begin(), baz.end()).size(), baz.size());
- EXPECT_TRUE(MakeWStringPiece(baz.end(), baz.end()).empty());
- }
- TEST(StringUtilTest, RemoveChars) {
- const char kRemoveChars[] = "-/+*";
- std::string input = "A-+bc/d!*";
- EXPECT_TRUE(RemoveChars(input, kRemoveChars, &input));
- EXPECT_EQ("Abcd!", input);
- // No characters match kRemoveChars.
- EXPECT_FALSE(RemoveChars(input, kRemoveChars, &input));
- EXPECT_EQ("Abcd!", input);
- // Empty string.
- input.clear();
- EXPECT_FALSE(RemoveChars(input, kRemoveChars, &input));
- EXPECT_EQ(std::string(), input);
- }
- TEST(StringUtilTest, ReplaceChars) {
- struct TestData {
- const char* input;
- const char* replace_chars;
- const char* replace_with;
- const char* output;
- bool result;
- } cases[] = {
- {"", "", "", "", false},
- {"t", "t", "t", "t", true},
- {"a", "b", "c", "a", false},
- {"b", "b", "c", "c", true},
- {"bob", "b", "p", "pop", true},
- {"bob", "o", "i", "bib", true},
- {"test", "", "", "test", false},
- {"test", "", "!", "test", false},
- {"test", "z", "!", "test", false},
- {"test", "e", "!", "t!st", true},
- {"test", "e", "!?", "t!?st", true},
- {"test", "ez", "!", "t!st", true},
- {"test", "zed", "!?", "t!?st", true},
- {"test", "t", "!?", "!?es!?", true},
- {"test", "et", "!>", "!>!>s!>", true},
- {"test", "zest", "!", "!!!!", true},
- {"test", "szt", "!", "!e!!", true},
- {"test", "t", "test", "testestest", true},
- {"tetst", "t", "test", "testeteststest", true},
- {"ttttttt", "t", "-", "-------", true},
- {"aAaAaAAaAAa", "A", "", "aaaaa", true},
- {"xxxxxxxxxx", "x", "", "", true},
- {"xxxxxxxxxx", "x", "x", "xxxxxxxxxx", true},
- {"xxxxxxxxxx", "x", "y-", "y-y-y-y-y-y-y-y-y-y-", true},
- {"xxxxxxxxxx", "x", "xy", "xyxyxyxyxyxyxyxyxyxy", true},
- {"xxxxxxxxxx", "x", "zyx", "zyxzyxzyxzyxzyxzyxzyxzyxzyxzyx", true},
- {"xaxxaxxxaxxxax", "x", "xy", "xyaxyxyaxyxyxyaxyxyxyaxy", true},
- {"-xaxxaxxxaxxxax-", "x", "xy", "-xyaxyxyaxyxyxyaxyxyxyaxy-", true},
- };
- for (const TestData& scenario : cases) {
- // Test with separate output and input vars.
- std::string output;
- bool result = ReplaceChars(scenario.input, scenario.replace_chars,
- scenario.replace_with, &output);
- EXPECT_EQ(scenario.result, result) << scenario.input;
- EXPECT_EQ(scenario.output, output);
- }
- for (const TestData& scenario : cases) {
- // Test with an input/output var of limited capacity.
- std::string input_output = scenario.input;
- input_output.shrink_to_fit();
- bool result = ReplaceChars(input_output, scenario.replace_chars,
- scenario.replace_with, &input_output);
- EXPECT_EQ(scenario.result, result) << scenario.input;
- EXPECT_EQ(scenario.output, input_output);
- }
- for (const TestData& scenario : cases) {
- // Test with an input/output var of ample capacity; should
- // not realloc.
- std::string input_output = scenario.input;
- input_output.reserve(strlen(scenario.output) * 2);
- const void* original_buffer = input_output.data();
- bool result = ReplaceChars(input_output, scenario.replace_chars,
- scenario.replace_with, &input_output);
- EXPECT_EQ(scenario.result, result) << scenario.input;
- EXPECT_EQ(scenario.output, input_output);
- EXPECT_EQ(original_buffer, input_output.data());
- }
- }
- TEST(StringUtilTest, ContainsOnlyChars) {
- // Providing an empty list of characters should return false but for the empty
- // string.
- EXPECT_TRUE(ContainsOnlyChars(std::string(), std::string()));
- EXPECT_FALSE(ContainsOnlyChars("Hello", std::string()));
- EXPECT_TRUE(ContainsOnlyChars(std::string(), "1234"));
- EXPECT_TRUE(ContainsOnlyChars("1", "1234"));
- EXPECT_TRUE(ContainsOnlyChars("1", "4321"));
- EXPECT_TRUE(ContainsOnlyChars("123", "4321"));
- EXPECT_FALSE(ContainsOnlyChars("123a", "4321"));
- EXPECT_TRUE(ContainsOnlyChars(std::string(), kWhitespaceASCII));
- EXPECT_TRUE(ContainsOnlyChars(" ", kWhitespaceASCII));
- EXPECT_TRUE(ContainsOnlyChars("\t", kWhitespaceASCII));
- EXPECT_TRUE(ContainsOnlyChars("\t \r \n ", kWhitespaceASCII));
- EXPECT_FALSE(ContainsOnlyChars("a", kWhitespaceASCII));
- EXPECT_FALSE(ContainsOnlyChars("\thello\r \n ", kWhitespaceASCII));
- EXPECT_TRUE(ContainsOnlyChars(std::u16string(), kWhitespaceUTF16));
- EXPECT_TRUE(ContainsOnlyChars(u" ", kWhitespaceUTF16));
- EXPECT_TRUE(ContainsOnlyChars(u"\t", kWhitespaceUTF16));
- EXPECT_TRUE(ContainsOnlyChars(u"\t \r \n ", kWhitespaceUTF16));
- EXPECT_FALSE(ContainsOnlyChars(u"a", kWhitespaceUTF16));
- EXPECT_FALSE(ContainsOnlyChars(u"\thello\r \n ", kWhitespaceUTF16));
- }
- TEST(StringUtilTest, CompareCaseInsensitiveASCII) {
- EXPECT_EQ(0, CompareCaseInsensitiveASCII("", ""));
- EXPECT_EQ(0, CompareCaseInsensitiveASCII("Asdf", "aSDf"));
- // Differing lengths.
- EXPECT_EQ(-1, CompareCaseInsensitiveASCII("Asdf", "aSDfA"));
- EXPECT_EQ(1, CompareCaseInsensitiveASCII("AsdfA", "aSDf"));
- // Differing values.
- EXPECT_EQ(-1, CompareCaseInsensitiveASCII("AsdfA", "aSDfb"));
- EXPECT_EQ(1, CompareCaseInsensitiveASCII("Asdfb", "aSDfA"));
- }
- TEST(StringUtilTest, EqualsCaseInsensitiveASCII) {
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("", ""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", "aSDFz"));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"", u""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"Asdf", u"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"bsdf", u"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"Asdf", u"aSDFz"));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"", ""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(u"Asdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"bsdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(u"Asdf", "aSDFz"));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("", u""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", u"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", u"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", u"aSDFz"));
- // The `WStringPiece` overloads are only defined on Windows.
- #if BUILDFLAG(IS_WIN)
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"", L""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"Asdf", L"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"bsdf", L"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"Asdf", L"aSDFz"));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"", ""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII(L"Asdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"bsdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII(L"Asdf", "aSDFz"));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("", L""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", L"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", L"aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", L"aSDFz"));
- #endif
- }
- TEST(StringUtilTest, IsUnicodeWhitespace) {
- // NOT unicode white space.
- EXPECT_FALSE(IsUnicodeWhitespace(L'\0'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'A'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'0'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'.'));
- EXPECT_FALSE(IsUnicodeWhitespace(L';'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'\x4100'));
- // Actual unicode whitespace.
- EXPECT_TRUE(IsUnicodeWhitespace(L' '));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\xa0'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\x3000'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\t'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\r'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\v'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\f'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\n'));
- }
- class WriteIntoTest : public testing::Test {
- protected:
- static void WritesCorrectly(size_t num_chars) {
- std::string buffer;
- char kOriginal[] = "supercali";
- strncpy(WriteInto(&buffer, num_chars + 1), kOriginal, num_chars);
- // Using std::string(buffer.c_str()) instead of |buffer| truncates the
- // string at the first \0.
- EXPECT_EQ(
- std::string(kOriginal, std::min(num_chars, std::size(kOriginal) - 1)),
- std::string(buffer.c_str()));
- EXPECT_EQ(num_chars, buffer.size());
- }
- };
- TEST_F(WriteIntoTest, WriteInto) {
- // Validate that WriteInto reserves enough space and
- // sizes a string correctly.
- WritesCorrectly(1);
- WritesCorrectly(2);
- WritesCorrectly(5000);
- // Validate that WriteInto handles 0-length strings
- std::string empty;
- const char kOriginal[] = "original";
- strncpy(WriteInto(&empty, 1), kOriginal, 0);
- EXPECT_STREQ("", empty.c_str());
- EXPECT_EQ(0u, empty.size());
- // Validate that WriteInto doesn't modify other strings
- // when using a Copy-on-Write implementation.
- const char kLive[] = "live";
- const char kDead[] = "dead";
- const std::string live = kLive;
- std::string dead = live;
- strncpy(WriteInto(&dead, 5), kDead, 4);
- EXPECT_EQ(kDead, dead);
- EXPECT_EQ(4u, dead.size());
- EXPECT_EQ(kLive, live);
- EXPECT_EQ(4u, live.size());
- }
- } // namespace base
|