#include "proto_builder.h" #include "value_builder.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace NYql; using namespace NKikimr::NMiniKQL; namespace { struct TSetup { TSetup() : Alloc(__LOCATION__) , Env(Alloc) , FunctionRegistry(CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr())) , TypeInfoHelper(new TTypeInfoHelper()) , FunctionTypeInfoBuilder(Env, TypeInfoHelper, "", nullptr, {}) , PgmBuilder(Env, *FunctionRegistry) , MemInfo("Test") , HolderFactory(Alloc.Ref(), MemInfo) , ValueBuilder(HolderFactory, NUdf::EValidatePolicy::Exception) { } TScopedAlloc Alloc; TTypeEnvironment Env; IFunctionRegistry::TPtr FunctionRegistry; NUdf::ITypeInfoHelper::TPtr TypeInfoHelper; TFunctionTypeInfoBuilder FunctionTypeInfoBuilder; TProgramBuilder PgmBuilder; TMemoryUsageInfo MemInfo; THolderFactory HolderFactory; TDefaultValueBuilder ValueBuilder; }; template TString YsonToProtoText(TSetup& setup, NUdf::TProtoInfo& info, TStringBuf yson) { TStringStream err; auto val = NCommon::ParseYsonValue( setup.HolderFactory, NYT::NodeToYsonString(NYT::NodeFromYsonString(yson), ::NYson::EYsonFormat::Binary), static_cast(info.StructType), 0, &err, true); if (!val) { throw yexception() << err.Str(); } TProto proto; FillProtoFromValue(*val, proto, info); TString res; NProtoBuf::TextFormat::Printer printer; printer.SetSingleLineMode(true); printer.SetUseShortRepeatedPrimitives(true); if (!printer.PrintToString(proto, &res)) { throw yexception() << "Proto printer failed"; } return StripString(res); } class TTestWriter : public NCommon::IBlockWriter { public: TTestWriter() : Buffer_(1024) { } void SetRecordBoundaryCallback(std::function /*callback*/) override { } std::pair NextEmptyBlock() override { auto ptr = Buffer_.Current(); return {ptr, ptr + Buffer_.Left()}; } void ReturnBlock(size_t avail, std::optional /*lastRecordBoundary*/) override { Buffer_.Proceed(avail); } void Finish() override { } TStringBuf Str() const { return {Buffer_.Data(), Buffer_.Filled()}; } private: TTempBuf Buffer_; }; template TString ProtoTextToYson(TSetup& setup, NUdf::TProtoInfo& info, TStringBuf protoText) { TProto proto; if (!NProtoBuf::TextFormat::ParseFromString(TString{protoText}, &proto)) { throw yexception() << "Failed to parse proto"; } auto value = FillValueFromProto(proto, &setup.ValueBuilder, info); TTestWriter out; NCommon::TOutputBuf buf(out, nullptr); NCommon::WriteYsonValueInTableFormat(buf, static_cast(info.StructType), 0, value, true); buf.Finish(); return NYT::NodeToYsonString(NYT::NodeFromYsonString(out.Str()), ::NYson::EYsonFormat::Text); } } // unnamed Y_UNIT_TEST_SUITE(TProtobufValueBuilderTests) { template void TestFloatSingle() { TSetup setup; NUdf::TProtoInfo info; info.YtMode = YTMODE; NUdf::ProtoTypeBuild(setup.FunctionTypeInfoBuilder, &info); UNIT_ASSERT_VALUES_EQUAL( YsonToProtoText(setup, info, "{FloatField=0.5}"), "FloatField: 0.5" ); UNIT_ASSERT_VALUES_EQUAL( YsonToProtoText(setup, info, "{FloatField=0.}"), "FloatField: 0" ); UNIT_ASSERT_VALUES_EQUAL( YsonToProtoText(setup, info, "{FloatField=-0.33333333}"), "FloatField: -0.333333343" ); UNIT_ASSERT_VALUES_EQUAL( YsonToProtoText(setup, info, "{FloatField=%-inf}"), "FloatField: -inf" ); UNIT_ASSERT_VALUES_EQUAL( YsonToProtoText(setup, info, "{FloatField=%nan}"), "FloatField: nan" ); UNIT_ASSERT_VALUES_EQUAL( ProtoTextToYson(setup, info, "FloatField: 0.5"), "[#;#;#;#;#;[0.5];#;#;#;#;#;#;#;#]" ); UNIT_ASSERT_VALUES_EQUAL( ProtoTextToYson(setup, info, "FloatField: 0"), "[#;#;#;#;#;[0.];#;#;#;#;#;#;#;#]" ); UNIT_ASSERT_VALUES_EQUAL( ProtoTextToYson(setup, info, "FloatField: -0.33333333"), "[#;#;#;#;#;[-0.3333333433];#;#;#;#;#;#;#;#]" ); UNIT_ASSERT_VALUES_EQUAL( ProtoTextToYson(setup, info, "FloatField: -inf"), "[#;#;#;#;#;[%-inf];#;#;#;#;#;#;#;#]" ); UNIT_ASSERT_VALUES_EQUAL( ProtoTextToYson(setup, info, "FloatField: nan"), "[#;#;#;#;#;[%nan];#;#;#;#;#;#;#;#]" ); } Y_UNIT_TEST(FloatSingleYtMode) { TestFloatSingle(); } Y_UNIT_TEST(FloatSingle) { TestFloatSingle(); } template void TestFloatRepeated() { TSetup setup; NUdf::TProtoInfo info; info.YtMode = YTMODE; info.OptionalLists = true; NUdf::ProtoTypeBuild(setup.FunctionTypeInfoBuilder, &info); UNIT_ASSERT_VALUES_EQUAL( YsonToProtoText(setup, info, "{FloatField=[0.; -0.33333333; 0.5; 1.0; %inf; %nan]}"), "FloatField: [0, -0.333333343, 0.5, 1, inf, nan]" ); UNIT_ASSERT_VALUES_EQUAL( ProtoTextToYson(setup, info, "FloatField: [0, -0.33333333, 0.5, 1, inf, nan]"), "[[[0.;-0.3333333433;0.5;1.;%inf;%nan]];#]" ); } Y_UNIT_TEST(FloatRepeatedYtMode) { TestFloatRepeated(); } Y_UNIT_TEST(FloatRepeated) { TestFloatRepeated(); } template void TestFloatDefaults() { TSetup setup; NUdf::TProtoInfo info; info.YtMode = YTMODE; info.OptionalLists = true; NUdf::ProtoTypeBuild(setup.FunctionTypeInfoBuilder, &info); UNIT_ASSERT_VALUES_EQUAL( ProtoTextToYson(setup, info, " "), "[[0.];[0.5];[%inf];[%nan]]" ); } Y_UNIT_TEST(FloatDefaultsYtMode) { TestFloatDefaults(); } Y_UNIT_TEST(FloatDefaults) { TestFloatDefaults(); } };