ios_ut.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. #include "output.h"
  2. #include "tokenizer.h"
  3. #include "buffer.h"
  4. #include "buffered.h"
  5. #include "walk.h"
  6. #include <library/cpp/testing/unittest/registar.h>
  7. #include <util/string/cast.h>
  8. #include <util/memory/tempbuf.h>
  9. #include <util/charset/wide.h>
  10. #include <string>
  11. #include <iostream>
  12. class TStreamsTest: public TTestBase {
  13. UNIT_TEST_SUITE(TStreamsTest);
  14. UNIT_TEST(TestGenericRead);
  15. UNIT_TEST(TestGenericWrite);
  16. UNIT_TEST(TestReadLine);
  17. UNIT_TEST(TestMemoryStream);
  18. UNIT_TEST(TestBufferedIO);
  19. UNIT_TEST(TestBufferStream);
  20. UNIT_TEST(TestStringStream);
  21. UNIT_TEST(TestWtrokaInput);
  22. UNIT_TEST(TestStrokaInput);
  23. UNIT_TEST(TestReadTo);
  24. UNIT_TEST(TestWtrokaOutput);
  25. UNIT_TEST(TestIStreamOperators);
  26. UNIT_TEST(TestWchar16Output);
  27. UNIT_TEST(TestWchar32Output);
  28. UNIT_TEST(TestUtf16StingOutputByChars);
  29. UNIT_TEST_SUITE_END();
  30. public:
  31. void TestGenericRead();
  32. void TestGenericWrite();
  33. void TestReadLine();
  34. void TestMemoryStream();
  35. void TestBufferedIO();
  36. void TestBufferStream();
  37. void TestStringStream();
  38. void TestWtrokaInput();
  39. void TestStrokaInput();
  40. void TestWtrokaOutput();
  41. void TestIStreamOperators();
  42. void TestReadTo();
  43. void TestWchar16Output();
  44. void TestWchar32Output();
  45. void TestUtf16StingOutputByChars();
  46. };
  47. UNIT_TEST_SUITE_REGISTRATION(TStreamsTest);
  48. void TStreamsTest::TestIStreamOperators() {
  49. TString data("first line\r\nsecond\t\xd1\x82\xd0\xb5\xd1\x81\xd1\x82 line\r\n 1 -4 59 4320000000009999999 c\n -1.5 1e-110");
  50. TStringInput si(data);
  51. TString l1;
  52. TString l2;
  53. TString l3;
  54. TUtf16String w1;
  55. TString l4;
  56. ui16 i1;
  57. i16 i2;
  58. i32 i3;
  59. ui64 i4;
  60. char c1;
  61. unsigned char c2;
  62. float f1;
  63. double f2;
  64. si >> l1 >> l2 >> l3 >> w1 >> l4 >> i1 >> i2 >> i3 >> i4 >> c1 >> c2 >> f1 >> f2;
  65. UNIT_ASSERT_EQUAL(l1, "first");
  66. UNIT_ASSERT_EQUAL(l2, "line");
  67. UNIT_ASSERT_EQUAL(l3, "second");
  68. UNIT_ASSERT_EQUAL(l4, "line");
  69. UNIT_ASSERT_EQUAL(i1, 1);
  70. UNIT_ASSERT_EQUAL(i2, -4);
  71. UNIT_ASSERT_EQUAL(i3, 59);
  72. UNIT_ASSERT_EQUAL(i4, 4320000000009999999ULL);
  73. UNIT_ASSERT_EQUAL(c1, 'c');
  74. UNIT_ASSERT_EQUAL(c2, '\n');
  75. UNIT_ASSERT_EQUAL(f1, -1.5);
  76. UNIT_ASSERT_EQUAL(f2, 1e-110);
  77. }
  78. void TStreamsTest::TestStringStream() {
  79. TStringStream s;
  80. s << "qw\r\n1234"
  81. << "\n"
  82. << 34;
  83. UNIT_ASSERT_EQUAL(s.ReadLine(), "qw");
  84. UNIT_ASSERT_EQUAL(s.ReadLine(), "1234");
  85. s << "\r\n"
  86. << 123.1;
  87. UNIT_ASSERT_EQUAL(s.ReadLine(), "34");
  88. UNIT_ASSERT_EQUAL(s.ReadLine(), "123.1");
  89. UNIT_ASSERT_EQUAL(s.Str(), "qw\r\n1234\n34\r\n123.1");
  90. // Test stream copying
  91. TStringStream sc = s;
  92. s << "-666-" << 13;
  93. sc << "-777-" << 0 << "JackPot";
  94. UNIT_ASSERT_EQUAL(s.Str(), "qw\r\n1234\n34\r\n123.1-666-13");
  95. UNIT_ASSERT_EQUAL(sc.Str(), "qw\r\n1234\n34\r\n123.1-777-0JackPot");
  96. TStringStream ss;
  97. ss = s;
  98. s << "... and some trash";
  99. UNIT_ASSERT_EQUAL(ss.Str(), "qw\r\n1234\n34\r\n123.1-666-13");
  100. }
  101. void TStreamsTest::TestGenericRead() {
  102. TString s("1234567890");
  103. TStringInput si(s);
  104. char buf[1024];
  105. UNIT_ASSERT_EQUAL(si.Read(buf, 6), 6);
  106. UNIT_ASSERT_EQUAL(memcmp(buf, "123456", 6), 0);
  107. UNIT_ASSERT_EQUAL(si.Read(buf, 6), 4);
  108. UNIT_ASSERT_EQUAL(memcmp(buf, "7890", 4), 0);
  109. }
  110. void TStreamsTest::TestGenericWrite() {
  111. TString s;
  112. TStringOutput so(s);
  113. so.Write("123456", 6);
  114. so.Write("7890", 4);
  115. UNIT_ASSERT_EQUAL(s, "1234567890");
  116. }
  117. void TStreamsTest::TestReadLine() {
  118. TString data("1234\r\n5678\nqw");
  119. TStringInput si(data);
  120. UNIT_ASSERT_EQUAL(si.ReadLine(), "1234");
  121. UNIT_ASSERT_EQUAL(si.ReadLine(), "5678");
  122. UNIT_ASSERT_EQUAL(si.ReadLine(), "qw");
  123. }
  124. void TStreamsTest::TestMemoryStream() {
  125. char buf[1024];
  126. TMemoryOutput mo(buf, sizeof(buf));
  127. bool ehandled = false;
  128. try {
  129. for (size_t i = 0; i < sizeof(buf) + 1; ++i) {
  130. mo.Write(i % 127);
  131. }
  132. } catch (...) {
  133. ehandled = true;
  134. }
  135. UNIT_ASSERT_EQUAL(ehandled, true);
  136. for (size_t i = 0; i < sizeof(buf); ++i) {
  137. UNIT_ASSERT_EQUAL(buf[i], (char)(i % 127));
  138. }
  139. }
  140. class TMyStringOutput: public IOutputStream {
  141. public:
  142. inline TMyStringOutput(TString& s, size_t buflen) noexcept
  143. : S_(s)
  144. , BufLen_(buflen)
  145. {
  146. }
  147. ~TMyStringOutput() override = default;
  148. void DoWrite(const void* data, size_t len) override {
  149. S_.Write(data, len);
  150. UNIT_ASSERT(len < BufLen_ || ((len % BufLen_) == 0));
  151. }
  152. void DoWriteV(const TPart* p, size_t count) override {
  153. TString s;
  154. for (size_t i = 0; i < count; ++i) {
  155. s.append((const char*)p[i].buf, p[i].len);
  156. }
  157. DoWrite(s.data(), s.size());
  158. }
  159. private:
  160. TStringOutput S_;
  161. const size_t BufLen_;
  162. };
  163. void TStreamsTest::TestBufferedIO() {
  164. TString s;
  165. {
  166. const size_t buflen = 7;
  167. TBuffered<TMyStringOutput> bo(buflen, s, buflen);
  168. for (size_t i = 0; i < 1000; ++i) {
  169. TString str(" ");
  170. str += ToString(i % 10);
  171. bo.Write(str.data(), str.size());
  172. }
  173. bo.Finish();
  174. }
  175. UNIT_ASSERT_EQUAL(s.size(), 2000);
  176. {
  177. const size_t buflen = 11;
  178. TBuffered<TStringInput> bi(buflen, s);
  179. for (size_t i = 0; i < 1000; ++i) {
  180. TString str(" ");
  181. str += ToString(i % 10);
  182. char buf[3];
  183. UNIT_ASSERT_EQUAL(bi.Load(buf, 2), 2);
  184. buf[2] = 0;
  185. UNIT_ASSERT_EQUAL(str, buf);
  186. }
  187. }
  188. s.clear();
  189. {
  190. const size_t buflen = 13;
  191. TBuffered<TMyStringOutput> bo(buflen, s, buflen);
  192. TString f = "1234567890";
  193. for (size_t i = 0; i < 10; ++i) {
  194. f += f;
  195. }
  196. for (size_t i = 0; i < 1000; ++i) {
  197. bo.Write(f.data(), i);
  198. }
  199. bo.Finish();
  200. }
  201. }
  202. void TStreamsTest::TestBufferStream() {
  203. TBufferStream stream;
  204. TString s = "test";
  205. stream.Write(s.data(), s.size());
  206. char buf[5];
  207. size_t bytesRead = stream.Read(buf, 4);
  208. UNIT_ASSERT_EQUAL(4, bytesRead);
  209. UNIT_ASSERT_EQUAL(0, strncmp(s.data(), buf, 4));
  210. stream.Write(s.data(), s.size());
  211. bytesRead = stream.Read(buf, 2);
  212. UNIT_ASSERT_EQUAL(2, bytesRead);
  213. UNIT_ASSERT_EQUAL(0, strncmp("te", buf, 2));
  214. bytesRead = stream.Read(buf, 2);
  215. UNIT_ASSERT_EQUAL(2, bytesRead);
  216. UNIT_ASSERT_EQUAL(0, strncmp("st", buf, 2));
  217. bytesRead = stream.Read(buf, 2);
  218. UNIT_ASSERT_EQUAL(0, bytesRead);
  219. }
  220. namespace {
  221. class TStringListInput: public IWalkInput {
  222. public:
  223. TStringListInput(const TVector<TString>& data)
  224. : Data_(data)
  225. , Index_(0)
  226. {
  227. }
  228. protected:
  229. size_t DoUnboundedNext(const void** ptr) override {
  230. if (Index_ >= Data_.size()) {
  231. return 0;
  232. }
  233. const TString& string = Data_[Index_++];
  234. *ptr = string.data();
  235. return string.size();
  236. }
  237. private:
  238. const TVector<TString>& Data_;
  239. size_t Index_;
  240. };
  241. const char Text[] =
  242. // UTF8 encoded "one \ntwo\r\nthree\n\tfour\nfive\n" in russian and ...
  243. "один \n"
  244. "два\r\n"
  245. "три\n"
  246. "\tчетыре\n"
  247. "пять\n"
  248. // ... additional test cases
  249. "\r\n"
  250. "\n\r" // this char goes to the front of the next string
  251. "one two\n"
  252. "123\r\n"
  253. "\t\r ";
  254. const char* Expected[] = {
  255. // UTF8 encoded "one ", "two", "three", "\tfour", "five" in russian and ...
  256. "один ",
  257. "два",
  258. "три",
  259. "\tчетыре",
  260. "пять",
  261. // ... additional test cases
  262. "",
  263. "",
  264. "\rone two",
  265. "123",
  266. "\t\r "};
  267. void TestStreamReadTo1(IInputStream& input, const char* comment) {
  268. TString tmp;
  269. input.ReadTo(tmp, 'c');
  270. UNIT_ASSERT_VALUES_EQUAL_C(tmp, "111a222b333", comment);
  271. char tmp2;
  272. input.Read(&tmp2, 1);
  273. UNIT_ASSERT_VALUES_EQUAL_C(tmp2, '4', comment);
  274. input.ReadTo(tmp, '6');
  275. UNIT_ASSERT_VALUES_EQUAL_C(tmp, "44d555e", comment);
  276. tmp = input.ReadAll();
  277. UNIT_ASSERT_VALUES_EQUAL_C(tmp, "66f", comment);
  278. }
  279. void TestStreamReadTo2(IInputStream& input, const char* comment) {
  280. TString s;
  281. size_t i = 0;
  282. while (input.ReadLine(s)) {
  283. UNIT_ASSERT_C(i < Y_ARRAY_SIZE(Expected), comment);
  284. UNIT_ASSERT_VALUES_EQUAL_C(s, Expected[i], comment);
  285. ++i;
  286. }
  287. }
  288. void TestStreamReadTo3(IInputStream& input, const char* comment) {
  289. UNIT_ASSERT_VALUES_EQUAL_C(input.ReadLine(), "111a222b333c444d555e666f", comment);
  290. }
  291. void TestStreamReadTo4(IInputStream& input, const char* comment) {
  292. UNIT_ASSERT_VALUES_EQUAL_C(input.ReadTo('\0'), "one", comment);
  293. UNIT_ASSERT_VALUES_EQUAL_C(input.ReadTo('\0'), "two", comment);
  294. UNIT_ASSERT_VALUES_EQUAL_C(input.ReadTo('\0'), "three", comment);
  295. }
  296. void TestStrokaInput(IInputStream& input, const char* comment) {
  297. TString line;
  298. ui32 i = 0;
  299. TInstant start = Now();
  300. while (input.ReadLine(line)) {
  301. ++i;
  302. }
  303. Cout << comment << ":" << (Now() - start).SecondsFloat() << Endl;
  304. UNIT_ASSERT_VALUES_EQUAL(i, 100000);
  305. }
  306. template <class T>
  307. void TestStreamReadTo(const TString& text, T test) {
  308. TStringInput is(text);
  309. test(is, "TStringInput");
  310. TMemoryInput mi(text.data(), text.size());
  311. test(mi, "TMemoryInput");
  312. TBuffer b(text.data(), text.size());
  313. TBufferInput bi(b);
  314. test(bi, "TBufferInput");
  315. TStringInput slave(text);
  316. TBufferedInput bdi(&slave);
  317. test(bdi, "TBufferedInput");
  318. TVector<TString> lst(1, text);
  319. TStringListInput sli(lst);
  320. test(sli, "IWalkInput");
  321. }
  322. }
  323. void TStreamsTest::TestReadTo() {
  324. TestStreamReadTo("111a222b333c444d555e666f", TestStreamReadTo1);
  325. TestStreamReadTo(Text, TestStreamReadTo2);
  326. TestStreamReadTo("111a222b333c444d555e666f", TestStreamReadTo3);
  327. TString withZero = "one";
  328. withZero.append('\0').append("two").append('\0').append("three");
  329. TestStreamReadTo(withZero, TestStreamReadTo4);
  330. }
  331. void TStreamsTest::TestStrokaInput() {
  332. TString s;
  333. for (ui32 i = 0; i < 100000; ++i) {
  334. TVector<char> d(i % 1000, 'a');
  335. s.append(d.data(), d.size());
  336. s.append('\n');
  337. }
  338. TestStreamReadTo(s, ::TestStrokaInput);
  339. }
  340. void TStreamsTest::TestWtrokaInput() {
  341. const TString s(Text);
  342. TStringInput is(s);
  343. TUtf16String w;
  344. size_t i = 0;
  345. while (is.ReadLine(w)) {
  346. UNIT_ASSERT(i < Y_ARRAY_SIZE(Expected));
  347. UNIT_ASSERT_VALUES_EQUAL(w, UTF8ToWide(Expected[i]));
  348. ++i;
  349. }
  350. }
  351. void TStreamsTest::TestWtrokaOutput() {
  352. TString s;
  353. TStringOutput os(s);
  354. const size_t n = sizeof(Expected) / sizeof(Expected[0]);
  355. for (size_t i = 0; i < n; ++i) {
  356. TUtf16String w = UTF8ToWide(Expected[i]);
  357. os << w;
  358. if (i == 1 || i == 5 || i == 8) {
  359. os << '\r';
  360. }
  361. if (i < n - 1) {
  362. os << '\n';
  363. }
  364. }
  365. UNIT_ASSERT(s == Text);
  366. }
  367. void TStreamsTest::TestWchar16Output() {
  368. TString s;
  369. TStringOutput os(s);
  370. os << wchar16(97); // latin a
  371. os << u'\u044E'; // cyrillic ю
  372. os << u'я';
  373. os << wchar16(0xD801); // high surrogate is printed as replacement character U+FFFD
  374. os << u'b';
  375. UNIT_ASSERT_VALUES_EQUAL(s, "aюя"
  376. "\xEF\xBF\xBD"
  377. "b");
  378. }
  379. void TStreamsTest::TestWchar32Output() {
  380. TString s;
  381. TStringOutput os(s);
  382. os << wchar32(97); // latin a
  383. os << U'\u044E'; // cyrillic ю
  384. os << U'я';
  385. os << U'\U0001F600'; // grinning face
  386. os << u'b';
  387. UNIT_ASSERT_VALUES_EQUAL(s, "aюя"
  388. "\xF0\x9F\x98\x80"
  389. "b");
  390. }
  391. void TStreamsTest::TestUtf16StingOutputByChars() {
  392. TString s = "\xd1\x87\xd0\xb8\xd1\x81\xd1\x82\xd0\xb8\xd1\x87\xd0\xb8\xd1\x81\xd1\x82\xd0\xb8";
  393. TUtf16String w = UTF8ToWide(s);
  394. UNIT_ASSERT_VALUES_EQUAL(w.size(), 10);
  395. TStringStream stream0;
  396. stream0 << w;
  397. UNIT_ASSERT_VALUES_EQUAL(stream0.Str(), s);
  398. TStringStream stream1;
  399. for (size_t i = 0; i < 10; i++) {
  400. stream1 << w[i];
  401. }
  402. UNIT_ASSERT_VALUES_EQUAL(stream1.Str(), s);
  403. }