ios_ut.cpp 12 KB

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