123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- #include "ysaveload.h"
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/memory/pool.h>
- #include <util/stream/buffer.h>
- #include <util/memory/blob.h>
- #include <util/generic/list.h>
- #include <util/generic/map.h>
- #include <util/generic/hash_multi_map.h>
- #include <util/generic/deque.h>
- #include <util/generic/string.h>
- #include <util/generic/vector.h>
- #include <util/generic/buffer.h>
- #include <util/generic/hash_set.h>
- #include <util/generic/maybe.h>
- static inline char* AllocateFromPool(TMemoryPool& pool, size_t len) {
- return (char*)pool.Allocate(len);
- }
- class TSaveLoadTest: public TTestBase {
- UNIT_TEST_SUITE(TSaveLoadTest);
- UNIT_TEST(TestSaveLoad)
- UNIT_TEST(TestNewStyle)
- UNIT_TEST(TestNewNewStyle)
- UNIT_TEST(TestList)
- UNIT_TEST(TestTuple)
- UNIT_TEST(TestVariant)
- UNIT_TEST(TestOptional)
- UNIT_TEST(TestInheritNonVirtualClass)
- UNIT_TEST(TestInheritVirtualClass)
- UNIT_TEST_SUITE_END();
- struct TSaveHelper {
- inline void Save(IOutputStream* o) const {
- o->Write("qwerty", 7);
- }
- inline void Load(IInputStream* i) {
- char buf[7];
- UNIT_ASSERT_EQUAL(i->Load(buf, 7), 7);
- UNIT_ASSERT_EQUAL(strcmp(buf, "qwerty"), 0);
- }
- };
- struct TNewStyleSaveHelper {
- template <class S>
- inline void SaveLoad(S* s) {
- ::SaveLoad(s, Str);
- }
- TString Str;
- };
- struct TNewNewStyleHelper {
- TString Str;
- ui32 Int;
- Y_SAVELOAD_DEFINE(Str, Int);
- };
- private:
- inline void TestNewNewStyle() {
- TString ss;
- {
- TNewNewStyleHelper h;
- h.Str = "qw";
- h.Int = 42;
- TStringOutput so(ss);
- ::Save(&so, h);
- }
- {
- TNewNewStyleHelper h;
- TStringInput si(ss);
- ::Load(&si, h);
- UNIT_ASSERT_EQUAL(h.Str, "qw");
- UNIT_ASSERT_EQUAL(h.Int, 42);
- }
- }
- inline void TestNewStyle() {
- TString ss;
- {
- TNewStyleSaveHelper sh;
- sh.Str = "qwerty";
- TStringOutput so(ss);
- SaveLoad(&so, sh);
- }
- {
- TNewStyleSaveHelper sh;
- TStringInput si(ss);
- SaveLoad(&si, sh);
- UNIT_ASSERT_EQUAL(sh.Str, "qwerty");
- }
- }
- inline void TestSaveLoad() {
- TBufferStream S_;
- //save part
- {
- Save(&S_, (ui8)1);
- Save(&S_, (ui16)2);
- Save(&S_, (ui32)3);
- Save(&S_, (ui64)4);
- }
- {
- TVector<ui16> vec;
- vec.push_back((ui16)1);
- vec.push_back((ui16)2);
- vec.push_back((ui16)4);
- Save(&S_, vec);
- }
- {
- TMap<ui16, ui32> map;
- map[(ui16)1] = 2;
- map[(ui16)2] = 3;
- map[(ui16)3] = 4;
- Save(&S_, map);
- }
- {
- TMultiMap<ui16, ui32> multimap;
- multimap.emplace((ui16)1, 2);
- multimap.emplace((ui16)2, 3);
- multimap.emplace((ui16)2, 4);
- multimap.emplace((ui16)2, 5);
- multimap.emplace((ui16)3, 6);
- Save(&S_, multimap);
- }
- {
- TSaveHelper helper;
- Save(&S_, helper);
- }
- {
- TString val("123456");
- Save(&S_, val);
- }
- {
- TBuffer buf;
- buf.Append("asdf", 4);
- Save(&S_, buf);
- }
- {
- TVector<const char*> vec;
- vec.push_back("1");
- vec.push_back("123");
- vec.push_back("4567");
- Save(&S_, vec);
- }
- {
- TDeque<ui16> deq;
- deq.push_back(1);
- deq.push_back(2);
- deq.push_back(4);
- deq.push_back(5);
- Save(&S_, deq);
- }
- {
- TMaybe<size_t> h(10);
- Save(&S_, h);
- }
- {
- TMaybe<size_t> h(20);
- Save(&S_, h);
- }
- {
- TMaybe<size_t> h;
- Save(&S_, h);
- }
- {
- TMaybe<size_t> h;
- Save(&S_, h);
- }
- {
- THashMultiMap<TString, int> mm;
- mm.insert({"one", 1});
- mm.insert({"two", 2});
- mm.insert({"two", 22});
- Save(&S_, mm);
- }
- //load part
- {
- ui8 val;
- Load(&S_, val);
- UNIT_ASSERT_EQUAL(val, 1);
- }
- {
- ui16 val;
- Load(&S_, val);
- UNIT_ASSERT_EQUAL(val, 2);
- }
- {
- ui32 val;
- Load(&S_, val);
- UNIT_ASSERT_EQUAL(val, 3);
- }
- {
- ui64 val;
- Load(&S_, val);
- UNIT_ASSERT_EQUAL(val, 4);
- }
- {
- TVector<ui16> vec;
- Load(&S_, vec);
- UNIT_ASSERT_EQUAL(vec.size(), 3);
- UNIT_ASSERT_EQUAL(vec[0], 1);
- UNIT_ASSERT_EQUAL(vec[1], 2);
- UNIT_ASSERT_EQUAL(vec[2], 4);
- }
- {
- TMap<ui16, ui32> map;
- Load(&S_, map);
- UNIT_ASSERT_EQUAL(map.size(), 3);
- UNIT_ASSERT_EQUAL(map[(ui16)1], 2);
- UNIT_ASSERT_EQUAL(map[(ui16)2], 3);
- UNIT_ASSERT_EQUAL(map[(ui16)3], 4);
- }
- {
- TMultiMap<ui16, ui32> multimap;
- Load(&S_, multimap);
- UNIT_ASSERT_EQUAL(multimap.size(), 5);
- UNIT_ASSERT_EQUAL(multimap.find((ui16)1)->second, 2);
- UNIT_ASSERT_EQUAL(multimap.find((ui16)3)->second, 6);
- THashSet<ui32> values;
- auto range = multimap.equal_range((ui16)2);
- for (auto i = range.first; i != range.second; ++i) {
- values.insert(i->second);
- }
- UNIT_ASSERT_EQUAL(values.size(), 3);
- UNIT_ASSERT_EQUAL(values.contains(3), true);
- UNIT_ASSERT_EQUAL(values.contains(4), true);
- UNIT_ASSERT_EQUAL(values.contains(5), true);
- }
- {
- TSaveHelper helper;
- Load(&S_, helper);
- }
- {
- TString val;
- Load(&S_, val);
- UNIT_ASSERT_EQUAL(val, "123456");
- }
- {
- TBuffer buf;
- Load(&S_, buf);
- UNIT_ASSERT_EQUAL(buf.size(), 4);
- UNIT_ASSERT_EQUAL(memcmp(buf.data(), "asdf", 4), 0);
- }
- {
- TVector<const char*> vec;
- TMemoryPool pool(1024);
- Load(&S_, vec, pool);
- UNIT_ASSERT_EQUAL(vec.size(), 3);
- UNIT_ASSERT_EQUAL(vec[0], TString("1"));
- UNIT_ASSERT_EQUAL(vec[1], TString("123"));
- UNIT_ASSERT_EQUAL(vec[2], TString("4567"));
- }
- {
- TDeque<ui16> deq;
- Load(&S_, deq);
- UNIT_ASSERT_EQUAL(deq.size(), 4);
- UNIT_ASSERT_EQUAL(deq[0], 1);
- UNIT_ASSERT_EQUAL(deq[1], 2);
- UNIT_ASSERT_EQUAL(deq[2], 4);
- UNIT_ASSERT_EQUAL(deq[3], 5);
- }
- {
- TMaybe<size_t> h(5);
- Load(&S_, h);
- UNIT_ASSERT_EQUAL(*h, 10);
- }
- {
- TMaybe<size_t> h;
- Load(&S_, h);
- UNIT_ASSERT_EQUAL(*h, 20);
- }
- {
- TMaybe<size_t> h;
- UNIT_ASSERT(!h);
- Load(&S_, h);
- UNIT_ASSERT(!h);
- }
- {
- TMaybe<size_t> h(7);
- UNIT_ASSERT(!!h);
- Load(&S_, h);
- UNIT_ASSERT(!h);
- }
- {
- THashMultiMap<TString, int> mm;
- Load(&S_, mm);
- UNIT_ASSERT_EQUAL(mm.size(), 3);
- UNIT_ASSERT_EQUAL(mm.count("one"), 1);
- auto oneIter = mm.equal_range("one").first;
- UNIT_ASSERT_EQUAL(oneIter->second, 1);
- UNIT_ASSERT_EQUAL(mm.count("two"), 2);
- auto twoIter = mm.equal_range("two").first;
- UNIT_ASSERT_EQUAL(twoIter->second, 2);
- UNIT_ASSERT_EQUAL((++twoIter)->second, 22);
- }
- }
- void TestList() {
- TBufferStream s;
- TList<int> list = {0, 1, 10};
- Save(&s, list);
- list.clear();
- Load(&s, list);
- UNIT_ASSERT_VALUES_EQUAL(list.size(), 3);
- UNIT_ASSERT_VALUES_EQUAL(*std::next(list.begin(), 0), 0);
- UNIT_ASSERT_VALUES_EQUAL(*std::next(list.begin(), 1), 1);
- UNIT_ASSERT_VALUES_EQUAL(*std::next(list.begin(), 2), 10);
- }
- void TestTuple() {
- TBufferStream s;
- using TTuple = std::tuple<int, TString, unsigned int>;
- const TTuple toSave{-10, "qwerty", 15};
- Save(&s, toSave);
- TTuple toLoad;
- Load(&s, toLoad);
- UNIT_ASSERT_VALUES_EQUAL(std::get<0>(toLoad), std::get<0>(toSave));
- UNIT_ASSERT_VALUES_EQUAL(std::get<1>(toLoad), std::get<1>(toSave));
- UNIT_ASSERT_VALUES_EQUAL(std::get<2>(toLoad), std::get<2>(toSave));
- }
- template <class TVariant, class T>
- void TestVariantImpl(TVariant& v, const T& expected) {
- v = expected;
- TBufferStream s;
- ::Save(&s, v);
- ::Load(&s, v);
- UNIT_ASSERT_VALUES_EQUAL(std::get<T>(v), expected);
- }
- void TestVariant() {
- std::variant<int, bool, TString, TVector<char>> v(1);
- TestVariantImpl(v, 42);
- TestVariantImpl(v, true);
- TestVariantImpl(v, TString("foo"));
- TestVariantImpl(v, TVector<char>{'b', 'a', 'r'});
- v = TString("baz");
- TBufferStream s;
- ::Save(&s, v);
- std::variant<char, bool> v2 = false;
- UNIT_ASSERT_EXCEPTION(::Load(&s, v2), TLoadEOF);
- }
- template <class T>
- void TestOptionalImpl(const std::optional<T>& v) {
- std::optional<T> loaded;
- TBufferStream s;
- ::Save(&s, v);
- ::Load(&s, loaded);
- UNIT_ASSERT_VALUES_EQUAL(v.has_value(), loaded.has_value());
- if (v.has_value()) {
- UNIT_ASSERT_VALUES_EQUAL(*v, *loaded);
- }
- }
- void TestOptional() {
- TestOptionalImpl(std::optional<ui64>(42ull));
- TestOptionalImpl(std::optional<bool>(true));
- TestOptionalImpl(std::optional<TString>("abacaba"));
- TestOptionalImpl(std::optional<ui64>(std::nullopt));
- }
- // tests serialization of class with three public string members
- template <class TDerived, class TInterface = TDerived>
- void TestInheritClassImpl() {
- TBufferStream s;
- {
- TDerived v1;
- v1.Str1 = "One";
- v1.Str2 = "Two";
- v1.Str3 = "Three";
- ::Save(&s, static_cast<const TInterface&>(v1));
- }
- {
- TDerived v2;
- ::Load(&s, static_cast<TInterface&>(v2));
- UNIT_ASSERT_VALUES_EQUAL_C(v2.Str1, "One", TypeName<TDerived>() << " via " << TypeName<TInterface>());
- UNIT_ASSERT_VALUES_EQUAL_C(v2.Str2, "Two", TypeName<TDerived>() << " via " << TypeName<TInterface>());
- UNIT_ASSERT_VALUES_EQUAL_C(v2.Str3, "Three", TypeName<TDerived>() << " via " << TypeName<TInterface>());
- }
- }
- void TestInheritNonVirtualClass() {
- struct TBaseNonVirtual {
- TString Str1;
- Y_SAVELOAD_DEFINE(Str1);
- };
- struct TDerivedNonVirtual: TBaseNonVirtual {
- TString Str2;
- TString Str3;
- Y_SAVELOAD_DEFINE(TNonVirtualSaver<TBaseNonVirtual>{this}, Str2, Str3);
- };
- TestInheritClassImpl<TDerivedNonVirtual>();
- }
- void TestInheritVirtualClass() {
- struct IInterface {
- virtual void Save(IOutputStream* out) const = 0;
- virtual void Load(IInputStream* in) = 0;
- };
- struct TBaseVirtual: IInterface {
- TString Str1;
- Y_SAVELOAD_DEFINE_OVERRIDE(Str1);
- };
- struct TDerivedVirtual: TBaseVirtual {
- TString Str2;
- TString Str3;
- Y_SAVELOAD_DEFINE_OVERRIDE(TNonVirtualSaver<TBaseVirtual>{this}, Str2, Str3);
- };
- TestInheritClassImpl<TDerivedVirtual>();
- TestInheritClassImpl<TDerivedVirtual, TBaseVirtual>();
- TestInheritClassImpl<TDerivedVirtual, IInterface>();
- }
- };
- UNIT_TEST_SUITE_REGISTRATION(TSaveLoadTest);
|