#include #include #include #include #include #include #include #include #include namespace NKikimr::NMiniKQL { using namespace NTest; namespace { template void TestBlockWay(const TVector& data, const TVector& expected) { TBlockHelper().TestKernelFuzzied(data, expected, [](TSetup& setup, TRuntimeNode variantValue) { return setup.PgmBuilder->BlockWay(variantValue); }); } template using TRepeatedNameMember = NTest::TStructMember(Fill), ui32>; } // namespace Y_UNIT_TEST_SUITE(TMiniKQLBlockWayTest) { Y_UNIT_TEST(TupleVariant_Ui32Ui64_Mixed) { using TVariant = std::variant; TVector data = {TVariant{ui32{1}}, TVariant{ui64{2}}, TVariant{ui32{3}}}; TVector expected = {0u, 1u, 0u}; TestBlockWay(data, expected); } Y_UNIT_TEST(TupleVariant_AllIndex0) { using TVariant = std::variant; TVector data = {TVariant{ui32{10}}, TVariant{ui32{20}}, TVariant{ui32{30}}}; TVector expected = {0u, 0u, 0u}; TestBlockWay(data, expected); } Y_UNIT_TEST(TupleVariant_AllIndex1) { using TVariant = std::variant; TVector data = {TVariant{ui64{10}}, TVariant{ui64{20}}, TVariant{ui64{30}}}; TVector expected = {1u, 1u, 1u}; TestBlockWay(data, expected); } Y_UNIT_TEST(TupleVariant_StringAlternative) { using TVariant = std::variant; TVector data = {TVariant{ui32{42}}, TVariant{TString{"hello"}}, TVariant{ui32{7}}}; TVector expected = {0u, 1u, 0u}; TestBlockWay(data, expected); } Y_UNIT_TEST(TupleVariant_InnerOptional) { using TVariant = std::variant, ui64>; TVector data = {TVariant{TMaybe{10u}}, TVariant{ui64{20u}}, TVariant{TMaybe{}}}; TVector expected = {0u, 1u, 0u}; TestBlockWay(data, expected); } Y_UNIT_TEST(OptionalTupleVariant_MixedNull) { using TVariant = std::variant; TVector> data = {TMaybe{TVariant{ui32{1}}}, TMaybe{}, TMaybe{TVariant{ui64{2}}}}; TVector> expected = {ui32{0}, Nothing(), ui32{1}}; TestBlockWay(data, expected); } Y_UNIT_TEST(OptionalTupleVariant_AllNull) { using TVariant = std::variant; TVector> data = {TMaybe{}, TMaybe{}, TMaybe{}}; TVector> expected = {Nothing(), Nothing(), Nothing()}; TestBlockWay(data, expected); } Y_UNIT_TEST(OptionalTupleVariant_NoNull) { using TVariant = std::variant; TVector> data = {TMaybe{TVariant{ui32{1}}}, TMaybe{TVariant{ui64{2}}}, TMaybe{TVariant{ui32{3}}}}; TVector> expected = {ui32{0}, ui32{1}, ui32{0}}; TestBlockWay(data, expected); } Y_UNIT_TEST(StructVariant_NonOptional_MemberNames) { using TMemberA = NTest::TStructMember<"a", ui32>; using TMemberB = NTest::TStructMember<"b_name_longer_than_sixteen_bytes", ui64>; using TMemberC = NTest::TStructMember<"c", double>; using TVariant = NTest::TStructVariant; TVector data = {TVariant{TMemberA{1}}, TVariant{TMemberB{2}}, TVariant{TMemberC{3}}, TVariant{TMemberA{4}}, TVariant{TMemberB{5}}}; TVector expected = {TUtf8("a"), TUtf8("b_name_longer_than_sixteen_bytes"), TUtf8("c"), TUtf8("a"), TUtf8("b_name_longer_than_sixteen_bytes")}; TestBlockWay(data, expected); } Y_UNIT_TEST(StructVariant_Optional_MixedNull) { using TFirstMember = NTest::TStructMember<"x", ui32>; using TSecondMember = NTest::TStructMember<"y", ui64>; using TVariant = NTest::TStructVariant; auto elem1 = TMaybe(TFirstMember{1}); auto elem2 = Nothing(); auto elem3 = TMaybe(TSecondMember{2}); auto elem4 = TMaybe(TFirstMember{3}); TVector> items = {elem1, elem2, elem3, elem4}; TVector> expected = { TMaybe{"x"}, TMaybe{}, TMaybe{"y"}, TMaybe{"x"}, }; TestBlockWay(items, expected); } Y_UNIT_TEST(StructVariant_LongNames_ChunkedOutput) { constexpr size_t ItemsPerIteration = 10000; constexpr size_t NameLength = 100; static_assert(NameLength * ItemsPerIteration > MaxBlockSizeInBytes, "Output must overflow a single block"); using TVariant = NTest::TStructVariant< TRepeatedNameMember<'a', NameLength>, TRepeatedNameMember<'b', NameLength>, TRepeatedNameMember<'c', NameLength>>; auto rng = CreateDeterministicRandomProvider(7); TBlockHelper helper; helper.WithScopedFuzzers([&] { size_t randomSize = rng->GenRand() % ItemsPerIteration; const TVector data = NYql::GenerateRandomData(rng, randomSize); TVector expected; expected.reserve(data.size()); for (const auto& value : data) { expected.emplace_back(value.Name()); } helper.RunNodeOverWideStream( expected, [](TSetup& setup, TRuntimeNode variantBlock) { return setup.PgmBuilder->BlockWay(variantBlock); }, data); }); } Y_UNIT_TEST(StructVariant_LongNames_ChunkedOutput_Optional) { constexpr size_t ItemsPerIteration = 10000; constexpr size_t NameLength = 100; static_assert(NameLength * ItemsPerIteration > MaxBlockSizeInBytes, "Output must overflow a single block"); using TVariant = TMaybe< NTest::TStructVariant< TRepeatedNameMember<'a', NameLength>, TRepeatedNameMember<'b', NameLength>, TRepeatedNameMember<'c', NameLength>>>; auto rng = CreateDeterministicRandomProvider(7); TBlockHelper helper; helper.WithScopedFuzzers([&] { size_t randomSize = rng->GenRand() % ItemsPerIteration; const TVector data = NYql::GenerateRandomData(rng, randomSize); TVector> expected; expected.reserve(data.size()); for (const auto& value : data) { if (value) { expected.emplace_back(value->Name()); } else { expected.emplace_back(Nothing()); } } helper.RunNodeOverWideStream( expected, [](TSetup& setup, TRuntimeNode variantBlock) { return setup.PgmBuilder->BlockWay(variantBlock); }, data); }); } Y_UNIT_TEST(TupleVariant_Scalar) { using TVariant = std::variant; TBlockHelper().RunNodeOverWideStream( ui32{1}, [](TSetup& setup, TRuntimeNode variantBlock) { return setup.PgmBuilder->BlockWay(variantBlock); }, TVariant{ui64{42}}); } Y_UNIT_TEST(StructVariant_Scalar) { using TMemberAlpha = NTest::TStructMember<"alpha", ui32>; using TMemberBeta = NTest::TStructMember<"beta_member_longer_than_sixteen_bytes", ui64>; using TVariant = NTest::TStructVariant; TBlockHelper().RunNodeOverWideStream( TUtf8(TString("beta_member_longer_than_sixteen_bytes")), [](TSetup& setup, TRuntimeNode variantBlock) { return setup.PgmBuilder->BlockWay(variantBlock); }, TVariant{TMemberBeta{ui64{7}}}); } } // Y_UNIT_TEST_SUITE(TMiniKQLBlockWayTest) } // namespace NKikimr::NMiniKQL