value_builder_ut.cpp 7.5 KB

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