chunks_ut.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include <library/cpp/testing/unittest/registar.h>
  2. #include <util/stream/file.h>
  3. #include <util/system/filemap.h>
  4. #include <util/system/tempfile.h>
  5. #include "chunked_helpers.h"
  6. /// Data for TChunkedHelpersTest::TestGeneralVector
  7. struct TPodStruct {
  8. int x;
  9. float y;
  10. TPodStruct(int _x = 0, float _y = 0)
  11. : x(_x)
  12. , y(_y)
  13. {
  14. }
  15. };
  16. /// And its serialization
  17. template <>
  18. struct TSaveLoadVectorNonPodElement<TPodStruct> {
  19. typedef TPodStruct TItem;
  20. static inline void Save(IOutputStream* out, const TItem& item) {
  21. TSerializer<int>::Save(out, item.x);
  22. TSerializer<float>::Save(out, item.y);
  23. }
  24. static inline void Load(IInputStream* in, TItem& item, size_t elementSize) {
  25. Y_ASSERT(elementSize == sizeof(TItem));
  26. TSerializer<int>::Load(in, item.x);
  27. TSerializer<float>::Load(in, item.y);
  28. }
  29. };
  30. class TChunkedHelpersTest: public TTestBase {
  31. UNIT_TEST_SUITE(TChunkedHelpersTest);
  32. UNIT_TEST(TestHash)
  33. UNIT_TEST(TestGeneralVector)
  34. UNIT_TEST(TestStrings);
  35. UNIT_TEST(TestNamedChunkedData);
  36. UNIT_TEST_SUITE_END();
  37. public:
  38. void TestHash() {
  39. {
  40. TBufferStream stream;
  41. {
  42. TPlainHashWriter<ui64, ui16> writer;
  43. writer.Add(5, 7);
  44. writer.Save(stream);
  45. }
  46. {
  47. TBlob temp = TBlob::FromStreamSingleThreaded(stream);
  48. TPlainHash<ui64, ui16> reader(temp);
  49. ui16 value = 0;
  50. UNIT_ASSERT(reader.Find(5, &value));
  51. UNIT_ASSERT_EQUAL(7, value);
  52. UNIT_ASSERT(!reader.Find(6, &value));
  53. }
  54. }
  55. {
  56. TBufferStream stream;
  57. int v = 1;
  58. wchar16 k = 'a';
  59. {
  60. TPlainHashWriter<wchar16, void*> writer;
  61. writer.Add(k, &v);
  62. writer.Save(stream);
  63. }
  64. {
  65. TBlob temp = TBlob::FromStreamSingleThreaded(stream);
  66. TPlainHash<wchar16, void*> reader(temp);
  67. void* value = nullptr;
  68. UNIT_ASSERT(reader.Find(k, &value));
  69. UNIT_ASSERT_EQUAL((int*)value, &v);
  70. }
  71. }
  72. }
  73. void TestGeneralVector() {
  74. { /// ui32
  75. const size_t N = 3;
  76. TBufferStream stream;
  77. {
  78. TGeneralVectorWriter<ui32> writer;
  79. for (size_t i = 0; i < N; ++i)
  80. writer.PushBack(i);
  81. writer.Save(stream);
  82. }
  83. {
  84. TBlob temp = TBlob::FromStreamSingleThreaded(stream);
  85. TGeneralVector<ui32> reader(temp);
  86. UNIT_ASSERT_EQUAL(reader.GetSize(), N);
  87. for (size_t i = 0; i < N; ++i) {
  88. ui32 value;
  89. reader.Get(i, value);
  90. UNIT_ASSERT_EQUAL(value, i);
  91. UNIT_ASSERT_EQUAL(reader.At(i), i);
  92. }
  93. UNIT_ASSERT_EQUAL(reader.RealSize(), sizeof(ui64) + N * sizeof(ui32));
  94. }
  95. }
  96. { /// TString
  97. const size_t N = 4;
  98. TBufferStream stream;
  99. {
  100. TGeneralVectorWriter<TString> writer;
  101. for (size_t i = 0; i < N; ++i)
  102. writer.PushBack(ToString(i));
  103. writer.Save(stream);
  104. }
  105. {
  106. TBlob temp = TBlob::FromStreamSingleThreaded(stream);
  107. TGeneralVector<TString> reader(temp);
  108. UNIT_ASSERT_EQUAL(reader.GetSize(), N);
  109. for (size_t i = 0; i < N; ++i) {
  110. TString value;
  111. reader.Get(i, value);
  112. UNIT_ASSERT_EQUAL(value, ToString(i));
  113. UNIT_ASSERT_EQUAL(reader.Get(i), ToString(i));
  114. }
  115. UNIT_ASSERT_EQUAL(reader.RealSize(), sizeof(ui64) * (N + 2) + N * 2);
  116. }
  117. }
  118. { /// some other struct
  119. typedef TPodStruct TItem;
  120. const size_t N = 2;
  121. TBufferStream stream;
  122. {
  123. TGeneralVectorWriter<TItem> writer;
  124. writer.PushBack(TItem(1, 2));
  125. writer.PushBack(TItem(3, 4));
  126. writer.Save(stream);
  127. }
  128. {
  129. TBlob temp = TBlob::FromStreamSingleThreaded(stream);
  130. TGeneralVector<TItem> reader(temp);
  131. UNIT_ASSERT_EQUAL(reader.GetSize(), N);
  132. TItem value;
  133. reader.Get(0, value);
  134. UNIT_ASSERT(value.x == 1 && value.y == 2.0);
  135. reader.Get(1, value);
  136. UNIT_ASSERT(value.x == 3 && value.y == 4.0);
  137. UNIT_ASSERT_EQUAL(reader.RealSize(), sizeof(ui64) * (N + 2) + N * sizeof(TItem));
  138. }
  139. }
  140. { /// pointer
  141. const size_t N = 3;
  142. TVector<int> data_holder(N);
  143. int* a = &(data_holder[0]);
  144. TBufferStream stream;
  145. {
  146. TGeneralVectorWriter<int*> writer;
  147. for (size_t i = 0; i < N; ++i) {
  148. a[i] = i;
  149. writer.PushBack(a + i);
  150. }
  151. writer.Save(stream);
  152. }
  153. {
  154. TBlob temp = TBlob::FromStreamSingleThreaded(stream);
  155. TGeneralVector<int*> reader(temp);
  156. UNIT_ASSERT_EQUAL(reader.GetSize(), N);
  157. for (size_t i = 0; i < N; ++i) {
  158. int* value;
  159. reader.Get(i, value);
  160. UNIT_ASSERT_EQUAL(value, a + i);
  161. UNIT_ASSERT_EQUAL(reader.At(i), a + i);
  162. }
  163. UNIT_ASSERT_EQUAL(reader.RealSize(), sizeof(ui64) + N * sizeof(int*));
  164. }
  165. }
  166. { /// std::pair<int, int>
  167. typedef std::pair<int, int> TItem;
  168. const size_t N = 3;
  169. TBufferStream stream;
  170. {
  171. TGeneralVectorWriter<TItem> writer;
  172. for (size_t i = 0; i < N; ++i)
  173. writer.PushBack(TItem(i, i));
  174. writer.Save(stream);
  175. }
  176. {
  177. TBlob temp = TBlob::FromStreamSingleThreaded(stream);
  178. TGeneralVector<TItem> reader(temp);
  179. UNIT_ASSERT_EQUAL(reader.GetSize(), N);
  180. for (size_t i = 0; i < N; ++i) {
  181. TItem value;
  182. reader.Get(i, value);
  183. UNIT_ASSERT_EQUAL(value, TItem(i, i));
  184. }
  185. UNIT_ASSERT_EQUAL(reader.RealSize(), sizeof(ui64) + N * sizeof(TItem));
  186. }
  187. }
  188. }
  189. void TestStrings() {
  190. const TString FILENAME = "chunked_helpers_test.bin";
  191. TTempFileHandle file(FILENAME.c_str());
  192. {
  193. TFixedBufferFileOutput fOut(FILENAME);
  194. TStringsVectorWriter stringsWriter;
  195. stringsWriter.PushBack("");
  196. stringsWriter.PushBack("test");
  197. TChunkedDataWriter writer(fOut);
  198. WriteBlock(writer, stringsWriter);
  199. writer.WriteFooter();
  200. }
  201. {
  202. TBlob fIn = TBlob::FromFileSingleThreaded(FILENAME);
  203. TStringsVector vct(GetBlock(fIn, 0));
  204. UNIT_ASSERT_EQUAL(vct.Get(0), "");
  205. UNIT_ASSERT_EQUAL(vct.Get(1), "test");
  206. bool wasException = false;
  207. try {
  208. vct.Get(2);
  209. } catch (...) {
  210. wasException = true;
  211. }
  212. UNIT_ASSERT(wasException);
  213. }
  214. }
  215. void TestNamedChunkedData() {
  216. const TString filename = MakeTempName(nullptr, "named_chunked_data_test");
  217. TTempFile file(filename);
  218. {
  219. TFixedBufferFileOutput fOut(filename);
  220. TNamedChunkedDataWriter writer(fOut);
  221. writer.NewBlock("alpha");
  222. writer.Write("123456");
  223. writer.NewBlock();
  224. writer.Write("anonymous");
  225. writer.NewBlock("omega");
  226. writer.Write("12345678901234567");
  227. writer.WriteFooter();
  228. }
  229. {
  230. TBlob mf = TBlob::FromFileSingleThreaded(filename);
  231. TNamedChunkedDataReader reader(mf);
  232. UNIT_ASSERT(reader.GetBlocksCount() == 3);
  233. UNIT_ASSERT(reader.HasBlock("alpha"));
  234. UNIT_ASSERT(reader.HasBlock("omega"));
  235. UNIT_ASSERT_STRINGS_EQUAL(reader.GetBlockName(0), "alpha");
  236. UNIT_ASSERT_STRINGS_EQUAL(reader.GetBlockName(1), "");
  237. UNIT_ASSERT_STRINGS_EQUAL(reader.GetBlockName(2), "omega");
  238. UNIT_ASSERT_EQUAL(reader.GetBlockLenByName("alpha"), 6); // padding not included
  239. UNIT_ASSERT_EQUAL(reader.GetBlockLenByName("omega"), 17);
  240. UNIT_ASSERT(memcmp(reader.GetBlockByName("alpha"), "123456", 6) == 0);
  241. UNIT_ASSERT(memcmp(reader.GetBlock(1), "anonymous", 9) == 0);
  242. UNIT_ASSERT(memcmp(reader.GetBlockByName("omega"), "12345678901234567", 17) == 0);
  243. }
  244. }
  245. };
  246. UNIT_TEST_SUITE_REGISTRATION(TChunkedHelpersTest);
  247. class TChunkedDataTest: public TTestBase {
  248. private:
  249. UNIT_TEST_SUITE(TChunkedDataTest);
  250. UNIT_TEST(Test)
  251. UNIT_TEST(TestEmpty)
  252. UNIT_TEST_SUITE_END();
  253. void Test() {
  254. TBuffer buffer;
  255. {
  256. TBufferOutput out(buffer);
  257. TChunkedDataWriter writer(out);
  258. writer.NewBlock();
  259. writer << "test";
  260. writer.NewBlock();
  261. writer << 4;
  262. writer.NewBlock();
  263. writer.NewBlock();
  264. writer << 1;
  265. writer << 2;
  266. writer.WriteFooter();
  267. }
  268. {
  269. TBlob blob = TBlob::FromBufferSingleThreaded(buffer);
  270. TChunkedDataReader data(blob);
  271. // printf("%d\n", (int)data.GetBlockLen(3));
  272. UNIT_ASSERT_EQUAL(4, data.GetBlockLen(0));
  273. UNIT_ASSERT_EQUAL(1, data.GetBlockLen(1));
  274. UNIT_ASSERT_EQUAL(0, data.GetBlockLen(2));
  275. UNIT_ASSERT_EQUAL(2, data.GetBlockLen(3));
  276. }
  277. }
  278. void TestEmpty() {
  279. TBuffer buffer;
  280. {
  281. TBufferOutput out(buffer);
  282. TChunkedDataWriter writer(out);
  283. writer.NewBlock();
  284. writer.NewBlock();
  285. writer.WriteFooter();
  286. }
  287. {
  288. TBlob blob = TBlob::FromBufferSingleThreaded(buffer);
  289. TChunkedDataReader data(blob);
  290. // printf("%d\n", (int)data.GetBlockLen(1));
  291. UNIT_ASSERT_EQUAL(0, data.GetBlockLen(0));
  292. UNIT_ASSERT_EQUAL(0, data.GetBlockLen(1));
  293. }
  294. }
  295. };
  296. UNIT_TEST_SUITE_REGISTRATION(TChunkedDataTest);