value_builder_ut.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "proto_builder.h"
  2. #include "value_builder.h"
  3. #include <yql/essentials/minikql/protobuf_udf/ut/protobuf_ut.pb.h>
  4. #include <yql/essentials/providers/common/codec/yql_codec.h>
  5. #include <yql/essentials/providers/common/codec/yql_codec_buf.h>
  6. #include <yt/yql/providers/yt/codec/yt_codec.h>
  7. #include <yql/essentials/minikql/mkql_alloc.h>
  8. #include <yql/essentials/minikql/mkql_node.h>
  9. #include <yql/essentials/minikql/mkql_type_builder.h>
  10. #include <yql/essentials/minikql/mkql_program_builder.h>
  11. #include <yql/essentials/minikql/mkql_function_registry.h>
  12. #include <yql/essentials/minikql/computation/mkql_value_builder.h>
  13. #include <yql/essentials/public/udf/udf_types.h>
  14. #include <google/protobuf/text_format.h>
  15. #include <library/cpp/yson/node/node_io.h>
  16. #include <library/cpp/testing/unittest/registar.h>
  17. #include <util/generic/strbuf.h>
  18. #include <util/generic/string.h>
  19. #include <util/stream/str.h>
  20. #include <util/string/strip.h>
  21. #include <util/memory/tempbuf.h>
  22. using namespace NYql;
  23. using namespace NKikimr::NMiniKQL;
  24. namespace {
  25. struct TSetup {
  26. TSetup()
  27. : Alloc(__LOCATION__)
  28. , Env(Alloc)
  29. , FunctionRegistry(CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr()))
  30. , TypeInfoHelper(new TTypeInfoHelper())
  31. , FunctionTypeInfoBuilder(Env, TypeInfoHelper, "", nullptr, {})
  32. , PgmBuilder(Env, *FunctionRegistry)
  33. , MemInfo("Test")
  34. , HolderFactory(Alloc.Ref(), MemInfo)
  35. , ValueBuilder(HolderFactory, NUdf::EValidatePolicy::Exception)
  36. {
  37. }
  38. TScopedAlloc Alloc;
  39. TTypeEnvironment Env;
  40. IFunctionRegistry::TPtr FunctionRegistry;
  41. NUdf::ITypeInfoHelper::TPtr TypeInfoHelper;
  42. TFunctionTypeInfoBuilder FunctionTypeInfoBuilder;
  43. TProgramBuilder PgmBuilder;
  44. TMemoryUsageInfo MemInfo;
  45. THolderFactory HolderFactory;
  46. TDefaultValueBuilder ValueBuilder;
  47. };
  48. template <typename TProto>
  49. TString YsonToProtoText(TSetup& setup, NUdf::TProtoInfo& info, TStringBuf yson) {
  50. TStringStream err;
  51. auto val = ParseYsonValueInTableFormat(
  52. setup.HolderFactory,
  53. NYT::NodeToYsonString(NYT::NodeFromYsonString(yson), ::NYson::EYsonFormat::Binary),
  54. static_cast<NKikimr::NMiniKQL::TStructType*>(info.StructType),
  55. 0,
  56. &err);
  57. if (!val) {
  58. throw yexception() << err.Str();
  59. }
  60. TProto proto;
  61. FillProtoFromValue(*val, proto, info);
  62. TString res;
  63. NProtoBuf::TextFormat::Printer printer;
  64. printer.SetSingleLineMode(true);
  65. printer.SetUseShortRepeatedPrimitives(true);
  66. if (!printer.PrintToString(proto, &res)) {
  67. throw yexception() << "Proto printer failed";
  68. }
  69. return StripString(res);
  70. }
  71. class TTestWriter : public NCommon::IBlockWriter {
  72. public:
  73. TTestWriter()
  74. : Buffer_(1024)
  75. {
  76. }
  77. void SetRecordBoundaryCallback(std::function<void()> /*callback*/) override {
  78. }
  79. std::pair<char*, char*> NextEmptyBlock() override {
  80. auto ptr = Buffer_.Current();
  81. return {ptr, ptr + Buffer_.Left()};
  82. }
  83. void ReturnBlock(size_t avail, std::optional<size_t> /*lastRecordBoundary*/) override {
  84. Buffer_.Proceed(avail);
  85. }
  86. void Finish() override {
  87. }
  88. TStringBuf Str() const {
  89. return {Buffer_.Data(), Buffer_.Filled()};
  90. }
  91. private:
  92. TTempBuf Buffer_;
  93. };
  94. template <typename TProto>
  95. TString ProtoTextToYson(TSetup& setup, NUdf::TProtoInfo& info, TStringBuf protoText) {
  96. TProto proto;
  97. if (!NProtoBuf::TextFormat::ParseFromString(TString{protoText}, &proto)) {
  98. throw yexception() << "Failed to parse proto";
  99. }
  100. auto value = FillValueFromProto(proto, &setup.ValueBuilder, info);
  101. TTestWriter out;
  102. NCommon::TOutputBuf buf(out, nullptr);
  103. WriteYsonValueInTableFormat(buf, static_cast<NKikimr::NMiniKQL::TStructType*>(info.StructType), 0, value, true);
  104. buf.Finish();
  105. return NYT::NodeToYsonString(NYT::NodeFromYsonString(out.Str()), ::NYson::EYsonFormat::Text);
  106. }
  107. } // unnamed
  108. Y_UNIT_TEST_SUITE(TProtobufValueBuilderTests) {
  109. template <bool YTMODE>
  110. void TestFloatSingle() {
  111. TSetup setup;
  112. NUdf::TProtoInfo info;
  113. info.YtMode = YTMODE;
  114. NUdf::ProtoTypeBuild<NYql::NProtoTest::TIntegral>(setup.FunctionTypeInfoBuilder, &info);
  115. UNIT_ASSERT_VALUES_EQUAL(
  116. YsonToProtoText<NYql::NProtoTest::TIntegral>(setup, info, "{FloatField=0.5}"),
  117. "FloatField: 0.5"
  118. );
  119. UNIT_ASSERT_VALUES_EQUAL(
  120. YsonToProtoText<NYql::NProtoTest::TIntegral>(setup, info, "{FloatField=0.}"),
  121. "FloatField: 0"
  122. );
  123. UNIT_ASSERT_VALUES_EQUAL(
  124. YsonToProtoText<NYql::NProtoTest::TIntegral>(setup, info, "{FloatField=-0.33333333}"),
  125. "FloatField: -0.333333343"
  126. );
  127. UNIT_ASSERT_VALUES_EQUAL(
  128. YsonToProtoText<NYql::NProtoTest::TIntegral>(setup, info, "{FloatField=%-inf}"),
  129. "FloatField: -inf"
  130. );
  131. UNIT_ASSERT_VALUES_EQUAL(
  132. YsonToProtoText<NYql::NProtoTest::TIntegral>(setup, info, "{FloatField=%nan}"),
  133. "FloatField: nan"
  134. );
  135. UNIT_ASSERT_VALUES_EQUAL(
  136. ProtoTextToYson<NYql::NProtoTest::TIntegral>(setup, info, "FloatField: 0.5"),
  137. "[#;#;#;#;#;[0.5];#;#;#;#;#;#;#;#]"
  138. );
  139. UNIT_ASSERT_VALUES_EQUAL(
  140. ProtoTextToYson<NYql::NProtoTest::TIntegral>(setup, info, "FloatField: 0"),
  141. "[#;#;#;#;#;[0.];#;#;#;#;#;#;#;#]"
  142. );
  143. UNIT_ASSERT_VALUES_EQUAL(
  144. ProtoTextToYson<NYql::NProtoTest::TIntegral>(setup, info, "FloatField: -0.33333333"),
  145. "[#;#;#;#;#;[-0.3333333433];#;#;#;#;#;#;#;#]"
  146. );
  147. UNIT_ASSERT_VALUES_EQUAL(
  148. ProtoTextToYson<NYql::NProtoTest::TIntegral>(setup, info, "FloatField: -inf"),
  149. "[#;#;#;#;#;[%-inf];#;#;#;#;#;#;#;#]"
  150. );
  151. UNIT_ASSERT_VALUES_EQUAL(
  152. ProtoTextToYson<NYql::NProtoTest::TIntegral>(setup, info, "FloatField: nan"),
  153. "[#;#;#;#;#;[%nan];#;#;#;#;#;#;#;#]"
  154. );
  155. }
  156. Y_UNIT_TEST(FloatSingleYtMode) {
  157. TestFloatSingle<true>();
  158. }
  159. Y_UNIT_TEST(FloatSingle) {
  160. TestFloatSingle<false>();
  161. }
  162. template <bool YTMODE>
  163. void TestFloatRepeated() {
  164. TSetup setup;
  165. NUdf::TProtoInfo info;
  166. info.YtMode = YTMODE;
  167. info.OptionalLists = true;
  168. NUdf::ProtoTypeBuild<NYql::NProtoTest::TRepeated>(setup.FunctionTypeInfoBuilder, &info);
  169. UNIT_ASSERT_VALUES_EQUAL(
  170. YsonToProtoText<NYql::NProtoTest::TRepeated>(setup, info, "{FloatField=[0.; -0.33333333; 0.5; 1.0; %inf; %nan]}"),
  171. "FloatField: [0, -0.333333343, 0.5, 1, inf, nan]"
  172. );
  173. UNIT_ASSERT_VALUES_EQUAL(
  174. ProtoTextToYson<NYql::NProtoTest::TRepeated>(setup, info, "FloatField: [0, -0.33333333, 0.5, 1, inf, nan]"),
  175. "[[[0.;-0.3333333433;0.5;1.;%inf;%nan]];#]"
  176. );
  177. }
  178. Y_UNIT_TEST(FloatRepeatedYtMode) {
  179. TestFloatRepeated<true>();
  180. }
  181. Y_UNIT_TEST(FloatRepeated) {
  182. TestFloatRepeated<false>();
  183. }
  184. template <bool YTMODE>
  185. void TestFloatDefaults() {
  186. TSetup setup;
  187. NUdf::TProtoInfo info;
  188. info.YtMode = YTMODE;
  189. info.OptionalLists = true;
  190. NUdf::ProtoTypeBuild<NYql::NProtoTest::TWithDefaults>(setup.FunctionTypeInfoBuilder, &info);
  191. UNIT_ASSERT_VALUES_EQUAL(
  192. ProtoTextToYson<NYql::NProtoTest::TWithDefaults>(setup, info, " "),
  193. "[[0.];[0.5];[%inf];[%nan]]"
  194. );
  195. }
  196. Y_UNIT_TEST(FloatDefaultsYtMode) {
  197. TestFloatDefaults<true>();
  198. }
  199. Y_UNIT_TEST(FloatDefaults) {
  200. TestFloatDefaults<false>();
  201. }
  202. };