ysaveload_ut.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. #include "ysaveload.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/memory/pool.h>
  4. #include <util/stream/buffer.h>
  5. #include <util/memory/blob.h>
  6. #include <util/generic/list.h>
  7. #include <util/generic/map.h>
  8. #include <util/generic/set.h>
  9. #include <util/generic/hash.h>
  10. #include <util/generic/deque.h>
  11. #include <util/generic/string.h>
  12. #include <util/generic/vector.h>
  13. #include <util/generic/buffer.h>
  14. #include <util/generic/hash_set.h>
  15. #include <util/generic/maybe.h>
  16. #include <util/generic/variant.h>
  17. static inline char* AllocateFromPool(TMemoryPool& pool, size_t len) {
  18. return (char*)pool.Allocate(len);
  19. }
  20. class TSaveLoadTest: public TTestBase {
  21. UNIT_TEST_SUITE(TSaveLoadTest);
  22. UNIT_TEST(TestSaveLoad)
  23. UNIT_TEST(TestNewStyle)
  24. UNIT_TEST(TestNewNewStyle)
  25. UNIT_TEST(TestList)
  26. UNIT_TEST(TestTuple)
  27. UNIT_TEST(TestVariant)
  28. UNIT_TEST(TestInheritNonVirtualClass)
  29. UNIT_TEST(TestInheritVirtualClass)
  30. UNIT_TEST_SUITE_END();
  31. struct TSaveHelper {
  32. inline void Save(IOutputStream* o) const {
  33. o->Write("qwerty", 7);
  34. }
  35. inline void Load(IInputStream* i) {
  36. char buf[7];
  37. UNIT_ASSERT_EQUAL(i->Load(buf, 7), 7);
  38. UNIT_ASSERT_EQUAL(strcmp(buf, "qwerty"), 0);
  39. }
  40. };
  41. struct TNewStyleSaveHelper {
  42. template <class S>
  43. inline void SaveLoad(S* s) {
  44. ::SaveLoad(s, Str);
  45. }
  46. TString Str;
  47. };
  48. struct TNewNewStyleHelper {
  49. TString Str;
  50. ui32 Int;
  51. Y_SAVELOAD_DEFINE(Str, Int)
  52. };
  53. private:
  54. inline void TestNewNewStyle() {
  55. TString ss;
  56. {
  57. TNewNewStyleHelper h;
  58. h.Str = "qw";
  59. h.Int = 42;
  60. TStringOutput so(ss);
  61. ::Save(&so, h);
  62. }
  63. {
  64. TNewNewStyleHelper h;
  65. TStringInput si(ss);
  66. ::Load(&si, h);
  67. UNIT_ASSERT_EQUAL(h.Str, "qw");
  68. UNIT_ASSERT_EQUAL(h.Int, 42);
  69. }
  70. }
  71. inline void TestNewStyle() {
  72. TString ss;
  73. {
  74. TNewStyleSaveHelper sh;
  75. sh.Str = "qwerty";
  76. TStringOutput so(ss);
  77. SaveLoad(&so, sh);
  78. }
  79. {
  80. TNewStyleSaveHelper sh;
  81. TStringInput si(ss);
  82. SaveLoad(&si, sh);
  83. UNIT_ASSERT_EQUAL(sh.Str, "qwerty");
  84. }
  85. }
  86. inline void TestSaveLoad() {
  87. TBufferStream S_;
  88. //save part
  89. {
  90. Save(&S_, (ui8)1);
  91. Save(&S_, (ui16)2);
  92. Save(&S_, (ui32)3);
  93. Save(&S_, (ui64)4);
  94. }
  95. {
  96. TVector<ui16> vec;
  97. vec.push_back((ui16)1);
  98. vec.push_back((ui16)2);
  99. vec.push_back((ui16)4);
  100. Save(&S_, vec);
  101. }
  102. {
  103. TMap<ui16, ui32> map;
  104. map[(ui16)1] = 2;
  105. map[(ui16)2] = 3;
  106. map[(ui16)3] = 4;
  107. Save(&S_, map);
  108. }
  109. {
  110. TMultiMap<ui16, ui32> multimap;
  111. multimap.emplace((ui16)1, 2);
  112. multimap.emplace((ui16)2, 3);
  113. multimap.emplace((ui16)2, 4);
  114. multimap.emplace((ui16)2, 5);
  115. multimap.emplace((ui16)3, 6);
  116. Save(&S_, multimap);
  117. }
  118. {
  119. TSaveHelper helper;
  120. Save(&S_, helper);
  121. }
  122. {
  123. TString val("123456");
  124. Save(&S_, val);
  125. }
  126. {
  127. TBuffer buf;
  128. buf.Append("asdf", 4);
  129. Save(&S_, buf);
  130. }
  131. {
  132. TVector<const char*> vec;
  133. vec.push_back("1");
  134. vec.push_back("123");
  135. vec.push_back("4567");
  136. Save(&S_, vec);
  137. }
  138. {
  139. TDeque<ui16> deq;
  140. deq.push_back(1);
  141. deq.push_back(2);
  142. deq.push_back(4);
  143. deq.push_back(5);
  144. Save(&S_, deq);
  145. }
  146. {
  147. TMaybe<size_t> h(10);
  148. Save(&S_, h);
  149. }
  150. {
  151. TMaybe<size_t> h(20);
  152. Save(&S_, h);
  153. }
  154. {
  155. TMaybe<size_t> h;
  156. Save(&S_, h);
  157. }
  158. {
  159. TMaybe<size_t> h;
  160. Save(&S_, h);
  161. }
  162. {
  163. THashMultiMap<TString, int> mm;
  164. mm.insert({"one", 1});
  165. mm.insert({"two", 2});
  166. mm.insert({"two", 22});
  167. Save(&S_, mm);
  168. }
  169. //load part
  170. {
  171. ui8 val;
  172. Load(&S_, val);
  173. UNIT_ASSERT_EQUAL(val, 1);
  174. }
  175. {
  176. ui16 val;
  177. Load(&S_, val);
  178. UNIT_ASSERT_EQUAL(val, 2);
  179. }
  180. {
  181. ui32 val;
  182. Load(&S_, val);
  183. UNIT_ASSERT_EQUAL(val, 3);
  184. }
  185. {
  186. ui64 val;
  187. Load(&S_, val);
  188. UNIT_ASSERT_EQUAL(val, 4);
  189. }
  190. {
  191. TVector<ui16> vec;
  192. Load(&S_, vec);
  193. UNIT_ASSERT_EQUAL(vec.size(), 3);
  194. UNIT_ASSERT_EQUAL(vec[0], 1);
  195. UNIT_ASSERT_EQUAL(vec[1], 2);
  196. UNIT_ASSERT_EQUAL(vec[2], 4);
  197. }
  198. {
  199. TMap<ui16, ui32> map;
  200. Load(&S_, map);
  201. UNIT_ASSERT_EQUAL(map.size(), 3);
  202. UNIT_ASSERT_EQUAL(map[(ui16)1], 2);
  203. UNIT_ASSERT_EQUAL(map[(ui16)2], 3);
  204. UNIT_ASSERT_EQUAL(map[(ui16)3], 4);
  205. }
  206. {
  207. TMultiMap<ui16, ui32> multimap;
  208. Load(&S_, multimap);
  209. UNIT_ASSERT_EQUAL(multimap.size(), 5);
  210. UNIT_ASSERT_EQUAL(multimap.find((ui16)1)->second, 2);
  211. UNIT_ASSERT_EQUAL(multimap.find((ui16)3)->second, 6);
  212. THashSet<ui32> values;
  213. auto range = multimap.equal_range((ui16)2);
  214. for (auto i = range.first; i != range.second; ++i) {
  215. values.insert(i->second);
  216. }
  217. UNIT_ASSERT_EQUAL(values.size(), 3);
  218. UNIT_ASSERT_EQUAL(values.contains(3), true);
  219. UNIT_ASSERT_EQUAL(values.contains(4), true);
  220. UNIT_ASSERT_EQUAL(values.contains(5), true);
  221. }
  222. {
  223. TSaveHelper helper;
  224. Load(&S_, helper);
  225. }
  226. {
  227. TString val;
  228. Load(&S_, val);
  229. UNIT_ASSERT_EQUAL(val, "123456");
  230. }
  231. {
  232. TBuffer buf;
  233. Load(&S_, buf);
  234. UNIT_ASSERT_EQUAL(buf.size(), 4);
  235. UNIT_ASSERT_EQUAL(memcmp(buf.data(), "asdf", 4), 0);
  236. }
  237. {
  238. TVector<const char*> vec;
  239. TMemoryPool pool(1024);
  240. Load(&S_, vec, pool);
  241. UNIT_ASSERT_EQUAL(vec.size(), 3);
  242. UNIT_ASSERT_EQUAL(vec[0], TString("1"));
  243. UNIT_ASSERT_EQUAL(vec[1], TString("123"));
  244. UNIT_ASSERT_EQUAL(vec[2], TString("4567"));
  245. }
  246. {
  247. TDeque<ui16> deq;
  248. Load(&S_, deq);
  249. UNIT_ASSERT_EQUAL(deq.size(), 4);
  250. UNIT_ASSERT_EQUAL(deq[0], 1);
  251. UNIT_ASSERT_EQUAL(deq[1], 2);
  252. UNIT_ASSERT_EQUAL(deq[2], 4);
  253. UNIT_ASSERT_EQUAL(deq[3], 5);
  254. }
  255. {
  256. TMaybe<size_t> h(5);
  257. Load(&S_, h);
  258. UNIT_ASSERT_EQUAL(*h, 10);
  259. }
  260. {
  261. TMaybe<size_t> h;
  262. Load(&S_, h);
  263. UNIT_ASSERT_EQUAL(*h, 20);
  264. }
  265. {
  266. TMaybe<size_t> h;
  267. UNIT_ASSERT(!h);
  268. Load(&S_, h);
  269. UNIT_ASSERT(!h);
  270. }
  271. {
  272. TMaybe<size_t> h(7);
  273. UNIT_ASSERT(!!h);
  274. Load(&S_, h);
  275. UNIT_ASSERT(!h);
  276. }
  277. {
  278. THashMultiMap<TString, int> mm;
  279. Load(&S_, mm);
  280. UNIT_ASSERT_EQUAL(mm.size(), 3);
  281. UNIT_ASSERT_EQUAL(mm.count("one"), 1);
  282. auto oneIter = mm.equal_range("one").first;
  283. UNIT_ASSERT_EQUAL(oneIter->second, 1);
  284. UNIT_ASSERT_EQUAL(mm.count("two"), 2);
  285. auto twoIter = mm.equal_range("two").first;
  286. UNIT_ASSERT_EQUAL(twoIter->second, 2);
  287. UNIT_ASSERT_EQUAL((++twoIter)->second, 22);
  288. }
  289. }
  290. void TestList() {
  291. TBufferStream s;
  292. TList<int> list = {0, 1, 10};
  293. Save(&s, list);
  294. list.clear();
  295. Load(&s, list);
  296. UNIT_ASSERT_VALUES_EQUAL(list.size(), 3);
  297. UNIT_ASSERT_VALUES_EQUAL(*std::next(list.begin(), 0), 0);
  298. UNIT_ASSERT_VALUES_EQUAL(*std::next(list.begin(), 1), 1);
  299. UNIT_ASSERT_VALUES_EQUAL(*std::next(list.begin(), 2), 10);
  300. }
  301. void TestTuple() {
  302. TBufferStream s;
  303. using TTuple = std::tuple<int, TString, unsigned int>;
  304. const TTuple toSave{-10, "qwerty", 15};
  305. Save(&s, toSave);
  306. TTuple toLoad;
  307. Load(&s, toLoad);
  308. UNIT_ASSERT_VALUES_EQUAL(std::get<0>(toLoad), std::get<0>(toSave));
  309. UNIT_ASSERT_VALUES_EQUAL(std::get<1>(toLoad), std::get<1>(toSave));
  310. UNIT_ASSERT_VALUES_EQUAL(std::get<2>(toLoad), std::get<2>(toSave));
  311. }
  312. template <class TVariant, class T>
  313. void TestVariantImpl(TVariant& v, const T& expected) {
  314. v = expected;
  315. TBufferStream s;
  316. ::Save(&s, v);
  317. ::Load(&s, v);
  318. UNIT_ASSERT_VALUES_EQUAL(std::get<T>(v), expected);
  319. }
  320. void TestVariant() {
  321. std::variant<int, bool, TString, TVector<char>> v(1);
  322. TestVariantImpl(v, 42);
  323. TestVariantImpl(v, true);
  324. TestVariantImpl(v, TString("foo"));
  325. TestVariantImpl(v, TVector<char>{'b', 'a', 'r'});
  326. v = TString("baz");
  327. TBufferStream s;
  328. ::Save(&s, v);
  329. std::variant<char, bool> v2 = false;
  330. UNIT_ASSERT_EXCEPTION(::Load(&s, v2), TLoadEOF);
  331. }
  332. // tests serialization of class with three public string members
  333. template <class TDerived, class TInterface = TDerived>
  334. void TestInheritClassImpl() {
  335. TBufferStream s;
  336. {
  337. TDerived v1;
  338. v1.Str1 = "One";
  339. v1.Str2 = "Two";
  340. v1.Str3 = "Three";
  341. ::Save(&s, static_cast<const TInterface&>(v1));
  342. }
  343. {
  344. TDerived v2;
  345. ::Load(&s, static_cast<TInterface&>(v2));
  346. UNIT_ASSERT_VALUES_EQUAL_C(v2.Str1, "One", TypeName<TDerived>() << " via " << TypeName<TInterface>());
  347. UNIT_ASSERT_VALUES_EQUAL_C(v2.Str2, "Two", TypeName<TDerived>() << " via " << TypeName<TInterface>());
  348. UNIT_ASSERT_VALUES_EQUAL_C(v2.Str3, "Three", TypeName<TDerived>() << " via " << TypeName<TInterface>());
  349. }
  350. }
  351. void TestInheritNonVirtualClass() {
  352. struct TBaseNonVirtual {
  353. TString Str1;
  354. Y_SAVELOAD_DEFINE(Str1);
  355. };
  356. struct TDerivedNonVirtual: TBaseNonVirtual {
  357. TString Str2;
  358. TString Str3;
  359. Y_SAVELOAD_DEFINE(TNonVirtualSaver<TBaseNonVirtual>{this}, Str2, Str3);
  360. };
  361. TestInheritClassImpl<TDerivedNonVirtual>();
  362. }
  363. void TestInheritVirtualClass() {
  364. struct IInterface {
  365. virtual void Save(IOutputStream* out) const = 0;
  366. virtual void Load(IInputStream* in) = 0;
  367. };
  368. struct TBaseVirtual: IInterface {
  369. TString Str1;
  370. Y_SAVELOAD_DEFINE_OVERRIDE(Str1);
  371. };
  372. struct TDerivedVirtual: TBaseVirtual {
  373. TString Str2;
  374. TString Str3;
  375. Y_SAVELOAD_DEFINE_OVERRIDE(TNonVirtualSaver<TBaseVirtual>{this}, Str2, Str3);
  376. };
  377. TestInheritClassImpl<TDerivedVirtual>();
  378. TestInheritClassImpl<TDerivedVirtual, TBaseVirtual>();
  379. TestInheritClassImpl<TDerivedVirtual, IInterface>();
  380. }
  381. };
  382. UNIT_TEST_SUITE_REGISTRATION(TSaveLoadTest);