common_ut.cpp 12 KB

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