strbuf_ut.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #include "strbuf.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <string_view>
  4. Y_UNIT_TEST_SUITE(TStrBufTest) {
  5. Y_UNIT_TEST(TestConstructorsAndOperators) {
  6. TStringBuf str("qwerty");
  7. UNIT_ASSERT_EQUAL(*str.data(), 'q');
  8. UNIT_ASSERT_EQUAL(str.size(), 6);
  9. TStringBuf str1("qwe\0rty"sv);
  10. TStringBuf str2(str1.data());
  11. UNIT_ASSERT_VALUES_UNEQUAL(str1, str2);
  12. UNIT_ASSERT_VALUES_EQUAL(str1.size(), 7);
  13. UNIT_ASSERT_VALUES_EQUAL(str2.size(), 3);
  14. std::string_view helloWorld("Hello, World!");
  15. TStringBuf fromStringView(helloWorld);
  16. UNIT_ASSERT_EQUAL(fromStringView.data(), helloWorld.data());
  17. UNIT_ASSERT_EQUAL(fromStringView.size(), helloWorld.size());
  18. std::string_view fromStringBuf = fromStringView;
  19. UNIT_ASSERT_EQUAL(helloWorld.data(), fromStringBuf.data());
  20. UNIT_ASSERT_EQUAL(helloWorld.size(), fromStringBuf.size());
  21. }
  22. Y_UNIT_TEST(TestConstExpr) {
  23. static constexpr TStringBuf str1("qwe\0rty", 7);
  24. static constexpr TStringBuf str2(str1.data(), str1.size());
  25. static constexpr TStringBuf str3 = "qwe\0rty"sv;
  26. UNIT_ASSERT_VALUES_EQUAL(str1.size(), 7);
  27. UNIT_ASSERT_VALUES_EQUAL(str1, str2);
  28. UNIT_ASSERT_VALUES_EQUAL(str2, str3);
  29. UNIT_ASSERT_VALUES_EQUAL(str1, str3);
  30. static constexpr std::string_view view1(str1);
  31. UNIT_ASSERT_VALUES_EQUAL(str1, view1);
  32. static_assert(str1.data() == view1.data());
  33. static_assert(str1.size() == view1.size());
  34. static constexpr TStringBuf str4(view1);
  35. UNIT_ASSERT_VALUES_EQUAL(str1, str4);
  36. static_assert(str1.data() == str4.data());
  37. static_assert(str1.size() == str4.size());
  38. }
  39. Y_UNIT_TEST(TestConstExprComparison) {
  40. static constexpr TStringBuf str1("qwe\0rty"sv);
  41. static constexpr TStringBuf str2("qw");
  42. static_assert(str1 != str2);
  43. static_assert(str1 >= str2);
  44. static_assert(str1.StartsWith(str2));
  45. static_assert(!str1.EndsWith(str2));
  46. }
  47. Y_UNIT_TEST(TestAfter) {
  48. TStringBuf str("qwerty");
  49. UNIT_ASSERT_VALUES_EQUAL(str.After('w'), TStringBuf("erty"));
  50. UNIT_ASSERT_VALUES_EQUAL(str.After('x'), TStringBuf("qwerty"));
  51. UNIT_ASSERT_VALUES_EQUAL(str.After('y'), TStringBuf());
  52. UNIT_ASSERT_STRINGS_EQUAL(str.After('='), str);
  53. // Also works properly on empty strings
  54. TStringBuf empty;
  55. UNIT_ASSERT_STRINGS_EQUAL(empty.After('x'), empty);
  56. }
  57. Y_UNIT_TEST(TestBefore) {
  58. TStringBuf str("qwerty");
  59. UNIT_ASSERT_VALUES_EQUAL(str.Before('w'), TStringBuf("q"));
  60. UNIT_ASSERT_VALUES_EQUAL(str.Before('x'), TStringBuf("qwerty"));
  61. UNIT_ASSERT_VALUES_EQUAL(str.Before('y'), TStringBuf("qwert"));
  62. UNIT_ASSERT_VALUES_EQUAL(str.Before('q'), TStringBuf());
  63. }
  64. Y_UNIT_TEST(TestRAfterBefore) {
  65. TStringBuf str("a/b/c");
  66. UNIT_ASSERT_STRINGS_EQUAL(str.RAfter('/'), "c");
  67. UNIT_ASSERT_STRINGS_EQUAL(str.RAfter('_'), str);
  68. UNIT_ASSERT_STRINGS_EQUAL(str.RAfter('a'), "/b/c");
  69. UNIT_ASSERT_STRINGS_EQUAL(str.RBefore('/'), "a/b");
  70. UNIT_ASSERT_STRINGS_EQUAL(str.RBefore('_'), str);
  71. UNIT_ASSERT_STRINGS_EQUAL(str.RBefore('a'), "");
  72. }
  73. Y_UNIT_TEST(TestAfterPrefix) {
  74. TStringBuf str("cat_dog");
  75. TStringBuf r = "the_same";
  76. UNIT_ASSERT(!str.AfterPrefix("dog", r));
  77. UNIT_ASSERT_EQUAL(r, "the_same");
  78. UNIT_ASSERT(str.AfterPrefix("cat_", r));
  79. UNIT_ASSERT_EQUAL(r, "dog");
  80. // example:
  81. str = "http://ya.ru";
  82. if (str.AfterPrefix("http://", r)) {
  83. UNIT_ASSERT_EQUAL(r, "ya.ru");
  84. }
  85. // SkipPrefix()
  86. TStringBuf a = "abcdef";
  87. UNIT_ASSERT(a.SkipPrefix("a") && a == "bcdef");
  88. UNIT_ASSERT(a.SkipPrefix("bc") && a == "def");
  89. UNIT_ASSERT(a.SkipPrefix("") && a == "def");
  90. UNIT_ASSERT(!a.SkipPrefix("xyz") && a == "def");
  91. UNIT_ASSERT(!a.SkipPrefix("defg") && a == "def");
  92. UNIT_ASSERT(a.SkipPrefix("def") && a == "");
  93. UNIT_ASSERT(a.SkipPrefix("") && a == "");
  94. UNIT_ASSERT(!a.SkipPrefix("def") && a == "");
  95. }
  96. Y_UNIT_TEST(TestBeforeSuffix) {
  97. TStringBuf str("cat_dog");
  98. TStringBuf r = "the_same";
  99. UNIT_ASSERT(!str.BeforeSuffix("cat", r));
  100. UNIT_ASSERT_EQUAL(r, "the_same");
  101. UNIT_ASSERT(str.BeforeSuffix("_dog", r));
  102. UNIT_ASSERT_EQUAL(r, "cat");
  103. // example:
  104. str = "maps.yandex.com.ua";
  105. if (str.BeforeSuffix(".ru", r)) {
  106. UNIT_ASSERT_EQUAL(r, "maps.yandex");
  107. }
  108. // ChopSuffix()
  109. TStringBuf a = "abcdef";
  110. UNIT_ASSERT(a.ChopSuffix("f") && a == "abcde");
  111. UNIT_ASSERT(a.ChopSuffix("de") && a == "abc");
  112. UNIT_ASSERT(a.ChopSuffix("") && a == "abc");
  113. UNIT_ASSERT(!a.ChopSuffix("xyz") && a == "abc");
  114. UNIT_ASSERT(!a.ChopSuffix("abcd") && a == "abc");
  115. UNIT_ASSERT(a.ChopSuffix("abc") && a == "");
  116. UNIT_ASSERT(a.ChopSuffix("") && a == "");
  117. UNIT_ASSERT(!a.ChopSuffix("abc") && a == "");
  118. }
  119. Y_UNIT_TEST(TestEmpty) {
  120. UNIT_ASSERT(TStringBuf().empty());
  121. UNIT_ASSERT(!TStringBuf("q").empty());
  122. }
  123. Y_UNIT_TEST(TestShift) {
  124. TStringBuf qw("qwerty");
  125. TStringBuf str;
  126. str = qw;
  127. str.Chop(10);
  128. UNIT_ASSERT(str.empty());
  129. str = qw;
  130. UNIT_ASSERT_EQUAL(str.SubStr(2), TStringBuf("erty"));
  131. UNIT_ASSERT_EQUAL(str.Skip(3), qw.SubStr(3));
  132. str.Chop(1);
  133. UNIT_ASSERT_EQUAL(str, TStringBuf("rt"));
  134. }
  135. Y_UNIT_TEST(TestSplit) {
  136. TStringBuf qw("qwerty");
  137. TStringBuf lt, rt;
  138. rt = qw;
  139. lt = rt.NextTok('r');
  140. UNIT_ASSERT_EQUAL(lt, TStringBuf("qwe"));
  141. UNIT_ASSERT_EQUAL(rt, TStringBuf("ty"));
  142. lt = qw;
  143. rt = lt.SplitOff('r');
  144. UNIT_ASSERT_EQUAL(lt, TStringBuf("qwe"));
  145. UNIT_ASSERT_EQUAL(rt, TStringBuf("ty"));
  146. rt = qw;
  147. lt = rt.NextTok('r');
  148. TStringBuf ty = rt.NextTok('r'); // no 'r' in "ty"
  149. UNIT_ASSERT_EQUAL(rt.size(), 0);
  150. UNIT_ASSERT_EQUAL(ty, TStringBuf("ty"));
  151. }
  152. Y_UNIT_TEST(TestNextTok) {
  153. TStringBuf buf("12q45q");
  154. TStringBuf tok;
  155. UNIT_ASSERT(buf.NextTok('q', tok) && tok == "12");
  156. UNIT_ASSERT(buf.NextTok('q', tok) && tok == "45");
  157. UNIT_ASSERT(!buf.NextTok('q', tok));
  158. }
  159. Y_UNIT_TEST(TestNextStringTok) {
  160. TStringBuf buf1("a@@b@@c");
  161. UNIT_ASSERT_EQUAL(buf1.NextTok("@@"), TStringBuf("a"));
  162. UNIT_ASSERT_EQUAL(buf1.NextTok("@@"), TStringBuf("b"));
  163. UNIT_ASSERT_EQUAL(buf1.NextTok("@@"), TStringBuf("c"));
  164. UNIT_ASSERT_EQUAL(buf1, TStringBuf());
  165. TStringBuf buf2("a@@b@@c");
  166. UNIT_ASSERT_EQUAL(buf2.RNextTok("@@"), TStringBuf("c"));
  167. UNIT_ASSERT_EQUAL(buf2.RNextTok("@@"), TStringBuf("b"));
  168. UNIT_ASSERT_EQUAL(buf2.RNextTok("@@"), TStringBuf("a"));
  169. UNIT_ASSERT_EQUAL(buf2, TStringBuf());
  170. TStringBuf buf3("a@@b@@c");
  171. UNIT_ASSERT_EQUAL(buf3.RNextTok("@@@"), TStringBuf("a@@b@@c"));
  172. UNIT_ASSERT_EQUAL(buf3, TStringBuf());
  173. }
  174. Y_UNIT_TEST(TestReadLine) {
  175. TStringBuf buf("12\n45\r\n\r\n23");
  176. TStringBuf tok;
  177. buf.ReadLine(tok);
  178. UNIT_ASSERT_VALUES_EQUAL(tok, "12");
  179. buf.ReadLine(tok);
  180. UNIT_ASSERT_VALUES_EQUAL(tok, "45");
  181. buf.ReadLine(tok);
  182. UNIT_ASSERT_VALUES_EQUAL(tok, "");
  183. buf.ReadLine(tok);
  184. UNIT_ASSERT_VALUES_EQUAL(tok, "23");
  185. UNIT_ASSERT(!buf.ReadLine(tok));
  186. }
  187. Y_UNIT_TEST(TestRFind) {
  188. TStringBuf buf1 = "123123456";
  189. UNIT_ASSERT_EQUAL(buf1.rfind('3'), 5);
  190. UNIT_ASSERT_EQUAL(buf1.rfind('4'), 6);
  191. UNIT_ASSERT_EQUAL(buf1.rfind('7'), TStringBuf::npos);
  192. TStringBuf buf2;
  193. UNIT_ASSERT_EQUAL(buf2.rfind('3'), TStringBuf::npos);
  194. TStringBuf buf3 = TStringBuf("123123456", 6);
  195. UNIT_ASSERT_EQUAL(buf3.rfind('3'), 5);
  196. UNIT_ASSERT_EQUAL(buf3.rfind('4'), TStringBuf::npos);
  197. UNIT_ASSERT_EQUAL(buf3.rfind('7'), TStringBuf::npos);
  198. TStringBuf buf4 = TStringBuf("123123456", 5);
  199. UNIT_ASSERT_EQUAL(buf4.rfind('3'), 2);
  200. }
  201. Y_UNIT_TEST(TestRNextTok) {
  202. TStringBuf buf1("a.b.c");
  203. UNIT_ASSERT_EQUAL(buf1.RNextTok('.'), TStringBuf("c"));
  204. UNIT_ASSERT_EQUAL(buf1, TStringBuf("a.b"));
  205. TStringBuf buf2("a");
  206. UNIT_ASSERT_EQUAL(buf2.RNextTok('.'), TStringBuf("a"));
  207. UNIT_ASSERT_EQUAL(buf2, TStringBuf());
  208. TStringBuf buf3("ab cd ef"), tok;
  209. UNIT_ASSERT(buf3.RNextTok(' ', tok) && tok == "ef" && buf3 == "ab cd");
  210. UNIT_ASSERT(buf3.RNextTok(' ', tok) && tok == "cd" && buf3 == "ab");
  211. UNIT_ASSERT(buf3.RNextTok(' ', tok) && tok == "ab" && buf3 == "");
  212. UNIT_ASSERT(!buf3.RNextTok(' ', tok) && tok == "ab" && buf3 == ""); // not modified
  213. }
  214. Y_UNIT_TEST(TestRSplitOff) {
  215. TStringBuf buf1("a.b.c");
  216. UNIT_ASSERT_EQUAL(buf1.RSplitOff('.'), TStringBuf("a.b"));
  217. UNIT_ASSERT_EQUAL(buf1, TStringBuf("c"));
  218. TStringBuf buf2("a");
  219. UNIT_ASSERT_EQUAL(buf2.RSplitOff('.'), TStringBuf());
  220. UNIT_ASSERT_EQUAL(buf2, TStringBuf("a"));
  221. }
  222. Y_UNIT_TEST(TestCBeginCEnd) {
  223. const char helloThere[] = "Hello there";
  224. TStringBuf s{helloThere};
  225. size_t index = 0;
  226. for (auto it = s.cbegin(); s.cend() != it; ++it, ++index) {
  227. UNIT_ASSERT_VALUES_EQUAL(helloThere[index], *it);
  228. }
  229. }
  230. Y_UNIT_TEST(TestSplitOnAt) {
  231. TStringBuf s = "abcabc";
  232. TStringBuf l, r;
  233. size_t pos = s.find('a');
  234. UNIT_ASSERT(s.TrySplitOn(pos, l, r));
  235. UNIT_ASSERT(l == "" && r == "bcabc");
  236. UNIT_ASSERT(s.TrySplitAt(pos, l, r));
  237. UNIT_ASSERT(l == "" && r == "abcabc");
  238. pos = s.find("ca");
  239. UNIT_ASSERT(s.TrySplitOn(pos, l, r));
  240. UNIT_ASSERT(l == "ab" && r == "abc");
  241. UNIT_ASSERT(s.TrySplitOn(pos, l, r, 2));
  242. UNIT_ASSERT(l == "ab" && r == "bc");
  243. UNIT_ASSERT(s.TrySplitAt(pos, l, r));
  244. UNIT_ASSERT(l == "ab" && r == "cabc");
  245. // out of range
  246. pos = 100500;
  247. UNIT_ASSERT(s.TrySplitOn(pos, l, r)); // still true
  248. UNIT_ASSERT(l == "abcabc" && r == "");
  249. l = "111";
  250. r = "222";
  251. UNIT_ASSERT(s.TrySplitAt(pos, l, r)); // still true
  252. UNIT_ASSERT(l == "abcabc" && r == "");
  253. // npos
  254. pos = s.find("missing");
  255. l = "111";
  256. r = "222";
  257. UNIT_ASSERT(!s.TrySplitOn(pos, l, r));
  258. UNIT_ASSERT(l == "111" && r == "222"); // not modified
  259. s.SplitOn(pos, l, r);
  260. UNIT_ASSERT(l == "abcabc" && r == ""); // modified
  261. l = "111";
  262. r = "222";
  263. UNIT_ASSERT(!s.TrySplitAt(pos, l, r));
  264. UNIT_ASSERT(l == "111" && r == "222"); // not modified
  265. s.SplitAt(pos, l, r);
  266. UNIT_ASSERT(l == "abcabc" && r == ""); // modified
  267. }
  268. template <class T>
  269. void PassByConstReference(const T& val) {
  270. // In https://st.yandex-team.ru/IGNIETFERRO-294 was assumed that `const char[]` types are compile time strings
  271. // and that CharTraits::Length may not be called for them. Unfortunately that is not true, `char[]` types
  272. // are easily converted to `const char[]` if they are passed to a function accepting `const T&`.
  273. UNIT_ASSERT(TStringBuf(val).size() == 5);
  274. }
  275. Y_UNIT_TEST(TestPassingArraysByConstReference) {
  276. char data[] = "Hello\0word";
  277. PassByConstReference(data);
  278. }
  279. Y_UNIT_TEST(TestTruncate) {
  280. TStringBuf s = "123";
  281. s.Trunc(5);
  282. UNIT_ASSERT_STRINGS_EQUAL(s, "123");
  283. s.Trunc(3);
  284. UNIT_ASSERT_STRINGS_EQUAL(s, "123");
  285. s.Trunc(1);
  286. UNIT_ASSERT_STRINGS_EQUAL(s, "1");
  287. s.Trunc(0);
  288. UNIT_ASSERT_STRINGS_EQUAL(s, "");
  289. s.Trunc(0);
  290. UNIT_ASSERT_STRINGS_EQUAL(s, "");
  291. }
  292. Y_UNIT_TEST(TestLiterals) {
  293. auto s = "123"_sb;
  294. static_assert(std::is_same_v<decltype(s), TStringBuf>);
  295. UNIT_ASSERT_VALUES_EQUAL(s, TStringBuf("123"));
  296. }
  297. } // Y_UNIT_TEST_SUITE(TStrBufTest)
  298. Y_UNIT_TEST_SUITE(TWtrBufTest) {
  299. Y_UNIT_TEST(TestConstExpr) {
  300. static constexpr TWtringBuf str1(u"qwe\0rty", 7);
  301. static constexpr TWtringBuf str2(str1.data(), str1.size());
  302. static constexpr TWtringBuf str3 = u"qwe\0rty"sv;
  303. UNIT_ASSERT_VALUES_EQUAL(str1.size(), 7);
  304. UNIT_ASSERT_VALUES_EQUAL(str1, str2);
  305. UNIT_ASSERT_VALUES_EQUAL(str2, str3);
  306. UNIT_ASSERT_VALUES_EQUAL(str1, str3);
  307. static constexpr std::u16string_view view1(str1);
  308. UNIT_ASSERT_VALUES_EQUAL(str1, view1);
  309. static_assert(str1.data() == view1.data());
  310. static_assert(str1.size() == view1.size());
  311. static constexpr TWtringBuf str4(view1);
  312. UNIT_ASSERT_VALUES_EQUAL(str1, str4);
  313. static_assert(str1.data() == str4.data());
  314. static_assert(str1.size() == str4.size());
  315. static_assert(str1 == str2);
  316. }
  317. } // Y_UNIT_TEST_SUITE(TWtrBufTest)