protobuf_table_schema_ut.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #include "common.h"
  2. #include "errors.h"
  3. #include "common_ut.h"
  4. #include "util/generic/fwd.h"
  5. #include <yt/cpp/mapreduce/interface/protobuf_table_schema_ut.pb.h>
  6. #include <yt/cpp/mapreduce/interface/proto3_ut.pb.h>
  7. #include <yt/cpp/mapreduce/tests/yt_unittest_lib/yt_unittest_lib.h>
  8. #include <library/cpp/testing/unittest/registar.h>
  9. #include <algorithm>
  10. using namespace NYT;
  11. bool IsFieldPresent(const TTableSchema& schema, TStringBuf name)
  12. {
  13. for (const auto& field : schema.Columns()) {
  14. if (field.Name() == name) {
  15. return true;
  16. }
  17. }
  18. return false;
  19. }
  20. Y_UNIT_TEST_SUITE(ProtoSchemaTest_Simple)
  21. {
  22. Y_UNIT_TEST(TIntegral)
  23. {
  24. const auto schema = CreateTableSchema<NUnitTesting::TIntegral>();
  25. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  26. .AddColumn(TColumnSchema().Name("DoubleField").Type(ToTypeV3(EValueType::VT_DOUBLE, false)))
  27. .AddColumn(TColumnSchema().Name("FloatField").Type(ToTypeV3(EValueType::VT_DOUBLE, false)))
  28. .AddColumn(TColumnSchema().Name("Int32Field").Type(ToTypeV3(EValueType::VT_INT32, false)))
  29. .AddColumn(TColumnSchema().Name("Int64Field").Type(ToTypeV3(EValueType::VT_INT64, false)))
  30. .AddColumn(TColumnSchema().Name("Uint32Field").Type(ToTypeV3(EValueType::VT_UINT32, false)))
  31. .AddColumn(TColumnSchema().Name("Uint64Field").Type(ToTypeV3(EValueType::VT_UINT64, false)))
  32. .AddColumn(TColumnSchema().Name("Sint32Field").Type(ToTypeV3(EValueType::VT_INT32, false)))
  33. .AddColumn(TColumnSchema().Name("Sint64Field").Type(ToTypeV3(EValueType::VT_INT64, false)))
  34. .AddColumn(TColumnSchema().Name("Fixed32Field").Type(ToTypeV3(EValueType::VT_UINT32, false)))
  35. .AddColumn(TColumnSchema().Name("Fixed64Field").Type(ToTypeV3(EValueType::VT_UINT64, false)))
  36. .AddColumn(TColumnSchema().Name("Sfixed32Field").Type(ToTypeV3(EValueType::VT_INT32, false)))
  37. .AddColumn(TColumnSchema().Name("Sfixed64Field").Type(ToTypeV3(EValueType::VT_INT64, false)))
  38. .AddColumn(TColumnSchema().Name("BoolField").Type(ToTypeV3(EValueType::VT_BOOLEAN, false)))
  39. .AddColumn(TColumnSchema().Name("EnumField").Type(ToTypeV3(EValueType::VT_STRING, false))));
  40. }
  41. Y_UNIT_TEST(TOneOf)
  42. {
  43. const auto schema = CreateTableSchema<NUnitTesting::TOneOf>();
  44. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  45. .AddColumn(TColumnSchema().Name("DoubleField").Type(ToTypeV3(EValueType::VT_DOUBLE, false)))
  46. .AddColumn(TColumnSchema().Name("Int32Field").Type(ToTypeV3(EValueType::VT_INT32, false)))
  47. .AddColumn(TColumnSchema().Name("BoolField").Type(ToTypeV3(EValueType::VT_BOOLEAN, false))));
  48. }
  49. Y_UNIT_TEST(TWithRequired)
  50. {
  51. const auto schema = CreateTableSchema<NUnitTesting::TWithRequired>();
  52. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  53. .AddColumn(TColumnSchema().Name("RequiredField").Type(ToTypeV3(EValueType::VT_STRING, true)))
  54. .AddColumn(TColumnSchema().Name("NotRequiredField").Type(ToTypeV3(EValueType::VT_STRING, false))));
  55. }
  56. Y_UNIT_TEST(TAggregated)
  57. {
  58. const auto schema = CreateTableSchema<NUnitTesting::TAggregated>();
  59. UNIT_ASSERT_VALUES_EQUAL(6, schema.Columns().size());
  60. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  61. .AddColumn(TColumnSchema().Name("StringField").Type(ToTypeV3(EValueType::VT_STRING, false)))
  62. .AddColumn(TColumnSchema().Name("BytesField").Type(ToTypeV3(EValueType::VT_STRING, false)))
  63. .AddColumn(TColumnSchema().Name("NestedField").Type(ToTypeV3(EValueType::VT_STRING, false)))
  64. .AddColumn(TColumnSchema().Name("NestedRepeatedField").Type(ToTypeV3(EValueType::VT_STRING, false)))
  65. .AddColumn(TColumnSchema().Name("NestedOneOfField").Type(ToTypeV3(EValueType::VT_STRING, false)))
  66. .AddColumn(TColumnSchema().Name("NestedRecursiveField").Type(ToTypeV3(EValueType::VT_STRING, false))));
  67. }
  68. Y_UNIT_TEST(TAliased)
  69. {
  70. const auto schema = CreateTableSchema<NUnitTesting::TAliased>();
  71. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  72. .AddColumn(TColumnSchema().Name("key").Type(ToTypeV3(EValueType::VT_INT32, false)))
  73. .AddColumn(TColumnSchema().Name("subkey").Type(ToTypeV3(EValueType::VT_DOUBLE, false)))
  74. .AddColumn(TColumnSchema().Name("Data").Type(ToTypeV3(EValueType::VT_STRING, false))));
  75. }
  76. Y_UNIT_TEST(SortColumns)
  77. {
  78. const TSortColumns keys = {"key", "subkey"};
  79. const auto schema = CreateTableSchema<NUnitTesting::TAliased>(keys);
  80. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  81. .AddColumn(TColumnSchema()
  82. .Name("key")
  83. .Type(ToTypeV3(EValueType::VT_INT32, false))
  84. .SortOrder(ESortOrder::SO_ASCENDING))
  85. .AddColumn(TColumnSchema()
  86. .Name("subkey")
  87. .Type(ToTypeV3(EValueType::VT_DOUBLE, false))
  88. .SortOrder(ESortOrder::SO_ASCENDING))
  89. .AddColumn(TColumnSchema().Name("Data").Type(ToTypeV3(EValueType::VT_STRING, false))));
  90. }
  91. Y_UNIT_TEST(SortColumnsReordered)
  92. {
  93. const TSortColumns keys = {"subkey"};
  94. const auto schema = CreateTableSchema<NUnitTesting::TAliased>(keys);
  95. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  96. .AddColumn(TColumnSchema()
  97. .Name("subkey")
  98. .Type(ToTypeV3(EValueType::VT_DOUBLE, false))
  99. .SortOrder(ESortOrder::SO_ASCENDING))
  100. .AddColumn(TColumnSchema().Name("key").Type(ToTypeV3(EValueType::VT_INT32, false)))
  101. .AddColumn(TColumnSchema().Name("Data").Type(ToTypeV3(EValueType::VT_STRING, false))));
  102. }
  103. Y_UNIT_TEST(SortColumnsInvalid)
  104. {
  105. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TAliased>({"subkey", "subkey"}), yexception);
  106. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TAliased>({"key", "junk"}), yexception);
  107. }
  108. Y_UNIT_TEST(KeepFieldsWithoutExtensionTrue)
  109. {
  110. const auto schema = CreateTableSchema<NUnitTesting::TAliased>({}, true);
  111. UNIT_ASSERT(IsFieldPresent(schema, "key"));
  112. UNIT_ASSERT(IsFieldPresent(schema, "subkey"));
  113. UNIT_ASSERT(IsFieldPresent(schema, "Data"));
  114. UNIT_ASSERT(schema.Strict());
  115. }
  116. Y_UNIT_TEST(KeepFieldsWithoutExtensionFalse)
  117. {
  118. const auto schema = CreateTableSchema<NUnitTesting::TAliased>({}, false);
  119. UNIT_ASSERT(IsFieldPresent(schema, "key"));
  120. UNIT_ASSERT(IsFieldPresent(schema, "subkey"));
  121. UNIT_ASSERT(!IsFieldPresent(schema, "Data"));
  122. UNIT_ASSERT(schema.Strict());
  123. }
  124. Y_UNIT_TEST(ProtobufTypeOption)
  125. {
  126. const auto schema = CreateTableSchema<NUnitTesting::TWithTypeOptions>({});
  127. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  128. .Strict(false)
  129. .AddColumn(TColumnSchema().Name("ColorIntField").Type(ToTypeV3(EValueType::VT_INT64, false)))
  130. .AddColumn(TColumnSchema().Name("ColorStringField").Type(ToTypeV3(EValueType::VT_STRING, false)))
  131. .AddColumn(TColumnSchema().Name("AnyField").Type(ToTypeV3(EValueType::VT_ANY, false)))
  132. .AddColumn(TColumnSchema().Name("EmbeddedField").Type(
  133. NTi::Optional(NTi::Struct({
  134. {"ColorIntField", ToTypeV3(EValueType::VT_INT64, false)},
  135. {"ColorStringField", ToTypeV3(EValueType::VT_STRING, false)},
  136. {"AnyField", ToTypeV3(EValueType::VT_ANY, false)}}))))
  137. .AddColumn(TColumnSchema().Name("RepeatedEnumIntField").Type(NTi::List(NTi::Int64()))));
  138. }
  139. Y_UNIT_TEST(ProtobufTypeOption_TypeMismatch)
  140. {
  141. UNIT_ASSERT_EXCEPTION(
  142. CreateTableSchema<NUnitTesting::TWithTypeOptions_TypeMismatch_EnumInt>({}),
  143. yexception);
  144. UNIT_ASSERT_EXCEPTION(
  145. CreateTableSchema<NUnitTesting::TWithTypeOptions_TypeMismatch_EnumString>({}),
  146. yexception);
  147. UNIT_ASSERT_EXCEPTION(
  148. CreateTableSchema<NUnitTesting::TWithTypeOptions_TypeMismatch_Any>({}),
  149. yexception);
  150. UNIT_ASSERT_EXCEPTION(
  151. CreateTableSchema<NUnitTesting::TWithTypeOptions_TypeMismatch_OtherColumns>({}),
  152. yexception);
  153. }
  154. }
  155. Y_UNIT_TEST_SUITE(ProtoSchemaTest_Complex)
  156. {
  157. Y_UNIT_TEST(TRepeated)
  158. {
  159. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TRepeated>(), yexception);
  160. const auto schema = CreateTableSchema<NUnitTesting::TRepeatedYtMode>();
  161. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  162. .AddColumn(TColumnSchema().Name("Int32Field").Type(NTi::List(ToTypeV3(EValueType::VT_INT32, true)))));
  163. }
  164. Y_UNIT_TEST(TRepeatedOptionalList)
  165. {
  166. const auto schema = CreateTableSchema<NUnitTesting::TOptionalList>();
  167. auto type = NTi::Optional(NTi::List(NTi::Int64()));
  168. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  169. .AddColumn(TColumnSchema().Name("OptionalListInt64").TypeV3(type)));
  170. }
  171. NTi::TTypePtr GetUrlRowType(bool required)
  172. {
  173. static const NTi::TTypePtr structType = NTi::Struct({
  174. {"Host", ToTypeV3(EValueType::VT_STRING, false)},
  175. {"Path", ToTypeV3(EValueType::VT_STRING, false)},
  176. {"HttpCode", ToTypeV3(EValueType::VT_INT32, false)}});
  177. return required ? structType : NTi::TTypePtr(NTi::Optional(structType));
  178. }
  179. Y_UNIT_TEST(TRowFieldSerializationOption)
  180. {
  181. const auto schema = CreateTableSchema<NUnitTesting::TRowFieldSerializationOption>();
  182. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  183. .AddColumn(TColumnSchema().Name("UrlRow_1").Type(GetUrlRowType(false)))
  184. .AddColumn(TColumnSchema().Name("UrlRow_2").Type(ToTypeV3(EValueType::VT_STRING, false))));
  185. }
  186. Y_UNIT_TEST(TRowMessageSerializationOption)
  187. {
  188. const auto schema = CreateTableSchema<NUnitTesting::TRowMessageSerializationOption>();
  189. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  190. .AddColumn(TColumnSchema().Name("UrlRow_1").Type(GetUrlRowType(false)))
  191. .AddColumn(TColumnSchema().Name("UrlRow_2").Type(GetUrlRowType(false))));
  192. }
  193. Y_UNIT_TEST(TRowMixedSerializationOptions)
  194. {
  195. const auto schema = CreateTableSchema<NUnitTesting::TRowMixedSerializationOptions>();
  196. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  197. .AddColumn(TColumnSchema().Name("UrlRow_1").Type(GetUrlRowType(false)))
  198. .AddColumn(TColumnSchema().Name("UrlRow_2").Type(ToTypeV3(EValueType::VT_STRING, false))));
  199. }
  200. NTi::TTypePtr GetUrlRowType_ColumnNames(bool required)
  201. {
  202. static const NTi::TTypePtr type = NTi::Struct({
  203. {"Host_ColumnName", ToTypeV3(EValueType::VT_STRING, false)},
  204. {"Path_KeyColumnName", ToTypeV3(EValueType::VT_STRING, false)},
  205. {"HttpCode", ToTypeV3(EValueType::VT_INT32, false)},
  206. });
  207. return required ? type : NTi::TTypePtr(NTi::Optional(type));
  208. }
  209. Y_UNIT_TEST(TRowMixedSerializationOptions_ColumnNames)
  210. {
  211. const auto schema = CreateTableSchema<NUnitTesting::TRowMixedSerializationOptions_ColumnNames>();
  212. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  213. .AddColumn(TColumnSchema().Name("UrlRow_1").Type(GetUrlRowType_ColumnNames(false)))
  214. .AddColumn(TColumnSchema().Name("UrlRow_2").Type(ToTypeV3(EValueType::VT_STRING, false))));
  215. }
  216. Y_UNIT_TEST(NoOptionInheritance)
  217. {
  218. auto deepestEmbedded = NTi::Optional(NTi::Struct({{"x", ToTypeV3(EValueType::VT_INT64, false)}}));
  219. const auto schema = CreateTableSchema<NUnitTesting::TNoOptionInheritance>();
  220. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  221. .AddColumn(TColumnSchema()
  222. .Name("EmbeddedYt_YtOption")
  223. .Type(NTi::Optional(NTi::Struct({{"embedded", deepestEmbedded}}))))
  224. .AddColumn(TColumnSchema().Name("EmbeddedYt_ProtobufOption").Type(ToTypeV3(EValueType::VT_STRING, false)))
  225. .AddColumn(TColumnSchema().Name("EmbeddedYt_NoOption").Type(ToTypeV3(EValueType::VT_STRING, false)))
  226. .AddColumn(TColumnSchema()
  227. .Name("EmbeddedProtobuf_YtOption")
  228. .Type(NTi::Optional(NTi::Struct({{"embedded", ToTypeV3(EValueType::VT_STRING, false)}}))))
  229. .AddColumn(TColumnSchema().Name("EmbeddedProtobuf_ProtobufOption").Type(ToTypeV3(EValueType::VT_STRING, false)))
  230. .AddColumn(TColumnSchema().Name("EmbeddedProtobuf_NoOption").Type(ToTypeV3(EValueType::VT_STRING, false)))
  231. .AddColumn(TColumnSchema()
  232. .Name("Embedded_YtOption")
  233. .Type(NTi::Optional(NTi::Struct({{"embedded", ToTypeV3(EValueType::VT_STRING, false)}}))))
  234. .AddColumn(TColumnSchema().Name("Embedded_ProtobufOption").Type(ToTypeV3(EValueType::VT_STRING, false)))
  235. .AddColumn(TColumnSchema().Name("Embedded_NoOption").Type(ToTypeV3(EValueType::VT_STRING, false))));
  236. }
  237. Y_UNIT_TEST(Cyclic)
  238. {
  239. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TCyclic>(), TApiUsageError);
  240. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TCyclic::TA>(), TApiUsageError);
  241. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TCyclic::TB>(), TApiUsageError);
  242. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TCyclic::TC>(), TApiUsageError);
  243. UNIT_ASSERT_EXCEPTION(CreateTableSchema<NUnitTesting::TCyclic::TD>(), TApiUsageError);
  244. ASSERT_SERIALIZABLES_EQUAL(
  245. TTableSchema().AddColumn(
  246. TColumnSchema().Name("d").TypeV3(NTi::Optional(NTi::String()))),
  247. CreateTableSchema<NUnitTesting::TCyclic::TE>());
  248. }
  249. Y_UNIT_TEST(FieldSortOrder)
  250. {
  251. const auto schema = CreateTableSchema<NUnitTesting::TFieldSortOrder>();
  252. auto byFieldNumber = NTi::Optional(NTi::Struct({
  253. {"z", NTi::Optional(NTi::Bool())},
  254. {"x", NTi::Optional(NTi::Int64())},
  255. {"y", NTi::Optional(NTi::String())},
  256. }));
  257. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  258. .AddColumn(TColumnSchema().Name("EmbeddedDefault").Type(byFieldNumber))
  259. .AddColumn(TColumnSchema()
  260. .Name("EmbeddedAsInProtoFile")
  261. .Type(NTi::Optional(NTi::Struct({
  262. {"x", NTi::Optional(NTi::Int64())},
  263. {"y", NTi::Optional(NTi::String())},
  264. {"z", NTi::Optional(NTi::Bool())},
  265. }))))
  266. .AddColumn(TColumnSchema().Name("EmbeddedByFieldNumber").Type(byFieldNumber)));
  267. }
  268. Y_UNIT_TEST(Map)
  269. {
  270. const auto schema = CreateTableSchema<NUnitTesting::TWithMap>();
  271. auto createKeyValueStruct = [] (NTi::TTypePtr key, NTi::TTypePtr value) {
  272. return NTi::List(NTi::Struct({
  273. {"key", NTi::Optional(key)},
  274. {"value", NTi::Optional(value)},
  275. }));
  276. };
  277. auto embedded = NTi::Struct({
  278. {"x", NTi::Optional(NTi::Int64())},
  279. {"y", NTi::Optional(NTi::String())},
  280. });
  281. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  282. .AddColumn(TColumnSchema()
  283. .Name("MapDefault")
  284. .Type(createKeyValueStruct(NTi::Int64(), NTi::String())))
  285. .AddColumn(TColumnSchema()
  286. .Name("MapListOfStructsLegacy")
  287. .Type(createKeyValueStruct(NTi::Int64(), NTi::String())))
  288. .AddColumn(TColumnSchema()
  289. .Name("MapListOfStructs")
  290. .Type(createKeyValueStruct(NTi::Int64(), embedded)))
  291. .AddColumn(TColumnSchema()
  292. .Name("MapOptionalDict")
  293. .Type(NTi::Optional(NTi::Dict(NTi::Int64(), embedded))))
  294. .AddColumn(TColumnSchema()
  295. .Name("MapDict")
  296. .Type(NTi::Dict(NTi::Int64(), embedded))));
  297. }
  298. Y_UNIT_TEST(Oneof)
  299. {
  300. const auto schema = CreateTableSchema<NUnitTesting::TWithOneof>();
  301. auto embedded = NTi::Struct({
  302. {"Oneof", NTi::Optional(NTi::Variant(NTi::Struct({
  303. {"x", NTi::Int64()},
  304. {"y", NTi::String()},
  305. })))},
  306. });
  307. auto createType = [&] (TString oneof2Name) {
  308. return NTi::Optional(NTi::Struct({
  309. {"field", NTi::Optional(NTi::String())},
  310. {oneof2Name, NTi::Optional(NTi::Variant(NTi::Struct({
  311. {"x2", NTi::Int64()},
  312. {"y2", NTi::String()},
  313. {"z2", embedded},
  314. })))},
  315. {"y1", NTi::Optional(NTi::String())},
  316. {"z1", NTi::Optional(embedded)},
  317. {"x1", NTi::Optional(NTi::Int64())},
  318. }));
  319. };
  320. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  321. .AddColumn(TColumnSchema()
  322. .Name("DefaultSeparateFields")
  323. .Type(createType("variant_field_name")))
  324. .AddColumn(TColumnSchema()
  325. .Name("NoDefault")
  326. .Type(createType("Oneof2")))
  327. .AddColumn(TColumnSchema()
  328. .Name("SerializationProtobuf")
  329. .Type(NTi::Optional(NTi::Struct({
  330. {"y1", NTi::Optional(NTi::String())},
  331. {"x1", NTi::Optional(NTi::Int64())},
  332. {"z1", NTi::Optional(NTi::String())},
  333. }))))
  334. .AddColumn(TColumnSchema()
  335. .Name("TopLevelOneof")
  336. .Type(
  337. NTi::Optional(
  338. NTi::Variant(NTi::Struct({
  339. {"MemberOfTopLevelOneof", NTi::Int64()}
  340. }))
  341. )
  342. ))
  343. );
  344. }
  345. Y_UNIT_TEST(Embedded)
  346. {
  347. const auto schema = CreateTableSchema<NUnitTesting::TEmbeddingMessage>();
  348. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  349. .Strict(false)
  350. .AddColumn(TColumnSchema().Name("embedded2_num").Type(NTi::Optional(NTi::Uint64())))
  351. .AddColumn(TColumnSchema().Name("embedded2_struct").Type(NTi::Optional(NTi::Struct({
  352. {"float1", NTi::Optional(NTi::Double())},
  353. {"string1", NTi::Optional(NTi::String())},
  354. }))))
  355. .AddColumn(TColumnSchema().Name("embedded2_repeated").Type(NTi::List(NTi::String())))
  356. .AddColumn(TColumnSchema().Name("embedded_num").Type(NTi::Optional(NTi::Uint64())))
  357. .AddColumn(TColumnSchema().Name("embedded_extra_field").Type(NTi::Optional(NTi::String())))
  358. .AddColumn(TColumnSchema().Name("variant").Type(NTi::Optional(NTi::Variant(NTi::Struct({
  359. {"str_variant", NTi::String()},
  360. {"uint_variant", NTi::Uint64()},
  361. })))))
  362. .AddColumn(TColumnSchema().Name("num").Type(NTi::Optional(NTi::Uint64())))
  363. .AddColumn(TColumnSchema().Name("extra_field").Type(NTi::Optional(NTi::String())))
  364. );
  365. }
  366. }
  367. Y_UNIT_TEST_SUITE(ProtoSchemaTest_Proto3)
  368. {
  369. Y_UNIT_TEST(TWithOptional)
  370. {
  371. const auto schema = CreateTableSchema<NTestingProto3::TWithOptional>();
  372. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  373. .AddColumn(TColumnSchema()
  374. .Name("x").Type(NTi::Optional(NTi::Int64()))
  375. )
  376. );
  377. }
  378. Y_UNIT_TEST(TWithOptionalMessage)
  379. {
  380. const auto schema = CreateTableSchema<NTestingProto3::TWithOptionalMessage>();
  381. ASSERT_SERIALIZABLES_EQUAL(schema, TTableSchema()
  382. .AddColumn(TColumnSchema()
  383. .Name("x").Type(
  384. NTi::Optional(
  385. NTi::Struct({{"x", NTi::Optional(NTi::Int64())}})
  386. )
  387. )
  388. )
  389. );
  390. }
  391. }