#include #include #include namespace NKikimr::NMiniKQL { Y_UNIT_TEST_SUITE(TKeyTypeContanerHelper) { struct TSetup { TSetup() : Alloc(__LOCATION__) , TypeEnv(Alloc) , TypeBuilder(TypeEnv) , MemUsage("TKeyTypeContanerHelperTest") , HolderFactory(Alloc.Ref(), MemUsage) {} TScopedAlloc Alloc; TTypeEnvironment TypeEnv; TTypeBuilder TypeBuilder; TMemoryUsageInfo MemUsage; THolderFactory HolderFactory; }; struct TTestedSets { TTestedSets() = default; TTestedSets(const TType* type) : HashSetHelper(type) , HashSet(0, HashSetHelper.GetValueHash(), HashSetHelper.GetValueEqual()) , CmpSetHelper(type) , CmpSet(CmpSetHelper.GetValueLess()) {} void MoveFromHashToCmpSet() { const auto size = HashSet.size(); while(!HashSet.empty()) { CmpSet.insert(std::move(*HashSet.begin())); HashSet.erase(HashSet.begin()); } UNIT_ASSERT_EQUAL(size, CmpSet.size()); } void Reset() { HashSetHelper = TKeyTypeContanerHelper{}; HashSet = std::unordered_set>{ 0, HashSetHelper.GetValueHash(), HashSetHelper.GetValueEqual(), }; CmpSetHelper = TKeyTypeContanerHelper{}; CmpSet = std::set>{CmpSetHelper.GetValueLess()}; } TKeyTypeContanerHelper HashSetHelper; std::unordered_set> HashSet; TKeyTypeContanerHelper CmpSetHelper; std::set> CmpSet; }; Y_UNIT_TEST(StoreInts) { TSetup setup; TTestedSets sets{setup.TypeBuilder.NewDataType(NUdf::EDataSlot::Int32)}; const size_t N = 100; for (size_t i = 0; i != N; ++i) { sets.HashSet.insert(NUdf::TUnboxedValuePod{(ui32)i}); } UNIT_ASSERT_EQUAL(N, sets.HashSet.size()); sets.MoveFromHashToCmpSet(); for (size_t i = 0; i != N; ++i) { UNIT_ASSERT_EQUAL(i, sets.CmpSet.begin()->Get()); sets.CmpSet.erase(sets.CmpSet.begin()); } } Y_UNIT_TEST(StoreStrings) { TSetup setup; TTestedSets sets{setup.TypeBuilder.NewDataType(NUdf::EDataSlot::String)}; const size_t N = 100; //be aware of O(n^2) complexity in data generation for (size_t i = 0; i != N; ++i) { sets.HashSet.insert(NMiniKQL::MakeString(std::string(i, 'x'))); } UNIT_ASSERT_EQUAL(N, sets.HashSet.size()); sets.MoveFromHashToCmpSet(); for (size_t i = 0; i != N; ++i) { UNIT_ASSERT_EQUAL(i, sets.CmpSet.begin()->AsStringRef().Size()); sets.CmpSet.erase(sets.CmpSet.begin()); } } Y_UNIT_TEST(StoreTuples) { TSetup setup; TType* elems[] = { setup.TypeBuilder.NewDataType(NUdf::EDataSlot::Uint32), setup.TypeBuilder.NewDataType(NUdf::EDataSlot::String) }; TTestedSets sets{setup.TypeBuilder.NewTupleType(elems)}; const size_t N = 100; //be aware of O(n^2) complexity in data generation for (size_t i = 0; i != N; ++i) { NUdf::TUnboxedValue* items; NUdf::TUnboxedValue v = setup.HolderFactory.CreateDirectArrayHolder(2, items); items[0] = NUdf::TUnboxedValuePod{(ui32)i}; items[1] = NMiniKQL::MakeString(std::string(i, 'x')); sets.HashSet.insert(std::move(v)); } UNIT_ASSERT_EQUAL(N, sets.HashSet.size()); sets.MoveFromHashToCmpSet(); for (size_t i = 0; i != N; ++i) { UNIT_ASSERT_EQUAL(i, sets.CmpSet.begin()->GetElement(0).Get()); NUdf::TUnboxedValue s = sets.CmpSet.begin()->GetElement(1); UNIT_ASSERT_EQUAL(i, s.AsStringRef().Size()); sets.CmpSet.erase(sets.CmpSet.begin()); } } Y_UNIT_TEST(StoreStructs) { TSetup setup; std::pair elems[] = { std::pair{"i", setup.TypeBuilder.NewDataType(NUdf::EDataSlot::Uint32)}, std::pair{"s", setup.TypeBuilder.NewDataType(NUdf::EDataSlot::String)} }; TTestedSets sets{setup.TypeBuilder.NewStructType(elems)}; const size_t N = 100; //be aware of O(n^2) complexity in data generation for (size_t i = 0; i != N; ++i) { NUdf::TUnboxedValue* items; NUdf::TUnboxedValue v = setup.HolderFactory.CreateDirectArrayHolder(2, items); items[0] = NUdf::TUnboxedValuePod{(ui32)i}; items[1] = NMiniKQL::MakeString(std::string(i, 'x')); sets.HashSet.insert(std::move(v)); } UNIT_ASSERT_EQUAL(N, sets.HashSet.size()); sets.MoveFromHashToCmpSet(); for (size_t i = 0; i != N; ++i) { UNIT_ASSERT_EQUAL(i, sets.CmpSet.begin()->GetElement(0).Get()); NUdf::TUnboxedValue s = sets.CmpSet.begin()->GetElement(1); UNIT_ASSERT_EQUAL(i, s.AsStringRef().Size()); sets.CmpSet.erase(sets.CmpSet.begin()); } } Y_UNIT_TEST(ReleaseAllResources) { auto setup = std::make_shared(); auto guard = Guard(setup->Alloc); TTestedSets intSets{setup->TypeBuilder.NewDataType(NUdf::EDataSlot::Int32)}; TTestedSets stringSets{setup->TypeBuilder.NewDataType(NUdf::EDataSlot::String)}; TType* tupleElems[] = { setup->TypeBuilder.NewDataType(NUdf::EDataSlot::Uint32), setup->TypeBuilder.NewDataType(NUdf::EDataSlot::String) }; TTestedSets tupleSets{setup->TypeBuilder.NewTupleType(tupleElems)}; std::pair structElems[] = { std::pair{"i", setup->TypeBuilder.NewDataType(NUdf::EDataSlot::Uint32)}, std::pair{"s", setup->TypeBuilder.NewDataType(NUdf::EDataSlot::String)} }; TTestedSets structSets{setup->TypeBuilder.NewStructType(structElems)}; intSets.Reset(); stringSets.Reset(); tupleSets.Reset(); structSets.Reset(); guard.Release(); setup.reset(); } } } //namespace namespace NKikimr::NMiniKQL