common_ut.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. #include "common_ut.h"
  2. #include "fluent.h"
  3. #include <yt/cpp/mapreduce/interface/common.h>
  4. #include <yt/cpp/mapreduce/tests/yt_unittest_lib/yt_unittest_lib.h>
  5. #include <library/cpp/testing/unittest/registar.h>
  6. #include <library/cpp/yson/node/node_io.h>
  7. #include <library/cpp/yson/node/node_builder.h>
  8. #include <util/generic/xrange.h>
  9. using namespace NYT;
  10. template <class T>
  11. TString SaveToString(const T& obj)
  12. {
  13. TString s;
  14. TStringOutput out(s);
  15. ::Save(&out, obj);
  16. return s;
  17. }
  18. template <class T>
  19. T LoadFromString(TStringBuf s)
  20. {
  21. TMemoryInput in(s);
  22. T obj;
  23. ::Load(&in, obj);
  24. return obj;
  25. }
  26. template <class T>
  27. T SaveLoad(const T& obj)
  28. {
  29. return LoadFromString<T>(SaveToString(obj));
  30. }
  31. Y_UNIT_TEST_SUITE(Common)
  32. {
  33. Y_UNIT_TEST(SortColumnsLegacy)
  34. {
  35. TSortColumns keys1("a", "b");
  36. UNIT_ASSERT((keys1.Parts_ == TSortColumns{"a", "b"}));
  37. keys1.Add("c", "d");
  38. UNIT_ASSERT((keys1.Parts_ == TSortColumns{"a", "b", "c", "d"}));
  39. auto keys2 = TSortColumns(keys1).Add("e", "f");
  40. UNIT_ASSERT((keys1.Parts_ == TSortColumns{"a", "b", "c", "d"}));
  41. UNIT_ASSERT((keys2.Parts_ == TSortColumns{"a", "b", "c", "d", "e", "f"}));
  42. auto keys3 = TSortColumns(keys1).Add("e").Add("f").Add("g");
  43. UNIT_ASSERT((keys1.Parts_ == TSortColumns{"a", "b", "c", "d"}));
  44. UNIT_ASSERT((keys3.Parts_ == TSortColumns{"a", "b", "c", "d", "e", "f", "g"}));
  45. }
  46. Y_UNIT_TEST(SortColumn)
  47. {
  48. auto ascending = TSortColumn("a");
  49. UNIT_ASSERT_VALUES_EQUAL(ascending.Name(), "a");
  50. UNIT_ASSERT_VALUES_EQUAL(ascending.SortOrder(), ESortOrder::SO_ASCENDING);
  51. UNIT_ASSERT_VALUES_EQUAL(ascending, TSortColumn("a", ESortOrder::SO_ASCENDING));
  52. UNIT_ASSERT_VALUES_UNEQUAL(ascending, TSortColumn("a", ESortOrder::SO_DESCENDING));
  53. UNIT_ASSERT_NO_EXCEPTION(ascending.EnsureAscending());
  54. UNIT_ASSERT_VALUES_EQUAL(static_cast<TString>(ascending), "a");
  55. UNIT_ASSERT_VALUES_EQUAL(ascending, "a");
  56. auto another = ascending;
  57. UNIT_ASSERT_NO_EXCEPTION(another = "another");
  58. UNIT_ASSERT_VALUES_EQUAL(another.Name(), "another");
  59. UNIT_ASSERT_VALUES_EQUAL(another.SortOrder(), ESortOrder::SO_ASCENDING);
  60. UNIT_ASSERT_VALUES_EQUAL(another, TSortColumn("another", ESortOrder::SO_ASCENDING));
  61. UNIT_ASSERT_VALUES_UNEQUAL(another, TSortColumn("another", ESortOrder::SO_DESCENDING));
  62. auto ascendingNode = BuildYsonNodeFluently().Value(ascending);
  63. UNIT_ASSERT_VALUES_EQUAL(ascendingNode, TNode("a"));
  64. UNIT_ASSERT_VALUES_EQUAL(SaveLoad(ascending), ascending);
  65. UNIT_ASSERT_VALUES_UNEQUAL(SaveToString(ascending), SaveToString(TString("a")));
  66. auto descending = TSortColumn("a", ESortOrder::SO_DESCENDING);
  67. UNIT_ASSERT_VALUES_EQUAL(descending.Name(), "a");
  68. UNIT_ASSERT_VALUES_EQUAL(descending.SortOrder(), ESortOrder::SO_DESCENDING);
  69. UNIT_ASSERT_VALUES_EQUAL(descending, TSortColumn("a", ESortOrder::SO_DESCENDING));
  70. UNIT_ASSERT_VALUES_UNEQUAL(descending, TSortColumn("a", ESortOrder::SO_ASCENDING));
  71. UNIT_ASSERT_EXCEPTION(descending.EnsureAscending(), yexception);
  72. UNIT_ASSERT_EXCEPTION(static_cast<TString>(descending), yexception);
  73. UNIT_ASSERT_EXCEPTION(descending == "a", yexception);
  74. UNIT_ASSERT_EXCEPTION(descending = "a", yexception);
  75. auto descendingNode = BuildYsonNodeFluently().Value(descending);
  76. UNIT_ASSERT_VALUES_EQUAL(descendingNode, TNode()("name", "a")("sort_order", "descending"));
  77. UNIT_ASSERT_VALUES_EQUAL(SaveLoad(descending), descending);
  78. UNIT_ASSERT_VALUES_UNEQUAL(SaveToString(descending), SaveToString("a"));
  79. UNIT_ASSERT_VALUES_EQUAL(ToString(TSortColumn("blah")), "blah");
  80. UNIT_ASSERT_VALUES_EQUAL(ToString(TSortColumn("blah", ESortOrder::SO_DESCENDING)), "{\"name\"=\"blah\";\"sort_order\"=\"descending\"}");
  81. }
  82. Y_UNIT_TEST(SortColumns)
  83. {
  84. TSortColumns ascending("a", "b");
  85. UNIT_ASSERT(ascending.Parts_ == (TSortColumns{"a", "b"}));
  86. UNIT_ASSERT_NO_EXCEPTION(ascending.EnsureAscending());
  87. UNIT_ASSERT_VALUES_EQUAL(static_cast<TColumnNames>(ascending).Parts_, (TVector<TString>{"a", "b"}));
  88. UNIT_ASSERT_VALUES_EQUAL(ascending.GetNames(), (TVector<TString>{"a", "b"}));
  89. auto mixed = ascending;
  90. mixed.Add(TSortColumn("c", ESortOrder::SO_DESCENDING), "d");
  91. UNIT_ASSERT((mixed.Parts_ != TVector<TSortColumn>{"a", "b", "c", "d"}));
  92. UNIT_ASSERT((mixed.Parts_ == TVector<TSortColumn>{"a", "b", TSortColumn("c", ESortOrder::SO_DESCENDING), "d"}));
  93. UNIT_ASSERT_VALUES_EQUAL(mixed.GetNames(), (TVector<TString>{"a", "b", "c", "d"}));
  94. UNIT_ASSERT_EXCEPTION(mixed.EnsureAscending(), yexception);
  95. UNIT_ASSERT_EXCEPTION(static_cast<TColumnNames>(mixed), yexception);
  96. }
  97. Y_UNIT_TEST(KeyBound)
  98. {
  99. auto keyBound = TKeyBound(ERelation::Greater, TKey(7, "a", TNode()("x", "y")));
  100. UNIT_ASSERT_VALUES_EQUAL(keyBound.Relation(), ERelation::Greater);
  101. UNIT_ASSERT_EQUAL(keyBound.Key(), TKey(7, "a", TNode()("x", "y")));
  102. auto keyBound1 = TKeyBound().Relation(ERelation::Greater).Key(TKey(7, "a", TNode()("x", "y")));
  103. auto expectedNode = TNode()
  104. .Add(">")
  105. .Add(TNode().Add(7).Add("a").Add(TNode()("x", "y")));
  106. UNIT_ASSERT_VALUES_EQUAL(expectedNode, BuildYsonNodeFluently().Value(keyBound));
  107. UNIT_ASSERT_VALUES_EQUAL(expectedNode, BuildYsonNodeFluently().Value(keyBound1));
  108. keyBound.Relation(ERelation::LessOrEqual);
  109. keyBound.Key(TKey("A", 7));
  110. UNIT_ASSERT_VALUES_EQUAL(keyBound.Relation(), ERelation::LessOrEqual);
  111. UNIT_ASSERT_EQUAL(keyBound.Key(), TKey("A", 7));
  112. UNIT_ASSERT_VALUES_EQUAL(
  113. BuildYsonNodeFluently().Value(keyBound),
  114. TNode()
  115. .Add("<=")
  116. .Add(TNode().Add("A").Add(7)));
  117. }
  118. Y_UNIT_TEST(TTableSchema)
  119. {
  120. TTableSchema schema;
  121. schema
  122. .AddColumn(TColumnSchema().Name("a").Type(EValueType::VT_STRING).SortOrder(SO_ASCENDING))
  123. .AddColumn(TColumnSchema().Name("b").Type(EValueType::VT_UINT64))
  124. .AddColumn(TColumnSchema().Name("c").Type(EValueType::VT_INT64));
  125. auto checkSortBy = [](TTableSchema schema, const TVector<TString>& columns) {
  126. auto initialSchema = schema;
  127. schema.SortBy(columns);
  128. for (auto i: xrange(columns.size())) {
  129. UNIT_ASSERT_VALUES_EQUAL(schema.Columns()[i].Name(), columns[i]);
  130. UNIT_ASSERT_VALUES_EQUAL(schema.Columns()[i].SortOrder(), ESortOrder::SO_ASCENDING);
  131. }
  132. for (auto i: xrange(columns.size(), (size_t)initialSchema.Columns().size())) {
  133. UNIT_ASSERT_VALUES_EQUAL(schema.Columns()[i].SortOrder(), Nothing());
  134. }
  135. UNIT_ASSERT_VALUES_EQUAL(initialSchema.Columns().size(), schema.Columns().size());
  136. return schema;
  137. };
  138. auto newSchema = checkSortBy(schema, {"b"});
  139. UNIT_ASSERT_VALUES_EQUAL(newSchema.Columns()[1].Name(), TString("a"));
  140. UNIT_ASSERT_VALUES_EQUAL(newSchema.Columns()[2].Name(), TString("c"));
  141. checkSortBy(schema, {"b", "c"});
  142. checkSortBy(schema, {"c", "a"});
  143. UNIT_ASSERT_EXCEPTION(checkSortBy(schema, {"b", "b"}), yexception);
  144. UNIT_ASSERT_EXCEPTION(checkSortBy(schema, {"a", "junk"}), yexception);
  145. }
  146. Y_UNIT_TEST(TTableSchema_Decimal)
  147. {
  148. NYT::TTableSchema tableSchema;
  149. tableSchema.AddColumn("a", NTi::Decimal(35, 18));
  150. tableSchema.AddColumn("b", NTi::Optional(NTi::Decimal(35, 18)));
  151. tableSchema.AddColumn("c", NTi::List(NTi::Decimal(35, 18)));
  152. auto tableSchemaNode = tableSchema.ToNode();
  153. const auto& tableSchemaNodeList = tableSchemaNode.AsList();
  154. // There was a bug in the serialization of decimal type: https://github.com/ytsaurus/ytsaurus/issues/173
  155. {
  156. const auto& currentType = tableSchemaNodeList[0];
  157. UNIT_ASSERT_VALUES_EQUAL(currentType.ChildAsString("type"), "string");
  158. UNIT_ASSERT(currentType.ChildAsBool("required"));
  159. UNIT_ASSERT(currentType.HasKey("type_v3"));
  160. UNIT_ASSERT_VALUES_EQUAL(currentType.At("type_v3").ChildAsString("type_name"), "decimal");
  161. }
  162. {
  163. const auto& currentType = tableSchemaNodeList[1];
  164. UNIT_ASSERT_VALUES_EQUAL(currentType.ChildAsString("type"), "string");
  165. UNIT_ASSERT(!currentType.ChildAsBool("required"));
  166. UNIT_ASSERT(currentType.HasKey("type_v3"));
  167. UNIT_ASSERT_VALUES_EQUAL(currentType.At("type_v3").ChildAsString("type_name"), "optional");
  168. UNIT_ASSERT_VALUES_EQUAL(currentType.At("type_v3").At("item").ChildAsString("type_name"), "decimal");
  169. }
  170. {
  171. const auto& currentType = tableSchemaNodeList[2];
  172. UNIT_ASSERT_VALUES_EQUAL(currentType.ChildAsString("type"), "any");
  173. UNIT_ASSERT(currentType.ChildAsBool("required"));
  174. UNIT_ASSERT(currentType.HasKey("type_v3"));
  175. UNIT_ASSERT_VALUES_EQUAL(currentType.At("type_v3").ChildAsString("type_name"), "list");
  176. UNIT_ASSERT_VALUES_EQUAL(currentType.At("type_v3").At("item").ChildAsString("type_name"), "decimal");
  177. }
  178. UNIT_ASSERT_EQUAL(tableSchema, TTableSchema::FromNode(tableSchemaNode));
  179. }
  180. Y_UNIT_TEST(TColumnSchema_TypeV3)
  181. {
  182. {
  183. auto column = TColumnSchema().Type(NTi::Interval());
  184. UNIT_ASSERT_VALUES_EQUAL(column.Required(), true);
  185. UNIT_ASSERT_VALUES_EQUAL(column.Type(), VT_INTERVAL);
  186. }
  187. {
  188. auto column = TColumnSchema().Type(NTi::Optional(NTi::Date()));
  189. UNIT_ASSERT_VALUES_EQUAL(column.Required(), false);
  190. UNIT_ASSERT_VALUES_EQUAL(column.Type(), VT_DATE);
  191. }
  192. {
  193. auto column = TColumnSchema().Type(NTi::Interval64());
  194. UNIT_ASSERT_VALUES_EQUAL(column.Required(), true);
  195. UNIT_ASSERT_VALUES_EQUAL(column.Type(), VT_INTERVAL64);
  196. }
  197. {
  198. auto column = TColumnSchema().Type(NTi::Optional(NTi::Date32()));
  199. UNIT_ASSERT_VALUES_EQUAL(column.Required(), false);
  200. UNIT_ASSERT_VALUES_EQUAL(column.Type(), VT_DATE32);
  201. }
  202. {
  203. auto column = TColumnSchema().Type(NTi::Null());
  204. UNIT_ASSERT_VALUES_EQUAL(column.Required(), false);
  205. UNIT_ASSERT_VALUES_EQUAL(column.Type(), VT_NULL);
  206. }
  207. {
  208. auto column = TColumnSchema().Type(NTi::Optional(NTi::Null()));
  209. UNIT_ASSERT_VALUES_EQUAL(column.Required(), false);
  210. UNIT_ASSERT_VALUES_EQUAL(column.Type(), VT_ANY);
  211. }
  212. {
  213. auto column = TColumnSchema().Type(NTi::Decimal(35, 18));
  214. UNIT_ASSERT_VALUES_EQUAL(column.Required(), true);
  215. UNIT_ASSERT_VALUES_EQUAL(column.Type(), VT_STRING);
  216. }
  217. }
  218. Y_UNIT_TEST(ToTypeV3)
  219. {
  220. UNIT_ASSERT_VALUES_EQUAL(*ToTypeV3(VT_INT32, true), *NTi::Int32());
  221. UNIT_ASSERT_VALUES_EQUAL(*ToTypeV3(VT_UTF8, false), *NTi::Optional(NTi::Utf8()));
  222. }
  223. Y_UNIT_TEST(DeserializeColumn)
  224. {
  225. auto deserialize = [] (TStringBuf yson) {
  226. auto node = NodeFromYsonString(yson);
  227. TColumnSchema column;
  228. Deserialize(column, node);
  229. return column;
  230. };
  231. auto column = deserialize("{name=foo; type=int64; required=%false}");
  232. UNIT_ASSERT_VALUES_EQUAL(column.Name(), "foo");
  233. UNIT_ASSERT_VALUES_EQUAL(*column.TypeV3(), *NTi::Optional(NTi::Int64()));
  234. column = deserialize("{name=bar; type=utf8; required=%true; type_v3=utf8}");
  235. UNIT_ASSERT_VALUES_EQUAL(column.Name(), "bar");
  236. UNIT_ASSERT_VALUES_EQUAL(*column.TypeV3(), *NTi::Utf8());
  237. }
  238. Y_UNIT_TEST(ColumnSchemaEquality)
  239. {
  240. auto base = TColumnSchema()
  241. .Name("col")
  242. .TypeV3(NTi::Optional(NTi::List(NTi::String())))
  243. .SortOrder(ESortOrder::SO_ASCENDING)
  244. .Lock("lock")
  245. .Expression("x + 12")
  246. .Aggregate("sum")
  247. .Group("group");
  248. auto other = base;
  249. ASSERT_SERIALIZABLES_EQUAL(other, base);
  250. other.Name("other");
  251. ASSERT_SERIALIZABLES_UNEQUAL(other, base);
  252. other = base;
  253. other.TypeV3(NTi::List(NTi::String()));
  254. ASSERT_SERIALIZABLES_UNEQUAL(other, base);
  255. other = base;
  256. other.ResetSortOrder();
  257. ASSERT_SERIALIZABLES_UNEQUAL(other, base);
  258. other = base;
  259. other.Lock("lock1");
  260. ASSERT_SERIALIZABLES_UNEQUAL(other, base);
  261. other = base;
  262. other.Expression("x + 13");
  263. ASSERT_SERIALIZABLES_UNEQUAL(other, base);
  264. other = base;
  265. other.ResetAggregate();
  266. ASSERT_SERIALIZABLES_UNEQUAL(other, base);
  267. other = base;
  268. other.Group("group1");
  269. ASSERT_SERIALIZABLES_UNEQUAL(other, base);
  270. }
  271. Y_UNIT_TEST(TableSchemaEquality)
  272. {
  273. auto col1 = TColumnSchema()
  274. .Name("col1")
  275. .TypeV3(NTi::Optional(NTi::List(NTi::String())))
  276. .SortOrder(ESortOrder::SO_ASCENDING);
  277. auto col2 = TColumnSchema()
  278. .Name("col2")
  279. .TypeV3(NTi::Uint32());
  280. auto schema = TTableSchema()
  281. .AddColumn(col1)
  282. .AddColumn(col2)
  283. .Strict(true)
  284. .UniqueKeys(true);
  285. auto other = schema;
  286. ASSERT_SERIALIZABLES_EQUAL(other, schema);
  287. other.Strict(false);
  288. ASSERT_SERIALIZABLES_UNEQUAL(other, schema);
  289. other = schema;
  290. other.MutableColumns()[0].TypeV3(NTi::List(NTi::String()));
  291. ASSERT_SERIALIZABLES_UNEQUAL(other, schema);
  292. other = schema;
  293. other.MutableColumns().push_back(col1);
  294. ASSERT_SERIALIZABLES_UNEQUAL(other, schema);
  295. other = schema;
  296. other.UniqueKeys(false);
  297. ASSERT_SERIALIZABLES_UNEQUAL(other, schema);
  298. }
  299. }