#include #include #include #include #include #include #include #include namespace NKikimr::NMiniKQL { using namespace NTest; namespace { constexpr size_t LargeStringLength = MaxBlockSizeInBytes / 10; template void TestBlockVariantItem(const TVector& data, const TVector& expected) { TBlockHelper().TestKernelFuzzied(data, expected, [](TSetup& setup, TRuntimeNode variantValue) { return setup.PgmBuilder->BlockVariantItem(variantValue); }); } template auto ExtractCommonAlternative(const std::variant& variant) { return std::visit([](const auto& alternativeValue) { return alternativeValue; }, variant); } template TVector()))> ExtractCommonAlternatives(const TVector& data) { TVector()))> expected; expected.reserve(data.size()); for (const auto& variant : data) { expected.push_back(ExtractCommonAlternative(variant)); } return expected; } } // namespace Y_UNIT_TEST_SUITE(TMiniKQLBlockVariantItemTest) { Y_UNIT_TEST(TupleVariant_Ui32_TwoAlternatives) { using TVariant = std::variant; TVector data = { TVariant(std::in_place_index<0>, 1u), TVariant(std::in_place_index<1>, 2u), TVariant(std::in_place_index<0>, 3u), }; TVector expected = {1u, 2u, 3u}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_Ui32_ThreeAlternatives) { using TVariant = std::variant; TVector data = { TVariant(std::in_place_index<0>, 1u), TVariant(std::in_place_index<1>, 2u), TVariant(std::in_place_index<2>, 3u), TVariant(std::in_place_index<0>, 4u), }; TVector expected = {1u, 2u, 3u, 4u}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_TString_TwoAlternatives) { using TVariant = std::variant; TVector data = { TVariant(std::in_place_index<0>, TString{"hello"}), TVariant(std::in_place_index<1>, TString{"world"}), TVariant(std::in_place_index<0>, TString{""}), }; TVector expected = {"hello", "world", ""}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_NestedTuple_TwoAlternatives) { using TInner = std::tuple; using TVariant = std::variant; TVector data = { TVariant(std::in_place_index<0>, TInner{1u, "a"}), TVariant(std::in_place_index<1>, TInner{2u, "b"}), TVariant(std::in_place_index<0>, TInner{3u, "c"}), }; TVector expected = {TInner{1u, "a"}, TInner{2u, "b"}, TInner{3u, "c"}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_NestedVariant_TwoAlternatives) { using TInner = std::variant; using TVariant = std::variant; TVector data = { TVariant(std::in_place_index<0>, TInner(std::in_place_index<0>, 1u)), TVariant(std::in_place_index<1>, TInner(std::in_place_index<1>, 2u)), TVariant(std::in_place_index<0>, TInner(std::in_place_index<1>, 3u)), }; TVector expected = ExtractCommonAlternatives(data); TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_OptionalInnerUi32_TwoAlternatives) { using TInner = TMaybe; using TVariant = std::variant; TVector data = { TVariant(std::in_place_index<0>, TInner{10u}), TVariant(std::in_place_index<1>, TInner{}), TVariant(std::in_place_index<0>, TInner{20u}), }; TVector> expected = {TInner{10u}, TInner{}, TInner{20u}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_OptionalInnerString_TwoAlternatives) { using TInner = TMaybe; using TVariant = std::variant; TVector data = { TVariant(std::in_place_index<0>, TInner{"first"}), TVariant(std::in_place_index<1>, TInner{}), TVariant(std::in_place_index<1>, TInner{"second"}), }; TVector> expected = {TInner{"first"}, TInner{}, TInner{"second"}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(OptionalTupleVariant_Ui32_NullRows) { using TVariant = std::variant; TVector> data = { TMaybe{TVariant(std::in_place_index<0>, 1u)}, TMaybe{}, TMaybe{TVariant(std::in_place_index<1>, 3u)}, }; TVector> expected = {ui32{1u}, Nothing(), ui32{3u}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(OptionalTupleVariant_TString_MixedNull) { using TVariant = std::variant; TVector> data = { TMaybe{TVariant(std::in_place_index<0>, TString{"hello"})}, TMaybe{}, TMaybe{TVariant(std::in_place_index<1>, TString{"world"})}, TMaybe{}, }; TVector> expected = {TString{"hello"}, Nothing(), TString{"world"}, Nothing()}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(OptionalTupleVariant_NestedTuple_MixedNull) { using TInner = std::tuple; using TVariant = std::variant; TVector> data = { TMaybe{TVariant(std::in_place_index<0>, TInner{1u, "a"})}, TMaybe{}, TMaybe{TVariant(std::in_place_index<1>, TInner{2u, "b"})}, }; TVector> expected = {TInner{1u, "a"}, Nothing(), TInner{2u, "b"}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(OptionalTupleVariant_OptionalInnerUi32_MixedNull) { using TInner = TMaybe; using TVariant = std::variant; TVector> data = { TMaybe{TVariant(std::in_place_index<0>, TInner{10u})}, TMaybe{TVariant(std::in_place_index<0>, TInner{})}, TMaybe{}, TMaybe{TVariant(std::in_place_index<1>, TInner{20u})}, TMaybe{TVariant(std::in_place_index<1>, TInner{})}, }; TVector> expected = { TMaybe{TInner{10u}}, TMaybe{TInner{}}, TMaybe{}, TMaybe{TInner{20u}}, TMaybe{TInner{}}, }; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(StructVariant_Ui32_TwoMembers) { using TMemberA = NTest::TStructMember<"a", ui32>; using TMemberB = NTest::TStructMember<"b", ui32>; using TVariant = NTest::TStructVariant; TVector data = {TVariant{TMemberA{1}}, TVariant{TMemberB{2}}, TVariant{TMemberA{3}}}; TVector expected = {1u, 2u, 3u}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(StructVariant_Ui32_ThreeMembers) { using TMemberA = NTest::TStructMember<"a", ui32>; using TMemberB = NTest::TStructMember<"b", ui32>; using TMemberC = NTest::TStructMember<"c", ui32>; using TVariant = NTest::TStructVariant; TVector data = {TVariant{TMemberA{1}}, TVariant{TMemberB{2}}, TVariant{TMemberC{3}}, TVariant{TMemberA{4}}}; TVector expected = {1u, 2u, 3u, 4u}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(StructVariant_TString_TwoMembers) { using TMemberA = NTest::TStructMember<"a", TString>; using TMemberB = NTest::TStructMember<"b", TString>; using TVariant = NTest::TStructVariant; TVector data = {TVariant{TMemberA{"hello"}}, TVariant{TMemberB{"world"}}, TVariant{TMemberA{""}}}; TVector expected = {"hello", "world", ""}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(StructVariant_NestedTuple_TwoMembers) { using TInner = std::tuple; using TMemberA = NTest::TStructMember<"a", TInner>; using TMemberB = NTest::TStructMember<"b", TInner>; using TVariant = NTest::TStructVariant; TVector data = {TVariant{TMemberA{TInner{1u, "a"}}}, TVariant{TMemberB{TInner{2u, "b"}}}}; TVector expected = {TInner{1u, "a"}, TInner{2u, "b"}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(OptionalStructVariant_Ui32_MixedNull) { using TMemberA = NTest::TStructMember<"a", ui32>; using TMemberB = NTest::TStructMember<"b", ui32>; using TVariant = NTest::TStructVariant; TVector> data = { TMaybe{TVariant{TMemberA{1}}}, TMaybe{}, TMaybe{TVariant{TMemberB{2}}}, }; TVector> expected = {ui32{1u}, Nothing(), ui32{2u}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(OptionalStructVariant_TString_MixedNull) { using TMemberA = NTest::TStructMember<"a", TString>; using TMemberB = NTest::TStructMember<"b", TString>; using TVariant = NTest::TStructVariant; TVector> data = { TMaybe{TVariant{TMemberA{"hello"}}}, TMaybe{}, TMaybe{TVariant{TMemberB{"world"}}}, }; TVector> expected = {TString{"hello"}, Nothing(), TString{"world"}}; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(OptionalStructVariant_OptionalInnerUi32_MixedNull) { using TInner = TMaybe; using TMemberA = NTest::TStructMember<"a", TInner>; using TMemberB = NTest::TStructMember<"b", TInner>; using TVariant = NTest::TStructVariant; TVector> data = { TMaybe{TVariant{TMemberA{TInner{10u}}}}, TMaybe{TVariant{TMemberA{TInner{}}}}, TMaybe{}, TMaybe{TVariant{TMemberB{TInner{20u}}}}, TMaybe{TVariant{TMemberB{TInner{}}}}, }; TVector> expected = { TMaybe{TInner{10u}}, TMaybe{TInner{}}, TMaybe{}, TMaybe{TInner{20u}}, TMaybe{TInner{}}, }; TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_Ui32_Fuzzied) { using TVariant = std::variant; auto rng = CreateDeterministicRandomProvider(200); const TVector data = NYql::GenerateRandomData(rng, 7); const TVector expected = ExtractCommonAlternatives(data); TestBlockVariantItem(data, expected); } Y_UNIT_TEST(TupleVariant_LargeString_ChunkedOutput) { using TVariant = std::variant; auto rng = CreateDeterministicRandomProvider(201); TBlockHelper helper; helper.WithScopedFuzzers([&]() { const NYql::TGeneratorSettings settings{ .Weights = {1.0, 1.0}, .InnerSettings = { NYql::TGeneratorSettings{.MinSize = 0, .MaxSize = LargeStringLength}, NYql::TGeneratorSettings{.MinSize = 0, .MaxSize = LargeStringLength}, }, }; const TVector data = NYql::GenerateRandomData(rng, settings, 50); const TVector expected = ExtractCommonAlternatives(data); helper.RunNodeOverWideStream( expected, [](TSetup& setup, TRuntimeNode variantBlock) { return setup.PgmBuilder->BlockVariantItem(variantBlock); }, data); }); } } // Y_UNIT_TEST_SUITE(TMiniKQLBlockVariantItemTest) } // namespace NKikimr::NMiniKQL