StringTest.cpp 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413
  1. /*
  2. * Copyright 2012-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef __STDC_FORMAT_MACROS
  17. #define __STDC_FORMAT_MACROS 1
  18. #endif
  19. #include <folly/String.h>
  20. #include <tuple>
  21. #include <cinttypes>
  22. #include <set>
  23. #include <boost/regex.hpp>
  24. #include <folly/container/Array.h>
  25. #include <folly/portability/GTest.h>
  26. #include <folly/test/TestUtils.h>
  27. using namespace folly;
  28. using namespace std;
  29. TEST(StringPrintf, BasicTest) {
  30. EXPECT_EQ("abc", stringPrintf("%s", "abc"));
  31. EXPECT_EQ("abc", stringPrintf("%sbc", "a"));
  32. EXPECT_EQ("abc", stringPrintf("a%sc", "b"));
  33. EXPECT_EQ("abc", stringPrintf("ab%s", "c"));
  34. EXPECT_EQ("abc", stringPrintf("abc"));
  35. }
  36. TEST(StringPrintf, NumericFormats) {
  37. EXPECT_EQ("12", stringPrintf("%d", 12));
  38. EXPECT_EQ("2000000000", stringPrintf("%ld", 2000000000UL));
  39. EXPECT_EQ("2000000000", stringPrintf("%ld", 2000000000L));
  40. EXPECT_EQ("-2000000000", stringPrintf("%ld", -2000000000L));
  41. EXPECT_EQ("5000000000", stringPrintf("%lld", 5000000000ULL));
  42. EXPECT_EQ("5000000000", stringPrintf("%lld", 5000000000LL));
  43. EXPECT_EQ("-5000000000", stringPrintf("%lld", -5000000000LL));
  44. EXPECT_EQ("-1", stringPrintf("%d", 0xffffffff));
  45. EXPECT_EQ(
  46. "-1",
  47. stringPrintf("%" PRId64, static_cast<int64_t>(0xffffffffffffffffLL)));
  48. EXPECT_EQ(
  49. "-1",
  50. stringPrintf("%" PRId64, static_cast<uint64_t>(0xffffffffffffffffULL)));
  51. EXPECT_EQ("7.7", stringPrintf("%1.1f", 7.7));
  52. EXPECT_EQ("7.7", stringPrintf("%1.1lf", 7.7));
  53. EXPECT_EQ("7.70000000000000018", stringPrintf("%.17f", 7.7));
  54. EXPECT_EQ("7.70000000000000018", stringPrintf("%.17lf", 7.7));
  55. }
  56. TEST(StringPrintf, Appending) {
  57. string s;
  58. stringAppendf(&s, "a%s", "b");
  59. stringAppendf(&s, "%c", 'c');
  60. EXPECT_EQ(s, "abc");
  61. stringAppendf(&s, " %d", 123);
  62. EXPECT_EQ(s, "abc 123");
  63. }
  64. void vprintfCheck(const char* expected, const char* fmt, ...) {
  65. va_list apOrig;
  66. va_start(apOrig, fmt);
  67. SCOPE_EXIT {
  68. va_end(apOrig);
  69. };
  70. va_list ap;
  71. va_copy(ap, apOrig);
  72. SCOPE_EXIT {
  73. va_end(ap);
  74. };
  75. // Check both APIs for calling stringVPrintf()
  76. EXPECT_EQ(expected, stringVPrintf(fmt, ap));
  77. va_end(ap);
  78. va_copy(ap, apOrig);
  79. std::string out;
  80. stringVPrintf(&out, fmt, ap);
  81. va_end(ap);
  82. va_copy(ap, apOrig);
  83. EXPECT_EQ(expected, out);
  84. // Check stringVAppendf() as well
  85. std::string prefix = "foobar";
  86. out = prefix;
  87. EXPECT_EQ(prefix + expected, stringVAppendf(&out, fmt, ap));
  88. va_end(ap);
  89. va_copy(ap, apOrig);
  90. }
  91. void vprintfError(const char* fmt, ...) {
  92. va_list ap;
  93. va_start(ap, fmt);
  94. SCOPE_EXIT {
  95. va_end(ap);
  96. };
  97. #ifdef HAVE_VSNPRINTF_ERRORS
  98. // OSX's sprintf family does not return a negative number on a bad format
  99. // string, but Linux does. It's unclear to me which behavior is more
  100. // correct.
  101. EXPECT_THROW({ stringVPrintf(fmt, ap); }, std::runtime_error);
  102. #endif
  103. }
  104. TEST(StringPrintf, VPrintf) {
  105. vprintfCheck("foo", "%s", "foo");
  106. vprintfCheck(
  107. "long string requiring reallocation 1 2 3 0x12345678",
  108. "%s %s %d %d %d %#x",
  109. "long string",
  110. "requiring reallocation",
  111. 1,
  112. 2,
  113. 3,
  114. 0x12345678);
  115. vprintfError("bogus%", "foo");
  116. }
  117. TEST(StringPrintf, VariousSizes) {
  118. // Test a wide variety of output sizes, making sure to cross the
  119. // vsnprintf buffer boundary implementation detail.
  120. for (int i = 0; i < 4096; ++i) {
  121. string expected(i + 1, 'a');
  122. expected = "X" + expected + "X";
  123. string result = stringPrintf("%s", expected.c_str());
  124. EXPECT_EQ(expected.size(), result.size());
  125. EXPECT_EQ(expected, result);
  126. }
  127. // clang-format off
  128. EXPECT_EQ("abc12345678910111213141516171819202122232425xyz",
  129. stringPrintf("abc%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
  130. "%d%d%d%d%d%d%d%d%d%d%dxyz",
  131. 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
  132. 17, 18, 19, 20, 21, 22, 23, 24, 25));
  133. // clang-format on
  134. }
  135. TEST(StringPrintf, oldStringPrintfTests) {
  136. EXPECT_EQ(string("a/b/c/d"), stringPrintf("%s/%s/%s/%s", "a", "b", "c", "d"));
  137. EXPECT_EQ(string(" 5 10"), stringPrintf("%5d %5d", 5, 10));
  138. // check printing w/ a big buffer
  139. for (int size = (1 << 8); size <= (1 << 15); size <<= 1) {
  140. string a(size, 'z');
  141. string b = stringPrintf("%s", a.c_str());
  142. EXPECT_EQ(a.size(), b.size());
  143. }
  144. }
  145. TEST(StringPrintf, oldStringAppendf) {
  146. string s = "hello";
  147. stringAppendf(&s, "%s/%s/%s/%s", "a", "b", "c", "d");
  148. EXPECT_EQ(string("helloa/b/c/d"), s);
  149. }
  150. TEST(Escape, cEscape) {
  151. EXPECT_EQ("hello world", cEscape<std::string>("hello world"));
  152. EXPECT_EQ(
  153. "hello \\\\world\\\" goodbye",
  154. cEscape<std::string>("hello \\world\" goodbye"));
  155. EXPECT_EQ("hello\\nworld", cEscape<std::string>("hello\nworld"));
  156. EXPECT_EQ("hello\\377\\376", cEscape<std::string>("hello\xff\xfe"));
  157. }
  158. TEST(Escape, cUnescape) {
  159. EXPECT_EQ("hello world", cUnescape<std::string>("hello world"));
  160. EXPECT_EQ(
  161. "hello \\world\" goodbye",
  162. cUnescape<std::string>("hello \\\\world\\\" goodbye"));
  163. EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\nworld"));
  164. EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\012world"));
  165. EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\x0aworld"));
  166. EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\377\\376"));
  167. EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\xff\\xfe"));
  168. EXPECT_EQ("hello\\", cUnescape<std::string>("hello\\", false));
  169. EXPECT_THROW_RE(
  170. cUnescape<std::string>("hello\\"),
  171. std::invalid_argument,
  172. "incomplete escape sequence");
  173. EXPECT_THROW_RE(
  174. cUnescape<std::string>("hello\\x"),
  175. std::invalid_argument,
  176. "incomplete hex escape sequence");
  177. EXPECT_THROW_RE(
  178. cUnescape<std::string>("hello\\q"),
  179. std::invalid_argument,
  180. "invalid escape sequence");
  181. }
  182. TEST(Escape, uriEscape) {
  183. EXPECT_EQ("hello%2c%20%2fworld", uriEscape<std::string>("hello, /world"));
  184. EXPECT_EQ(
  185. "hello%2c%20/world",
  186. uriEscape<std::string>("hello, /world", UriEscapeMode::PATH));
  187. EXPECT_EQ(
  188. "hello%2c+%2fworld",
  189. uriEscape<std::string>("hello, /world", UriEscapeMode::QUERY));
  190. EXPECT_EQ(
  191. "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~",
  192. uriEscape<std::string>(
  193. "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~"));
  194. }
  195. TEST(Escape, uriUnescape) {
  196. EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello, /world"));
  197. EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c%20%2fworld"));
  198. EXPECT_EQ("hello,+/world", uriUnescape<std::string>("hello%2c+%2fworld"));
  199. EXPECT_EQ(
  200. "hello, /world",
  201. uriUnescape<std::string>("hello%2c+%2fworld", UriEscapeMode::QUERY));
  202. EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2f"));
  203. EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2F"));
  204. EXPECT_THROW({ uriUnescape<std::string>("hello%"); }, std::invalid_argument);
  205. EXPECT_THROW({ uriUnescape<std::string>("hello%2"); }, std::invalid_argument);
  206. EXPECT_THROW(
  207. { uriUnescape<std::string>("hello%2g"); }, std::invalid_argument);
  208. }
  209. namespace {
  210. void expectPrintable(StringPiece s) {
  211. for (char c : s) {
  212. EXPECT_LE(32, c);
  213. EXPECT_GE(127, c);
  214. }
  215. }
  216. } // namespace
  217. TEST(Escape, uriEscapeAllCombinations) {
  218. char c[3];
  219. c[2] = '\0';
  220. StringPiece in(c, 2);
  221. fbstring tmp;
  222. fbstring out;
  223. for (int i = 0; i < 256; ++i) {
  224. c[0] = i;
  225. for (int j = 0; j < 256; ++j) {
  226. c[1] = j;
  227. tmp.clear();
  228. out.clear();
  229. uriEscape(in, tmp);
  230. expectPrintable(tmp);
  231. uriUnescape(tmp, out);
  232. EXPECT_EQ(in, out);
  233. }
  234. }
  235. }
  236. namespace {
  237. bool isHex(int v) {
  238. return (
  239. (v >= '0' && v <= '9') || (v >= 'A' && v <= 'F') ||
  240. (v >= 'a' && v <= 'f'));
  241. }
  242. } // namespace
  243. TEST(Escape, uriUnescapePercentDecoding) {
  244. char c[4] = {'%', '\0', '\0', '\0'};
  245. StringPiece in(c, 3);
  246. fbstring out;
  247. unsigned int expected = 0;
  248. for (int i = 0; i < 256; ++i) {
  249. c[1] = i;
  250. for (int j = 0; j < 256; ++j) {
  251. c[2] = j;
  252. if (isHex(i) && isHex(j)) {
  253. out.clear();
  254. uriUnescape(in, out);
  255. EXPECT_EQ(1, out.size());
  256. EXPECT_EQ(1, sscanf(c + 1, "%x", &expected));
  257. unsigned char v = out[0];
  258. EXPECT_EQ(expected, v);
  259. } else {
  260. EXPECT_THROW({ uriUnescape(in, out); }, std::invalid_argument);
  261. }
  262. }
  263. }
  264. }
  265. namespace {
  266. double pow2(int exponent) {
  267. return double(int64_t(1) << exponent);
  268. }
  269. } // namespace
  270. struct PrettyTestCase {
  271. std::string prettyString;
  272. double realValue;
  273. PrettyType prettyType;
  274. };
  275. PrettyTestCase prettyTestCases[] = {
  276. {string("853 ms"), 85.3e-2, PRETTY_TIME_HMS},
  277. {string("8.53 s "), 85.3e-1, PRETTY_TIME_HMS},
  278. {string("1.422 m "), 85.3, PRETTY_TIME_HMS},
  279. {string("14.22 m "), 85.3e1, PRETTY_TIME_HMS},
  280. {string("2.369 h "), 85.3e2, PRETTY_TIME_HMS},
  281. {string("2.369e+04 h "), 85.3e6, PRETTY_TIME_HMS},
  282. {string("8.53e+07 s "), 85.3e6, PRETTY_TIME},
  283. {string("8.53e+07 s "), 85.3e6, PRETTY_TIME},
  284. {string("85.3 ms"), 85.3e-3, PRETTY_TIME},
  285. {string("85.3 us"), 85.3e-6, PRETTY_TIME},
  286. {string("85.3 ns"), 85.3e-9, PRETTY_TIME},
  287. {string("85.3 ps"), 85.3e-12, PRETTY_TIME},
  288. {string("8.53e-14 s "), 85.3e-15, PRETTY_TIME},
  289. {string("0 s "), 0, PRETTY_TIME},
  290. {string("1 s "), 1.0, PRETTY_TIME},
  291. {string("1 ms"), 1.0e-3, PRETTY_TIME},
  292. {string("1 us"), 1.0e-6, PRETTY_TIME},
  293. {string("1 ns"), 1.0e-9, PRETTY_TIME},
  294. {string("1 ps"), 1.0e-12, PRETTY_TIME},
  295. // check bytes printing
  296. {string("853 B "), 853., PRETTY_BYTES},
  297. {string("833 kB"), 853.e3, PRETTY_BYTES},
  298. {string("813.5 MB"), 853.e6, PRETTY_BYTES},
  299. {string("7.944 GB"), 8.53e9, PRETTY_BYTES},
  300. {string("794.4 GB"), 853.e9, PRETTY_BYTES},
  301. {string("775.8 TB"), 853.e12, PRETTY_BYTES},
  302. {string("0 B "), 0, PRETTY_BYTES},
  303. {string("1 B "), pow2(0), PRETTY_BYTES},
  304. {string("1 kB"), pow2(10), PRETTY_BYTES},
  305. {string("1 MB"), pow2(20), PRETTY_BYTES},
  306. {string("1 GB"), pow2(30), PRETTY_BYTES},
  307. {string("1 TB"), pow2(40), PRETTY_BYTES},
  308. {string("1 PB"), pow2(50), PRETTY_BYTES},
  309. {string("1 EB"), pow2(60), PRETTY_BYTES},
  310. {string("853 B "), 853., PRETTY_BYTES_IEC},
  311. {string("833 KiB"), 853.e3, PRETTY_BYTES_IEC},
  312. {string("813.5 MiB"), 853.e6, PRETTY_BYTES_IEC},
  313. {string("7.944 GiB"), 8.53e9, PRETTY_BYTES_IEC},
  314. {string("794.4 GiB"), 853.e9, PRETTY_BYTES_IEC},
  315. {string("775.8 TiB"), 853.e12, PRETTY_BYTES_IEC},
  316. {string("1.776 PiB"), 2e15, PRETTY_BYTES_IEC},
  317. {string("1.735 EiB"), 2e18, PRETTY_BYTES_IEC},
  318. {string("0 B "), 0, PRETTY_BYTES_IEC},
  319. {string("1 B "), pow2(0), PRETTY_BYTES_IEC},
  320. {string("1 KiB"), pow2(10), PRETTY_BYTES_IEC},
  321. {string("1 MiB"), pow2(20), PRETTY_BYTES_IEC},
  322. {string("1 GiB"), pow2(30), PRETTY_BYTES_IEC},
  323. {string("1 TiB"), pow2(40), PRETTY_BYTES_IEC},
  324. {string("1 PiB"), pow2(50), PRETTY_BYTES_IEC},
  325. {string("1 EiB"), pow2(60), PRETTY_BYTES_IEC},
  326. // check bytes metric printing
  327. {string("853 B "), 853., PRETTY_BYTES_METRIC},
  328. {string("853 kB"), 853.e3, PRETTY_BYTES_METRIC},
  329. {string("853 MB"), 853.e6, PRETTY_BYTES_METRIC},
  330. {string("8.53 GB"), 8.53e9, PRETTY_BYTES_METRIC},
  331. {string("853 GB"), 853.e9, PRETTY_BYTES_METRIC},
  332. {string("853 TB"), 853.e12, PRETTY_BYTES_METRIC},
  333. {string("0 B "), 0, PRETTY_BYTES_METRIC},
  334. {string("1 B "), 1.0, PRETTY_BYTES_METRIC},
  335. {string("1 kB"), 1.0e+3, PRETTY_BYTES_METRIC},
  336. {string("1 MB"), 1.0e+6, PRETTY_BYTES_METRIC},
  337. {string("1 GB"), 1.0e+9, PRETTY_BYTES_METRIC},
  338. {string("1 TB"), 1.0e+12, PRETTY_BYTES_METRIC},
  339. {string("1 PB"), 1.0e+15, PRETTY_BYTES_METRIC},
  340. {string("1 EB"), 1.0e+18, PRETTY_BYTES_METRIC},
  341. // check metric-units (powers of 1000) printing
  342. {string("853 "), 853., PRETTY_UNITS_METRIC},
  343. {string("853 k"), 853.e3, PRETTY_UNITS_METRIC},
  344. {string("853 M"), 853.e6, PRETTY_UNITS_METRIC},
  345. {string("8.53 bil"), 8.53e9, PRETTY_UNITS_METRIC},
  346. {string("853 bil"), 853.e9, PRETTY_UNITS_METRIC},
  347. {string("853 tril"), 853.e12, PRETTY_UNITS_METRIC},
  348. // check binary-units (powers of 1024) printing
  349. {string("0 "), 0, PRETTY_UNITS_BINARY},
  350. {string("1 "), pow2(0), PRETTY_UNITS_BINARY},
  351. {string("1 k"), pow2(10), PRETTY_UNITS_BINARY},
  352. {string("1 M"), pow2(20), PRETTY_UNITS_BINARY},
  353. {string("1 G"), pow2(30), PRETTY_UNITS_BINARY},
  354. {string("1 T"), pow2(40), PRETTY_UNITS_BINARY},
  355. {string("1023 "), pow2(10) - 1, PRETTY_UNITS_BINARY},
  356. {string("1024 k"), pow2(20) - 1, PRETTY_UNITS_BINARY},
  357. {string("1024 M"), pow2(30) - 1, PRETTY_UNITS_BINARY},
  358. {string("1024 G"), pow2(40) - 1, PRETTY_UNITS_BINARY},
  359. {string("0 "), 0, PRETTY_UNITS_BINARY_IEC},
  360. {string("1 "), pow2(0), PRETTY_UNITS_BINARY_IEC},
  361. {string("1 Ki"), pow2(10), PRETTY_UNITS_BINARY_IEC},
  362. {string("1 Mi"), pow2(20), PRETTY_UNITS_BINARY_IEC},
  363. {string("1 Gi"), pow2(30), PRETTY_UNITS_BINARY_IEC},
  364. {string("1 Ti"), pow2(40), PRETTY_UNITS_BINARY_IEC},
  365. {string("1023 "), pow2(10) - 1, PRETTY_UNITS_BINARY_IEC},
  366. {string("1024 Ki"), pow2(20) - 1, PRETTY_UNITS_BINARY_IEC},
  367. {string("1024 Mi"), pow2(30) - 1, PRETTY_UNITS_BINARY_IEC},
  368. {string("1024 Gi"), pow2(40) - 1, PRETTY_UNITS_BINARY_IEC},
  369. // check border SI cases
  370. {string("1 Y"), 1e24, PRETTY_SI},
  371. {string("10 Y"), 1e25, PRETTY_SI},
  372. {string("1 y"), 1e-24, PRETTY_SI},
  373. {string("10 y"), 1e-23, PRETTY_SI},
  374. // check that negative values work
  375. {string("-85.3 s "), -85.3, PRETTY_TIME},
  376. {string("-85.3 ms"), -85.3e-3, PRETTY_TIME},
  377. {string("-85.3 us"), -85.3e-6, PRETTY_TIME},
  378. {string("-85.3 ns"), -85.3e-9, PRETTY_TIME},
  379. // end of test
  380. {string("endoftest"), 0, PRETTY_NUM_TYPES},
  381. };
  382. TEST(PrettyPrint, Basic) {
  383. for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i) {
  384. const PrettyTestCase& prettyTest = prettyTestCases[i];
  385. EXPECT_EQ(
  386. prettyTest.prettyString,
  387. prettyPrint(prettyTest.realValue, prettyTest.prettyType));
  388. }
  389. }
  390. TEST(PrettyToDouble, Basic) {
  391. // check manually created tests
  392. for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i) {
  393. PrettyTestCase testCase = prettyTestCases[i];
  394. PrettyType formatType = testCase.prettyType;
  395. double x = testCase.realValue;
  396. std::string testString = testCase.prettyString;
  397. double recoveredX = 0;
  398. try {
  399. recoveredX = prettyToDouble(testString, formatType);
  400. } catch (const std::exception& ex) {
  401. ADD_FAILURE() << testCase.prettyString << " -> " << ex.what();
  402. }
  403. double relativeError =
  404. fabs(x) < 1e-5 ? (x - recoveredX) : (x - recoveredX) / x;
  405. EXPECT_NEAR(0, relativeError, 1e-3);
  406. }
  407. // checks for compatibility with prettyPrint over the whole parameter space
  408. for (int i = 0; i < PRETTY_NUM_TYPES; ++i) {
  409. PrettyType formatType = static_cast<PrettyType>(i);
  410. for (double x = 1e-18; x < 1e40; x *= 1.9) {
  411. bool addSpace = static_cast<PrettyType>(i) == PRETTY_SI;
  412. for (int it = 0; it < 2; ++it, addSpace = true) {
  413. double recoveredX = 0;
  414. try {
  415. recoveredX =
  416. prettyToDouble(prettyPrint(x, formatType, addSpace), formatType);
  417. } catch (const std::exception& ex) {
  418. ADD_FAILURE() << folly::exceptionStr(ex);
  419. }
  420. double relativeError = (x - recoveredX) / x;
  421. EXPECT_NEAR(0, relativeError, 1e-3);
  422. }
  423. }
  424. }
  425. // check for incorrect values
  426. EXPECT_THROW(prettyToDouble("10Mx", PRETTY_SI), std::range_error);
  427. EXPECT_THROW(prettyToDouble("10 Mx", PRETTY_SI), std::range_error);
  428. EXPECT_THROW(prettyToDouble("10 M x", PRETTY_SI), std::range_error);
  429. StringPiece testString = "10Mx";
  430. EXPECT_DOUBLE_EQ(prettyToDouble(&testString, PRETTY_UNITS_METRIC), 10e6);
  431. EXPECT_EQ(testString, "x");
  432. }
  433. TEST(PrettyPrint, HexDump) {
  434. std::string a("abc\x00\x02\xa0", 6); // embedded NUL
  435. EXPECT_EQ(
  436. "00000000 61 62 63 00 02 a0 "
  437. "|abc... |\n",
  438. hexDump(a.data(), a.size()));
  439. a = "abcdefghijklmnopqrstuvwxyz";
  440. EXPECT_EQ(
  441. "00000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 "
  442. "|abcdefghijklmnop|\n"
  443. "00000010 71 72 73 74 75 76 77 78 79 7a "
  444. "|qrstuvwxyz |\n",
  445. hexDump(a.data(), a.size()));
  446. }
  447. TEST(System, errnoStr) {
  448. errno = EACCES;
  449. EXPECT_EQ(EACCES, errno);
  450. EXPECT_EQ(EACCES, errno); // twice to make sure EXPECT_EQ doesn't change it
  451. fbstring expected = strerror(ENOENT);
  452. errno = EACCES;
  453. EXPECT_EQ(expected, errnoStr(ENOENT));
  454. // Ensure that errno isn't changed
  455. EXPECT_EQ(EACCES, errno);
  456. // Per POSIX, all errno values are positive, so -1 is invalid
  457. errnoStr(-1);
  458. // Ensure that errno isn't changed
  459. EXPECT_EQ(EACCES, errno);
  460. }
  461. namespace {
  462. template <template <class, class> class VectorType>
  463. void splitTest() {
  464. VectorType<string, std::allocator<string>> parts;
  465. folly::split(',', "a,b,c", parts);
  466. EXPECT_EQ(parts.size(), 3);
  467. EXPECT_EQ(parts[0], "a");
  468. EXPECT_EQ(parts[1], "b");
  469. EXPECT_EQ(parts[2], "c");
  470. parts.clear();
  471. folly::split(',', StringPiece("a,b,c"), parts);
  472. EXPECT_EQ(parts.size(), 3);
  473. EXPECT_EQ(parts[0], "a");
  474. EXPECT_EQ(parts[1], "b");
  475. EXPECT_EQ(parts[2], "c");
  476. parts.clear();
  477. folly::split(',', string("a,b,c"), parts);
  478. EXPECT_EQ(parts.size(), 3);
  479. EXPECT_EQ(parts[0], "a");
  480. EXPECT_EQ(parts[1], "b");
  481. EXPECT_EQ(parts[2], "c");
  482. parts.clear();
  483. folly::split(',', "a,,c", parts);
  484. EXPECT_EQ(parts.size(), 3);
  485. EXPECT_EQ(parts[0], "a");
  486. EXPECT_EQ(parts[1], "");
  487. EXPECT_EQ(parts[2], "c");
  488. parts.clear();
  489. folly::split(',', string("a,,c"), parts);
  490. EXPECT_EQ(parts.size(), 3);
  491. EXPECT_EQ(parts[0], "a");
  492. EXPECT_EQ(parts[1], "");
  493. EXPECT_EQ(parts[2], "c");
  494. parts.clear();
  495. folly::split(',', "a,,c", parts, true);
  496. EXPECT_EQ(parts.size(), 2);
  497. EXPECT_EQ(parts[0], "a");
  498. EXPECT_EQ(parts[1], "c");
  499. parts.clear();
  500. folly::split(',', string("a,,c"), parts, true);
  501. EXPECT_EQ(parts.size(), 2);
  502. EXPECT_EQ(parts[0], "a");
  503. EXPECT_EQ(parts[1], "c");
  504. parts.clear();
  505. folly::split(',', string(",,a,,c,,,"), parts, true);
  506. EXPECT_EQ(parts.size(), 2);
  507. EXPECT_EQ(parts[0], "a");
  508. EXPECT_EQ(parts[1], "c");
  509. parts.clear();
  510. // test multiple split w/o clear
  511. folly::split(',', ",,a,,c,,,", parts, true);
  512. EXPECT_EQ(parts.size(), 2);
  513. EXPECT_EQ(parts[0], "a");
  514. EXPECT_EQ(parts[1], "c");
  515. folly::split(',', ",,a,,c,,,", parts, true);
  516. EXPECT_EQ(parts.size(), 4);
  517. EXPECT_EQ(parts[2], "a");
  518. EXPECT_EQ(parts[3], "c");
  519. parts.clear();
  520. // test splits that with multi-line delimiter
  521. folly::split("ab", "dabcabkdbkab", parts, true);
  522. EXPECT_EQ(parts.size(), 3);
  523. EXPECT_EQ(parts[0], "d");
  524. EXPECT_EQ(parts[1], "c");
  525. EXPECT_EQ(parts[2], "kdbk");
  526. parts.clear();
  527. // test last part is shorter than the delimiter
  528. folly::split("bc", "abcd", parts, true);
  529. EXPECT_EQ(parts.size(), 2);
  530. EXPECT_EQ(parts[0], "a");
  531. EXPECT_EQ(parts[1], "d");
  532. parts.clear();
  533. string orig = "ab2342asdfv~~!";
  534. folly::split("", orig, parts, true);
  535. EXPECT_EQ(parts.size(), 1);
  536. EXPECT_EQ(parts[0], orig);
  537. parts.clear();
  538. folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
  539. EXPECT_EQ(parts.size(), 1);
  540. EXPECT_EQ(parts[0], "asfds");
  541. parts.clear();
  542. folly::split("a", "", parts, true);
  543. EXPECT_EQ(parts.size(), 0);
  544. parts.clear();
  545. folly::split("a", "", parts);
  546. EXPECT_EQ(parts.size(), 1);
  547. EXPECT_EQ(parts[0], "");
  548. parts.clear();
  549. folly::split("a", StringPiece(), parts, true);
  550. EXPECT_EQ(parts.size(), 0);
  551. parts.clear();
  552. folly::split("a", StringPiece(), parts);
  553. EXPECT_EQ(parts.size(), 1);
  554. EXPECT_EQ(parts[0], "");
  555. parts.clear();
  556. folly::split("a", "abcdefg", parts, true);
  557. EXPECT_EQ(parts.size(), 1);
  558. EXPECT_EQ(parts[0], "bcdefg");
  559. parts.clear();
  560. orig = "All, , your base, are , , belong to us";
  561. folly::split(", ", orig, parts, true);
  562. EXPECT_EQ(parts.size(), 4);
  563. EXPECT_EQ(parts[0], "All");
  564. EXPECT_EQ(parts[1], "your base");
  565. EXPECT_EQ(parts[2], "are ");
  566. EXPECT_EQ(parts[3], "belong to us");
  567. parts.clear();
  568. folly::split(", ", orig, parts);
  569. EXPECT_EQ(parts.size(), 6);
  570. EXPECT_EQ(parts[0], "All");
  571. EXPECT_EQ(parts[1], "");
  572. EXPECT_EQ(parts[2], "your base");
  573. EXPECT_EQ(parts[3], "are ");
  574. EXPECT_EQ(parts[4], "");
  575. EXPECT_EQ(parts[5], "belong to us");
  576. parts.clear();
  577. orig = ", Facebook, rul,es!, ";
  578. folly::split(", ", orig, parts, true);
  579. EXPECT_EQ(parts.size(), 2);
  580. EXPECT_EQ(parts[0], "Facebook");
  581. EXPECT_EQ(parts[1], "rul,es!");
  582. parts.clear();
  583. folly::split(", ", orig, parts);
  584. EXPECT_EQ(parts.size(), 4);
  585. EXPECT_EQ(parts[0], "");
  586. EXPECT_EQ(parts[1], "Facebook");
  587. EXPECT_EQ(parts[2], "rul,es!");
  588. EXPECT_EQ(parts[3], "");
  589. }
  590. template <template <class, class> class VectorType>
  591. void piecesTest() {
  592. VectorType<StringPiece, std::allocator<StringPiece>> pieces;
  593. VectorType<StringPiece, std::allocator<StringPiece>> pieces2;
  594. folly::split(',', "a,b,c", pieces);
  595. EXPECT_EQ(pieces.size(), 3);
  596. EXPECT_EQ(pieces[0], "a");
  597. EXPECT_EQ(pieces[1], "b");
  598. EXPECT_EQ(pieces[2], "c");
  599. pieces.clear();
  600. folly::split(',', "a,,c", pieces);
  601. EXPECT_EQ(pieces.size(), 3);
  602. EXPECT_EQ(pieces[0], "a");
  603. EXPECT_EQ(pieces[1], "");
  604. EXPECT_EQ(pieces[2], "c");
  605. pieces.clear();
  606. folly::split(',', "a,,c", pieces, true);
  607. EXPECT_EQ(pieces.size(), 2);
  608. EXPECT_EQ(pieces[0], "a");
  609. EXPECT_EQ(pieces[1], "c");
  610. pieces.clear();
  611. folly::split(',', ",,a,,c,,,", pieces, true);
  612. EXPECT_EQ(pieces.size(), 2);
  613. EXPECT_EQ(pieces[0], "a");
  614. EXPECT_EQ(pieces[1], "c");
  615. pieces.clear();
  616. // test multiple split w/o clear
  617. folly::split(',', ",,a,,c,,,", pieces, true);
  618. EXPECT_EQ(pieces.size(), 2);
  619. EXPECT_EQ(pieces[0], "a");
  620. EXPECT_EQ(pieces[1], "c");
  621. folly::split(',', ",,a,,c,,,", pieces, true);
  622. EXPECT_EQ(pieces.size(), 4);
  623. EXPECT_EQ(pieces[2], "a");
  624. EXPECT_EQ(pieces[3], "c");
  625. pieces.clear();
  626. // test multiple split rounds
  627. folly::split(",", "a_b,c_d", pieces);
  628. EXPECT_EQ(pieces.size(), 2);
  629. EXPECT_EQ(pieces[0], "a_b");
  630. EXPECT_EQ(pieces[1], "c_d");
  631. folly::split("_", pieces[0], pieces2);
  632. EXPECT_EQ(pieces2.size(), 2);
  633. EXPECT_EQ(pieces2[0], "a");
  634. EXPECT_EQ(pieces2[1], "b");
  635. pieces2.clear();
  636. folly::split("_", pieces[1], pieces2);
  637. EXPECT_EQ(pieces2.size(), 2);
  638. EXPECT_EQ(pieces2[0], "c");
  639. EXPECT_EQ(pieces2[1], "d");
  640. pieces.clear();
  641. pieces2.clear();
  642. // test splits that with multi-line delimiter
  643. folly::split("ab", "dabcabkdbkab", pieces, true);
  644. EXPECT_EQ(pieces.size(), 3);
  645. EXPECT_EQ(pieces[0], "d");
  646. EXPECT_EQ(pieces[1], "c");
  647. EXPECT_EQ(pieces[2], "kdbk");
  648. pieces.clear();
  649. string orig = "ab2342asdfv~~!";
  650. folly::split("", orig.c_str(), pieces, true);
  651. EXPECT_EQ(pieces.size(), 1);
  652. EXPECT_EQ(pieces[0], orig);
  653. pieces.clear();
  654. folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
  655. EXPECT_EQ(pieces.size(), 1);
  656. EXPECT_EQ(pieces[0], "asfds");
  657. pieces.clear();
  658. folly::split("a", "", pieces, true);
  659. EXPECT_EQ(pieces.size(), 0);
  660. pieces.clear();
  661. folly::split("a", "", pieces);
  662. EXPECT_EQ(pieces.size(), 1);
  663. EXPECT_EQ(pieces[0], "");
  664. pieces.clear();
  665. folly::split("a", "abcdefg", pieces, true);
  666. EXPECT_EQ(pieces.size(), 1);
  667. EXPECT_EQ(pieces[0], "bcdefg");
  668. pieces.clear();
  669. orig = "All, , your base, are , , belong to us";
  670. folly::split(", ", orig, pieces, true);
  671. EXPECT_EQ(pieces.size(), 4);
  672. EXPECT_EQ(pieces[0], "All");
  673. EXPECT_EQ(pieces[1], "your base");
  674. EXPECT_EQ(pieces[2], "are ");
  675. EXPECT_EQ(pieces[3], "belong to us");
  676. pieces.clear();
  677. folly::split(", ", orig, pieces);
  678. EXPECT_EQ(pieces.size(), 6);
  679. EXPECT_EQ(pieces[0], "All");
  680. EXPECT_EQ(pieces[1], "");
  681. EXPECT_EQ(pieces[2], "your base");
  682. EXPECT_EQ(pieces[3], "are ");
  683. EXPECT_EQ(pieces[4], "");
  684. EXPECT_EQ(pieces[5], "belong to us");
  685. pieces.clear();
  686. orig = ", Facebook, rul,es!, ";
  687. folly::split(", ", orig, pieces, true);
  688. EXPECT_EQ(pieces.size(), 2);
  689. EXPECT_EQ(pieces[0], "Facebook");
  690. EXPECT_EQ(pieces[1], "rul,es!");
  691. pieces.clear();
  692. folly::split(", ", orig, pieces);
  693. EXPECT_EQ(pieces.size(), 4);
  694. EXPECT_EQ(pieces[0], "");
  695. EXPECT_EQ(pieces[1], "Facebook");
  696. EXPECT_EQ(pieces[2], "rul,es!");
  697. EXPECT_EQ(pieces[3], "");
  698. pieces.clear();
  699. const char* str = "a,b";
  700. folly::split(',', StringPiece(str), pieces);
  701. EXPECT_EQ(pieces.size(), 2);
  702. EXPECT_EQ(pieces[0], "a");
  703. EXPECT_EQ(pieces[1], "b");
  704. EXPECT_EQ(pieces[0].start(), str);
  705. EXPECT_EQ(pieces[1].start(), str + 2);
  706. std::set<StringPiece> unique;
  707. folly::splitTo<StringPiece>(
  708. ":",
  709. "asd:bsd:asd:asd:bsd:csd::asd",
  710. std::inserter(unique, unique.begin()),
  711. true);
  712. EXPECT_EQ(unique.size(), 3);
  713. if (unique.size() == 3) {
  714. EXPECT_EQ(*unique.begin(), "asd");
  715. EXPECT_EQ(*--unique.end(), "csd");
  716. }
  717. VectorType<fbstring, std::allocator<fbstring>> blah;
  718. folly::split('-', "a-b-c-d-f-e", blah);
  719. EXPECT_EQ(blah.size(), 6);
  720. }
  721. } // namespace
  722. TEST(Split, split_vector) {
  723. splitTest<std::vector>();
  724. }
  725. TEST(Split, split_fbvector) {
  726. splitTest<folly::fbvector>();
  727. }
  728. TEST(Split, pieces_vector) {
  729. piecesTest<std::vector>();
  730. }
  731. TEST(Split, pieces_fbvector) {
  732. piecesTest<folly::fbvector>();
  733. }
  734. TEST(Split, fixed) {
  735. StringPiece a, b, c, d;
  736. EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
  737. EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
  738. EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
  739. EXPECT_TRUE(folly::split<false>('.', "a", a));
  740. EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
  741. EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
  742. EXPECT_TRUE(folly::split('.', "a.b", a, b));
  743. EXPECT_TRUE(folly::split('.', "a", a));
  744. EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
  745. EXPECT_EQ("a", a);
  746. EXPECT_EQ("b", b);
  747. EXPECT_EQ("c", c);
  748. EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
  749. EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
  750. EXPECT_EQ("a", a);
  751. EXPECT_EQ("b.c", b);
  752. EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
  753. EXPECT_EQ("a", a);
  754. EXPECT_EQ("b", b);
  755. EXPECT_EQ("c", c);
  756. EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
  757. EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
  758. EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
  759. EXPECT_EQ("a", a);
  760. EXPECT_EQ("b", b);
  761. EXPECT_FALSE(folly::split<false>('.', "a", a, b));
  762. EXPECT_TRUE(folly::split<false>('.', "a.b", a));
  763. EXPECT_EQ("a.b", a);
  764. EXPECT_TRUE(folly::split('.', "a.b", a, b));
  765. EXPECT_EQ("a", a);
  766. EXPECT_EQ("b", b);
  767. EXPECT_FALSE(folly::split('.', "a", a, b));
  768. EXPECT_FALSE(folly::split('.', "a.b", a));
  769. }
  770. TEST(Split, std_string_fixed) {
  771. std::string a, b, c, d;
  772. EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
  773. EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
  774. EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
  775. EXPECT_TRUE(folly::split<false>('.', "a", a));
  776. EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
  777. EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
  778. EXPECT_TRUE(folly::split('.', "a.b", a, b));
  779. EXPECT_TRUE(folly::split('.', "a", a));
  780. EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
  781. EXPECT_EQ("a", a);
  782. EXPECT_EQ("b", b);
  783. EXPECT_EQ("c", c);
  784. EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
  785. EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
  786. EXPECT_EQ("a", a);
  787. EXPECT_EQ("b.c", b);
  788. EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
  789. EXPECT_EQ("a", a);
  790. EXPECT_EQ("b", b);
  791. EXPECT_EQ("c", c);
  792. EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
  793. EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
  794. EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
  795. EXPECT_EQ("a", a);
  796. EXPECT_EQ("b", b);
  797. EXPECT_FALSE(folly::split<false>('.', "a", a, b));
  798. EXPECT_TRUE(folly::split<false>('.', "a.b", a));
  799. EXPECT_EQ("a.b", a);
  800. EXPECT_TRUE(folly::split('.', "a.b", a, b));
  801. EXPECT_EQ("a", a);
  802. EXPECT_EQ("b", b);
  803. EXPECT_FALSE(folly::split('.', "a", a, b));
  804. EXPECT_FALSE(folly::split('.', "a.b", a));
  805. }
  806. TEST(Split, fixed_convert) {
  807. StringPiece a, d;
  808. int b;
  809. double c = 0;
  810. EXPECT_TRUE(folly::split(':', "a:13:14.7:b", a, b, c, d));
  811. EXPECT_EQ("a", a);
  812. EXPECT_EQ(13, b);
  813. EXPECT_NEAR(14.7, c, 1e-10);
  814. EXPECT_EQ("b", d);
  815. EXPECT_TRUE(folly::split<false>(':', "b:14:15.3:c", a, b, c, d));
  816. EXPECT_EQ("b", a);
  817. EXPECT_EQ(14, b);
  818. EXPECT_NEAR(15.3, c, 1e-10);
  819. EXPECT_EQ("c", d);
  820. EXPECT_FALSE(folly::split(':', "a:13:14.7:b", a, b, d));
  821. EXPECT_TRUE(folly::split<false>(':', "a:13:14.7:b", a, b, d));
  822. EXPECT_EQ("a", a);
  823. EXPECT_EQ(13, b);
  824. EXPECT_EQ("14.7:b", d);
  825. // Enable verifying that a line only contains one field
  826. EXPECT_TRUE(folly::split(' ', "hello", a));
  827. EXPECT_FALSE(folly::split(' ', "hello world", a));
  828. // Test cases with std::ignore.
  829. EXPECT_TRUE(folly::split(':', "a:13:14.7:b", std::ignore, b, c, d));
  830. EXPECT_EQ(13, b);
  831. EXPECT_NEAR(14.7, c, 1e-10);
  832. EXPECT_EQ("b", d);
  833. EXPECT_TRUE(folly::split(':', "a:13:14.7:b", std::ignore, b, c, std::ignore));
  834. EXPECT_EQ(13, b);
  835. EXPECT_NEAR(14.7, c, 1e-10);
  836. EXPECT_TRUE(folly::split<false>(':', "a:13:14.7:b", a, b, std::ignore));
  837. EXPECT_EQ("a", a);
  838. EXPECT_EQ(13, b);
  839. }
  840. namespace my {
  841. enum class Color {
  842. Red,
  843. Blue,
  844. };
  845. enum class ColorErrorCode { INVALID_COLOR };
  846. struct ColorError : std::runtime_error {
  847. using std::runtime_error::runtime_error;
  848. };
  849. ColorError makeConversionError(ColorErrorCode, StringPiece sp) {
  850. return ColorError("Invalid my::Color representation : " + sp.str());
  851. }
  852. Expected<StringPiece, ColorErrorCode> parseTo(
  853. StringPiece in,
  854. Color& out) noexcept {
  855. if (in == "R") {
  856. out = Color::Red;
  857. } else if (in == "B") {
  858. out = Color::Blue;
  859. } else {
  860. return makeUnexpected(ColorErrorCode::INVALID_COLOR);
  861. }
  862. return StringPiece(in.end(), in.end());
  863. }
  864. } // namespace my
  865. TEST(Split, fixed_convert_custom) {
  866. my::Color c1, c2;
  867. EXPECT_TRUE(folly::split(',', "R,B", c1, c2));
  868. EXPECT_EQ(c1, my::Color::Red);
  869. EXPECT_EQ(c2, my::Color::Blue);
  870. EXPECT_THROW(folly::split(',', "B,G", c1, c2), my::ColorError);
  871. }
  872. TEST(String, join) {
  873. string output;
  874. std::vector<int> empty = {};
  875. join(":", empty, output);
  876. EXPECT_TRUE(output.empty());
  877. std::vector<std::string> input1 = {"1", "23", "456", ""};
  878. join(':', input1, output);
  879. EXPECT_EQ(output, "1:23:456:");
  880. output = join(':', input1);
  881. EXPECT_EQ(output, "1:23:456:");
  882. auto input2 = {1, 23, 456};
  883. join("-*-", input2, output);
  884. EXPECT_EQ(output, "1-*-23-*-456");
  885. output = join("-*-", input2);
  886. EXPECT_EQ(output, "1-*-23-*-456");
  887. auto input3 = {'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k'};
  888. join("", input3, output);
  889. EXPECT_EQ(output, "facebook");
  890. join("_", {"", "f", "a", "c", "e", "b", "o", "o", "k", ""}, output);
  891. EXPECT_EQ(output, "_f_a_c_e_b_o_o_k_");
  892. output = join("", input3.begin(), input3.end());
  893. EXPECT_EQ(output, "facebook");
  894. std::multiset<char> input4(input3);
  895. output = join("", input4);
  896. EXPECT_EQ("abcefkoo", output);
  897. output = join("", input4.begin(), input4.end());
  898. EXPECT_EQ("abcefkoo", output);
  899. }
  900. TEST(String, hexlify) {
  901. string input1 = "0123";
  902. string output1;
  903. EXPECT_TRUE(hexlify(input1, output1));
  904. EXPECT_EQ("30313233", output1);
  905. fbstring input2 = "abcdefg";
  906. input2[1] = 0;
  907. input2[3] = 0xff;
  908. input2[5] = 0xb6;
  909. fbstring output2;
  910. EXPECT_TRUE(hexlify(input2, output2));
  911. EXPECT_EQ("610063ff65b667", output2);
  912. EXPECT_EQ("666f6f626172", hexlify("foobar"));
  913. auto bytes = folly::make_array<uint8_t>(1, 2, 3, 4);
  914. EXPECT_EQ("01020304", hexlify(ByteRange{bytes.data(), bytes.size()}));
  915. }
  916. TEST(String, unhexlify) {
  917. string input1 = "30313233";
  918. string output1;
  919. EXPECT_TRUE(unhexlify(input1, output1));
  920. EXPECT_EQ(output1, "0123");
  921. fbstring input2 = "610063ff65b667";
  922. fbstring output2;
  923. EXPECT_TRUE(unhexlify(input2, output2));
  924. EXPECT_EQ(output2.size(), 7);
  925. EXPECT_EQ(output2[0], 'a');
  926. EXPECT_EQ(output2[1], 0);
  927. EXPECT_EQ(output2[2], 'c');
  928. EXPECT_EQ(output2[3] & 0xff, 0xff);
  929. EXPECT_EQ(output2[4], 'e');
  930. EXPECT_EQ(output2[5] & 0xff, 0xb6);
  931. EXPECT_EQ(output2[6], 'g');
  932. string input3 = "x";
  933. string output3;
  934. EXPECT_FALSE(unhexlify(input3, output3));
  935. string input4 = "xy";
  936. string output4;
  937. EXPECT_FALSE(unhexlify(input4, output4));
  938. EXPECT_EQ("foobar", unhexlify("666f6f626172"));
  939. EXPECT_EQ(StringPiece("foo\0bar", 7), unhexlify("666f6f00626172"));
  940. EXPECT_THROW(unhexlify("666f6fzz626172"), std::domain_error);
  941. }
  942. TEST(String, backslashify) {
  943. EXPECT_EQ("abc", string("abc"));
  944. EXPECT_EQ("abc", backslashify(string("abc")));
  945. EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
  946. EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
  947. EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
  948. StringPiece input1 = "abc\r";
  949. std::string output1 = backslashify(input1);
  950. EXPECT_EQ("abc\\r", output1);
  951. }
  952. TEST(String, humanify) {
  953. // Simple cases; output is obvious.
  954. EXPECT_EQ("abc", humanify(string("abc")));
  955. EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
  956. EXPECT_EQ("0xff", humanify(string("\xff")));
  957. EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
  958. EXPECT_EQ("abc\\b", humanify(string("abc\b")));
  959. EXPECT_EQ("0x00", humanify(string(1, '\0')));
  960. EXPECT_EQ("0x0000", humanify(string(2, '\0')));
  961. // Mostly printable, so backslash! 80, 60, and 40% printable, respectively
  962. EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
  963. EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
  964. EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
  965. // 20% printable, and the printable portion isn't the prefix; hexify!
  966. EXPECT_EQ(
  967. "0xff61ffffff",
  968. humanify(string("\xff"
  969. "a\xff\xff\xff")));
  970. // Same as previous, except swap first two chars; prefix is
  971. // printable and within the threshold, so backslashify.
  972. EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
  973. // Just too much unprintable; hex, despite prefix.
  974. EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
  975. }
  976. namespace {
  977. /**
  978. * Copy bytes from src to somewhere in the buffer referenced by dst. The
  979. * actual starting position of the copy will be the first address in the
  980. * destination buffer whose address mod 8 is equal to the src address mod 8.
  981. * The caller is responsible for ensuring that the destination buffer has
  982. * enough extra space to accommodate the shifted copy.
  983. */
  984. char* copyWithSameAlignment(char* dst, const char* src, size_t length) {
  985. const char* originalDst = dst;
  986. size_t dstOffset = size_t(dst) & 0x7;
  987. size_t srcOffset = size_t(src) & 0x7;
  988. while (dstOffset != srcOffset) {
  989. dst++;
  990. dstOffset++;
  991. dstOffset &= 0x7;
  992. }
  993. CHECK(dst <= originalDst + 7);
  994. CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7));
  995. memcpy(dst, src, length);
  996. return dst;
  997. }
  998. void testToLowerAscii(Range<const char*> src) {
  999. // Allocate extra space so we can make copies that start at the
  1000. // same alignment (byte, word, quadword, etc) as the source buffer.
  1001. auto controlBuf = std::vector<char>(src.size() + 7);
  1002. char* control =
  1003. copyWithSameAlignment(controlBuf.data(), src.begin(), src.size());
  1004. auto testBuf = std::vector<char>(src.size() + 7);
  1005. char* test = copyWithSameAlignment(testBuf.data(), src.begin(), src.size());
  1006. for (size_t i = 0; i < src.size(); i++) {
  1007. control[i] = tolower(control[i]);
  1008. }
  1009. toLowerAscii(test, src.size());
  1010. for (size_t i = 0; i < src.size(); i++) {
  1011. EXPECT_EQ(control[i], test[i]);
  1012. }
  1013. }
  1014. } // namespace
  1015. TEST(String, toLowerAsciiAligned) {
  1016. static const size_t kSize = 256;
  1017. char input[kSize];
  1018. for (size_t i = 0; i < kSize; i++) {
  1019. input[i] = (char)(i & 0xff);
  1020. }
  1021. testToLowerAscii(Range<const char*>(input, kSize));
  1022. }
  1023. TEST(String, toLowerAsciiUnaligned) {
  1024. static const size_t kSize = 256;
  1025. char input[kSize];
  1026. for (size_t i = 0; i < kSize; i++) {
  1027. input[i] = (char)(i & 0xff);
  1028. }
  1029. // Test input buffers of several lengths to exercise all the
  1030. // cases: buffer at the start/middle/end of an aligned block, plus
  1031. // buffers that span multiple aligned blocks. The longest test input
  1032. // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned
  1033. // + 4 32-bit aligned + 3 unaligned = 22 bytes.
  1034. for (size_t length = 1; length < 23; length++) {
  1035. for (size_t offset = 0; offset + length <= kSize; offset++) {
  1036. testToLowerAscii(Range<const char*>(input + offset, length));
  1037. }
  1038. }
  1039. }
  1040. TEST(String, whitespace) {
  1041. // trimWhitespace:
  1042. EXPECT_EQ("kavabanga", trimWhitespace("kavabanga"));
  1043. EXPECT_EQ("kavabanga", trimWhitespace("kavabanga \t \n "));
  1044. EXPECT_EQ("kavabanga", trimWhitespace(" \t \r \n \n kavabanga"));
  1045. EXPECT_EQ("kavabanga", trimWhitespace("\t \r \n kavabanga \t \n "));
  1046. EXPECT_EQ("kavabanga", trimWhitespace(" \t \r \n \n kavabanga"));
  1047. EXPECT_EQ("kavabanga", trimWhitespace("\t \r \n kavabanga \t \n "));
  1048. EXPECT_EQ(
  1049. ltrimWhitespace(rtrimWhitespace("kavabanga")),
  1050. rtrimWhitespace(ltrimWhitespace("kavabanga")));
  1051. EXPECT_EQ(
  1052. ltrimWhitespace(rtrimWhitespace("kavabanga \r\t\n")),
  1053. rtrimWhitespace(ltrimWhitespace("kavabanga \r\t\n")));
  1054. EXPECT_EQ("", trimWhitespace("\t \r \n \t \n "));
  1055. EXPECT_EQ("", trimWhitespace(""));
  1056. EXPECT_EQ("", trimWhitespace("\t"));
  1057. EXPECT_EQ("", trimWhitespace("\r"));
  1058. EXPECT_EQ("", trimWhitespace("\n"));
  1059. EXPECT_EQ("", trimWhitespace("\t "));
  1060. EXPECT_EQ("", trimWhitespace("\r "));
  1061. EXPECT_EQ("", trimWhitespace("\n "));
  1062. EXPECT_EQ("", trimWhitespace(" \t"));
  1063. EXPECT_EQ("", trimWhitespace(" \r"));
  1064. EXPECT_EQ("", trimWhitespace(" \n"));
  1065. // ltrimWhitespace:
  1066. EXPECT_EQ("kavabanga", ltrimWhitespace("\t kavabanga"));
  1067. EXPECT_EQ("kavabanga \r\n", ltrimWhitespace("\t kavabanga \r\n"));
  1068. EXPECT_EQ("", ltrimWhitespace("\r "));
  1069. EXPECT_EQ("", ltrimWhitespace("\n "));
  1070. EXPECT_EQ("", ltrimWhitespace("\r "));
  1071. // rtrimWhitespace:
  1072. EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga"));
  1073. EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga \r\n"));
  1074. EXPECT_EQ("", rtrimWhitespace("\r "));
  1075. EXPECT_EQ("", rtrimWhitespace("\n "));
  1076. EXPECT_EQ("", rtrimWhitespace("\r "));
  1077. }
  1078. TEST(String, stripLeftMargin_really_empty) {
  1079. auto input = "";
  1080. auto expected = "";
  1081. EXPECT_EQ(expected, stripLeftMargin(input));
  1082. }
  1083. TEST(String, stripLeftMargin_empty) {
  1084. auto input = R"TEXT(
  1085. )TEXT";
  1086. auto expected = "";
  1087. EXPECT_EQ(expected, stripLeftMargin(input));
  1088. }
  1089. TEST(String, stripLeftMargin_only_whitespace) {
  1090. // using ~ as a marker
  1091. string input = R"TEXT(
  1092. ~
  1093. )TEXT";
  1094. input = boost::regex_replace(input, boost::regex("~"), "");
  1095. EXPECT_EQ("\n \n ", input);
  1096. auto expected = "\n";
  1097. EXPECT_EQ(expected, stripLeftMargin(input));
  1098. }
  1099. TEST(String, stripLeftMargin_only_uneven_whitespace) {
  1100. // using ~ as a marker1
  1101. string input = R"TEXT(
  1102. ~
  1103. ~
  1104. )TEXT";
  1105. input = boost::regex_replace(input, boost::regex("~"), "");
  1106. EXPECT_EQ("\n \n \n ", input);
  1107. auto expected = "\n\n";
  1108. EXPECT_EQ(expected, stripLeftMargin(input));
  1109. }
  1110. TEST(String, stripLeftMargin_one_line) {
  1111. auto input = R"TEXT(
  1112. hi there bob!
  1113. )TEXT";
  1114. auto expected = "hi there bob!\n";
  1115. EXPECT_EQ(expected, stripLeftMargin(input));
  1116. }
  1117. TEST(String, stripLeftMargin_two_lines) {
  1118. auto input = R"TEXT(
  1119. hi there bob!
  1120. nice weather today!
  1121. )TEXT";
  1122. auto expected = "hi there bob!\nnice weather today!\n";
  1123. EXPECT_EQ(expected, stripLeftMargin(input));
  1124. }
  1125. TEST(String, stripLeftMargin_three_lines_uneven) {
  1126. auto input = R"TEXT(
  1127. hi there bob!
  1128. nice weather today!
  1129. so long!
  1130. )TEXT";
  1131. auto expected = " hi there bob!\nnice weather today!\n so long!\n";
  1132. EXPECT_EQ(expected, stripLeftMargin(input));
  1133. }
  1134. TEST(String, stripLeftMargin_preceding_blank_lines) {
  1135. auto input = R"TEXT(
  1136. hi there bob!
  1137. )TEXT";
  1138. auto expected = "\n\nhi there bob!\n";
  1139. EXPECT_EQ(expected, stripLeftMargin(input));
  1140. }
  1141. TEST(String, stripLeftMargin_succeeding_blank_lines) {
  1142. auto input = R"TEXT(
  1143. hi there bob!
  1144. )TEXT";
  1145. auto expected = "hi there bob!\n\n\n";
  1146. EXPECT_EQ(expected, stripLeftMargin(input));
  1147. }
  1148. TEST(String, stripLeftMargin_interstitial_undented_whiteline) {
  1149. // using ~ as a marker
  1150. string input = R"TEXT(
  1151. hi there bob!
  1152. ~
  1153. so long!
  1154. )TEXT";
  1155. input = boost::regex_replace(input, boost::regex(" +~"), "");
  1156. EXPECT_EQ("\n hi there bob!\n\n so long!\n ", input);
  1157. auto expected = "hi there bob!\n\nso long!\n";
  1158. EXPECT_EQ(expected, stripLeftMargin(input));
  1159. }
  1160. TEST(String, stripLeftMargin_interstitial_dedented_whiteline) {
  1161. // using ~ as a marker
  1162. string input = R"TEXT(
  1163. hi there bob!
  1164. ~
  1165. so long!
  1166. )TEXT";
  1167. input = boost::regex_replace(input, boost::regex("~"), "");
  1168. EXPECT_EQ("\n hi there bob!\n \n so long!\n ", input);
  1169. auto expected = "hi there bob!\n\nso long!\n";
  1170. EXPECT_EQ(expected, stripLeftMargin(input));
  1171. }
  1172. TEST(String, stripLeftMargin_interstitial_equidented_whiteline) {
  1173. // using ~ as a marker
  1174. string input = R"TEXT(
  1175. hi there bob!
  1176. ~
  1177. so long!
  1178. )TEXT";
  1179. input = boost::regex_replace(input, boost::regex("~"), "");
  1180. EXPECT_EQ("\n hi there bob!\n \n so long!\n ", input);
  1181. auto expected = "hi there bob!\n\nso long!\n";
  1182. EXPECT_EQ(expected, stripLeftMargin(input));
  1183. }
  1184. TEST(String, stripLeftMargin_interstitial_indented_whiteline) {
  1185. // using ~ as a marker
  1186. string input = R"TEXT(
  1187. hi there bob!
  1188. ~
  1189. so long!
  1190. )TEXT";
  1191. input = boost::regex_replace(input, boost::regex("~"), "");
  1192. EXPECT_EQ("\n hi there bob!\n \n so long!\n ", input);
  1193. auto expected = "hi there bob!\n \nso long!\n";
  1194. EXPECT_EQ(expected, stripLeftMargin(input));
  1195. }
  1196. TEST(String, stripLeftMargin_no_pre_whitespace) {
  1197. // using ~ as a marker
  1198. string input = R"TEXT( hi there bob!
  1199. ~
  1200. so long!
  1201. )TEXT";
  1202. input = boost::regex_replace(input, boost::regex("~"), "");
  1203. EXPECT_EQ(" hi there bob!\n \n so long!\n ", input);
  1204. auto expected = "hi there bob!\n \nso long!\n";
  1205. EXPECT_EQ(expected, stripLeftMargin(input));
  1206. }
  1207. TEST(String, stripLeftMargin_no_post_whitespace) {
  1208. // using ~ as a marker
  1209. string input = R"TEXT(
  1210. hi there bob!
  1211. ~
  1212. so long! )TEXT";
  1213. input = boost::regex_replace(input, boost::regex("~"), "");
  1214. EXPECT_EQ("\n hi there bob!\n \n so long! ", input);
  1215. auto expected = "hi there bob!\n \nso long! ";
  1216. EXPECT_EQ(expected, stripLeftMargin(input));
  1217. }