mkql_node_ut.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. #include "mkql_node.h"
  2. #include "mkql_node_visitor.h"
  3. #include <library/cpp/testing/unittest/registar.h>
  4. #include <util/generic/algorithm.h>
  5. namespace NKikimr {
  6. namespace NMiniKQL {
  7. Y_UNIT_TEST_SUITE(TMiniKQLNodeTest) {
  8. Y_UNIT_TEST(TestTypeOfType) {
  9. TScopedAlloc alloc(__LOCATION__);
  10. TTypeEnvironment env(alloc);
  11. {
  12. auto type = env.GetTypeOfTypeLazy();
  13. UNIT_ASSERT(type->IsType());
  14. UNIT_ASSERT(type->GetType() == type);
  15. UNIT_ASSERT(type->IsSameType(*type));
  16. }
  17. }
  18. Y_UNIT_TEST(TestTypeOfVoid) {
  19. TScopedAlloc alloc(__LOCATION__);
  20. TTypeEnvironment env(alloc);
  21. {
  22. auto type = env.GetTypeOfVoidLazy();
  23. UNIT_ASSERT(type->IsVoid());
  24. UNIT_ASSERT(type->GetType() == env.GetTypeOfTypeLazy());
  25. UNIT_ASSERT(type->IsSameType(*type));
  26. }
  27. }
  28. Y_UNIT_TEST(TestVoid) {
  29. TScopedAlloc alloc(__LOCATION__);
  30. TTypeEnvironment env(alloc);
  31. TVoid* voidObj = env.GetVoidLazy();
  32. UNIT_ASSERT(voidObj->GetType()->IsVoid());
  33. UNIT_ASSERT(voidObj->GetType() == env.GetTypeOfVoidLazy());
  34. }
  35. Y_UNIT_TEST(TestTypeOfData) {
  36. TScopedAlloc alloc(__LOCATION__);
  37. TTypeEnvironment env(alloc);
  38. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<ui32>::Id, env);
  39. UNIT_ASSERT_EQUAL(dtype1->GetKind(), TType::EKind::Data);
  40. UNIT_ASSERT_EQUAL(dtype1->GetSchemeType(), NUdf::TDataType<ui32>::Id);
  41. UNIT_ASSERT(dtype1->IsSameType(*dtype1));
  42. UNIT_ASSERT_EXCEPTION(TDataType::Create(0, env), yexception);
  43. TDataType* dtype1Cloned = TDataType::Create(NUdf::TDataType<ui32>::Id, env);
  44. UNIT_ASSERT(dtype1Cloned->IsSameType(*dtype1));
  45. }
  46. Y_UNIT_TEST(TestData) {
  47. TScopedAlloc alloc(__LOCATION__);
  48. TTypeEnvironment env(alloc);
  49. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<ui32>::Id, env);
  50. ui32 u = 34567;
  51. auto d1 = TDataLiteral::Create(NUdf::TUnboxedValuePod(u), dtype1, env);
  52. UNIT_ASSERT(memcmp(d1->AsValue().AsStringRef().Data(), &u, sizeof(u)) == 0);
  53. UNIT_ASSERT(d1->GetType() == dtype1);
  54. }
  55. Y_UNIT_TEST(TestStructType) {
  56. TScopedAlloc alloc(__LOCATION__);
  57. TTypeEnvironment env(alloc);
  58. TStructType* sempty = env.GetEmptyStructLazy()->GetType();
  59. UNIT_ASSERT_EQUAL(sempty->GetKind(), TType::EKind::Struct);
  60. UNIT_ASSERT_EQUAL(sempty->GetMembersCount(), 0);
  61. TVector<std::pair<TString, TType*>> s1members;
  62. s1members.push_back(std::make_pair("aaa", env.GetVoidLazy()->GetGenericType()));
  63. TStructType* s1 = TStructType::Create(s1members.data(), s1members.size(), env);
  64. UNIT_ASSERT_EQUAL(s1->GetMembersCount(), 1);
  65. UNIT_ASSERT_EQUAL(s1->GetMemberName(0), "aaa");
  66. UNIT_ASSERT_EQUAL(s1->GetMemberType(0)->GetKind(), TType::EKind::Void);
  67. TVector<std::pair<TString, TType*>> s2members;
  68. s2members.push_back(std::make_pair("bbb", env.GetEmptyStructLazy()->GetGenericType()));
  69. s2members.push_back(std::make_pair("ccc", env.GetTypeOfVoidLazy()));
  70. TStructType* s2 = TStructType::Create(s2members.data(), s2members.size(), env);
  71. UNIT_ASSERT_EQUAL(s2->GetMembersCount(), 2);
  72. UNIT_ASSERT_EQUAL(s2->GetMemberName(0), "bbb");
  73. UNIT_ASSERT_EQUAL(s2->GetMemberType(0)->GetKind(), TType::EKind::Struct);
  74. UNIT_ASSERT_EQUAL(s2->GetMemberName(1), "ccc");
  75. UNIT_ASSERT_EQUAL(s2->GetMemberType(1)->GetKind(), TType::EKind::Void);
  76. TVector<std::pair<TString, TType*>> s3members;
  77. s3members.push_back(std::make_pair("", env.GetEmptyStructLazy()->GetGenericType()));
  78. UNIT_ASSERT_EXCEPTION(TStructType::Create(s3members.data(), s3members.size(), env), yexception);
  79. TStructType* s2cloned = TStructType::Create(s2members.data(), s2members.size(), env);
  80. UNIT_ASSERT(s2cloned->IsSameType(*s2cloned));
  81. UNIT_ASSERT(s2cloned->IsSameType(*s2));
  82. UNIT_ASSERT(!s2cloned->IsSameType(*s1));
  83. Reverse(s2members.begin(), s2members.end());
  84. UNIT_ASSERT_EXCEPTION(TStructType::Create(s2members.data(), s2members.size(), env), yexception);
  85. TVector<std::pair<TString, TType*>> duplicatedMembers;
  86. duplicatedMembers.push_back(std::make_pair("aaa", env.GetEmptyStructLazy()->GetGenericType()));
  87. duplicatedMembers.push_back(std::make_pair("aaa", env.GetTypeOfVoidLazy()));
  88. UNIT_ASSERT_EXCEPTION(TStructType::Create(duplicatedMembers.data(), duplicatedMembers.size(), env), yexception);
  89. }
  90. Y_UNIT_TEST(TestStructLiteral) {
  91. TScopedAlloc alloc(__LOCATION__);
  92. TTypeEnvironment env(alloc);
  93. TStructType* semptyType = env.GetEmptyStructLazy()->GetType();
  94. TStructLiteral* sempty = TStructLiteral::Create(0, nullptr, semptyType, env);
  95. UNIT_ASSERT_EQUAL(sempty->GetValuesCount(), 0);
  96. TVector<std::pair<TString, TType*>> s1members;
  97. s1members.push_back(std::make_pair("aaa", env.GetVoidLazy()->GetGenericType()));
  98. TStructType* s1type = TStructType::Create(s1members.data(), s1members.size(), env);
  99. TVector<TRuntimeNode> s1values;
  100. s1values.push_back(TRuntimeNode(env.GetVoidLazy(), true));
  101. TStructLiteral* s1 = TStructLiteral::Create(s1values.size(), s1values.data(), s1type, env);
  102. UNIT_ASSERT_EQUAL(s1->GetValuesCount(), 1);
  103. UNIT_ASSERT_EQUAL(s1->GetValue(0).GetNode(), s1values[0].GetNode());
  104. UNIT_ASSERT_EXCEPTION(TStructLiteral::Create(s1values.size(), s1values.data(), semptyType, env), yexception);
  105. TVector<std::pair<TString, TType*>> s2members;
  106. s2members.push_back(std::make_pair("aaa", env.GetEmptyTupleLazy()->GetGenericType()));
  107. TStructType* s2type = TStructType::Create(s2members.data(), s2members.size(), env);
  108. UNIT_ASSERT_EXCEPTION(TStructLiteral::Create(s1values.size(), s1values.data(), s2type, env), yexception);
  109. TStructType* s1typeDyn = TStructType::Create(s1members.data(), s1members.size(), env);
  110. TVector<TRuntimeNode> s1DynValues;
  111. TCallableType* ctype = TCallableType::Create("c1", env.GetVoidLazy()->GetGenericType(),
  112. 0, nullptr, nullptr, env);
  113. s1DynValues.push_back(TRuntimeNode(TCallable::Create(0, nullptr, ctype, env), false));
  114. UNIT_ASSERT_NO_EXCEPTION(TStructLiteral::Create(s1DynValues.size(), s1DynValues.data(), s1typeDyn, env));
  115. UNIT_ASSERT_NO_EXCEPTION(TStructLiteral::Create(s1values.size(), s1values.data(), s1typeDyn, env));
  116. }
  117. Y_UNIT_TEST(TestListType) {
  118. TScopedAlloc alloc(__LOCATION__);
  119. TTypeEnvironment env(alloc);
  120. TListType* list1type = TListType::Create(env.GetVoidLazy()->GetGenericType(), env);
  121. UNIT_ASSERT_EQUAL(list1type->GetKind(), TType::EKind::List);
  122. TListType* list2type = TListType::Create(env.GetEmptyTupleLazy()->GetGenericType(), env);
  123. TListType* list1typeCloned = TListType::Create(env.GetVoidLazy()->GetGenericType(), env);
  124. UNIT_ASSERT(list1type->IsSameType(*list1typeCloned));
  125. UNIT_ASSERT(!list1type->IsSameType(*list2type));
  126. }
  127. Y_UNIT_TEST(TestStreamType) {
  128. TScopedAlloc alloc(__LOCATION__);
  129. TTypeEnvironment env(alloc);
  130. TStreamType* stream1type = TStreamType::Create(env.GetVoidLazy()->GetGenericType(), env);
  131. UNIT_ASSERT_EQUAL(stream1type->GetKind(), TType::EKind::Stream);
  132. TStreamType* stream2type = TStreamType::Create(env.GetEmptyTupleLazy()->GetGenericType(), env);
  133. TStreamType* stream1typeCloned = TStreamType::Create(env.GetVoidLazy()->GetGenericType(), env);
  134. UNIT_ASSERT(stream1type->IsSameType(*stream1typeCloned));
  135. UNIT_ASSERT(!stream1type->IsSameType(*stream2type));
  136. }
  137. Y_UNIT_TEST(TestListLiteral) {
  138. TScopedAlloc alloc(__LOCATION__);
  139. TTypeEnvironment env(alloc);
  140. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<char*>::Id, env);
  141. TListType* list1type = TListType::Create(env.GetVoidLazy()->GetGenericType(), env);
  142. TListType* list2type = TListType::Create(dtype1, env);
  143. UNIT_ASSERT_NO_EXCEPTION(TListLiteral::Create(nullptr, 0, list1type, env));
  144. TString u = "34567";
  145. TVector<TRuntimeNode> someItems;
  146. someItems.push_back(TRuntimeNode(TDataLiteral::Create(
  147. NUdf::TUnboxedValue::Embedded(u), dtype1, env), true));
  148. u = "878";
  149. someItems.push_back(TRuntimeNode(TDataLiteral::Create(
  150. NUdf::TUnboxedValue::Embedded(u), dtype1, env), true));
  151. TListLiteral* list2 = TListLiteral::Create(someItems.data(), someItems.size(), list2type, env);
  152. UNIT_ASSERT_EQUAL(list2->GetItemsCount(), 2);
  153. UNIT_ASSERT_EQUAL(list2->GetItems()[0].GetNode()->GetType()->GetKind(), TType::EKind::Data);
  154. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*list2->GetItems()[0].GetNode()).AsValue().AsStringRef(), NUdf::TStringRef::Of("34567"));
  155. UNIT_ASSERT_EQUAL(list2->GetItems()[1].GetNode()->GetType()->GetKind(), TType::EKind::Data);
  156. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*list2->GetItems()[1].GetNode()).AsValue().AsStringRef(), NUdf::TStringRef::Of("878"));
  157. UNIT_ASSERT_EXCEPTION(TListLiteral::Create(someItems.data(), someItems.size(), list1type, env), yexception);
  158. TListType* list2typeDyn = TListType::Create(dtype1, env);
  159. UNIT_ASSERT_NO_EXCEPTION(TListLiteral::Create(someItems.data(), someItems.size(), list2typeDyn, env));
  160. TVector<TRuntimeNode> someDynItems;
  161. TCallableType* ctype = TCallableType::Create("c1", dtype1, 0, nullptr, nullptr, env);
  162. someDynItems.push_back(TRuntimeNode(TCallable::Create(0, nullptr, ctype, env), false));
  163. UNIT_ASSERT_NO_EXCEPTION(TListLiteral::Create(someDynItems.data(), someDynItems.size(), list2typeDyn, env));
  164. }
  165. Y_UNIT_TEST(TestOptionalType) {
  166. TScopedAlloc alloc(__LOCATION__);
  167. TTypeEnvironment env(alloc);
  168. TOptionalType* opt1type = TOptionalType::Create(env.GetVoidLazy()->GetGenericType(), env);
  169. UNIT_ASSERT_EQUAL(opt1type->GetKind(), TType::EKind::Optional);
  170. TOptionalType* opt2type = TOptionalType::Create(env.GetEmptyTupleLazy()->GetGenericType(), env);
  171. TOptionalType* opt1typeCloned = TOptionalType::Create(env.GetVoidLazy()->GetGenericType(), env);
  172. UNIT_ASSERT(opt1type->IsSameType(*opt1typeCloned));
  173. UNIT_ASSERT(!opt1type->IsSameType(*opt2type));
  174. }
  175. Y_UNIT_TEST(TestOptionalLiteral) {
  176. TScopedAlloc alloc(__LOCATION__);
  177. TTypeEnvironment env(alloc);
  178. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<char*>::Id, env);
  179. TOptionalType* opt1type = TOptionalType::Create(env.GetVoidLazy()->GetGenericType(), env);
  180. TOptionalType* opt2type = TOptionalType::Create(dtype1, env);
  181. TOptionalLiteral* emptyOpt = TOptionalLiteral::Create(opt1type, env);
  182. UNIT_ASSERT(!emptyOpt->HasItem());
  183. TString u = "34567";
  184. auto item1 = TRuntimeNode(TDataLiteral::Create(
  185. NUdf::TUnboxedValuePod::Embedded(u), dtype1, env), true);
  186. TOptionalLiteral* opt1 = TOptionalLiteral::Create(item1, opt2type, env);
  187. UNIT_ASSERT(opt1->HasItem());
  188. UNIT_ASSERT_EQUAL(opt1->GetItem().GetNode()->GetType()->GetKind(), TType::EKind::Data);
  189. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*opt1->GetItem().GetNode()).AsValue().AsStringRef(), NUdf::TStringRef::Of("34567"));
  190. UNIT_ASSERT_EXCEPTION(TOptionalLiteral::Create(item1, opt1type, env), yexception);
  191. auto opt2typeDyn = TOptionalType::Create(dtype1, env);
  192. UNIT_ASSERT_NO_EXCEPTION(TOptionalLiteral::Create(item1, opt2typeDyn, env));
  193. TCallableType* ctype = TCallableType::Create("c1", dtype1, 0, nullptr, nullptr, env);
  194. auto dynItem = TRuntimeNode(TCallable::Create(0, nullptr, ctype, env), false);
  195. UNIT_ASSERT_NO_EXCEPTION(TOptionalLiteral::Create(dynItem, opt2typeDyn, env));
  196. }
  197. Y_UNIT_TEST(TestDictType) {
  198. TScopedAlloc alloc(__LOCATION__);
  199. TTypeEnvironment env(alloc);
  200. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<ui32>::Id, env);
  201. TDictType* dictType1 = TDictType::Create(dtype1, env.GetVoidLazy()->GetGenericType(), env);
  202. UNIT_ASSERT_EQUAL(dictType1->GetKind(), TType::EKind::Dict);
  203. TDictType* dictType2 = TDictType::Create(dtype1, env.GetEmptyStructLazy()->GetGenericType(), env);
  204. TDictType* dictType1Cloned = TDictType::Create(dtype1, env.GetVoidLazy()->GetGenericType(), env);
  205. UNIT_ASSERT(dictType1->IsSameType(*dictType1Cloned));
  206. UNIT_ASSERT(!dictType1->IsSameType(*dictType2));
  207. }
  208. Y_UNIT_TEST(TestCallableType) {
  209. TScopedAlloc alloc(__LOCATION__);
  210. TTypeEnvironment env(alloc);
  211. TCallableType* ctype1 = TCallableType::Create("c1", env.GetTypeOfVoidLazy(),
  212. 0, nullptr, nullptr, env);
  213. UNIT_ASSERT_EQUAL(ctype1->GetKind(), TType::EKind::Callable);
  214. UNIT_ASSERT_EQUAL(ctype1->GetName(), "c1");
  215. UNIT_ASSERT_EQUAL(ctype1->GetArgumentsCount(), 0);
  216. UNIT_ASSERT_EQUAL(ctype1->GetReturnType()->GetKind(), TType::EKind::Void);
  217. TVector<TType*> types;
  218. types.push_back(env.GetVoidLazy()->GetGenericType());
  219. types.push_back(env.GetEmptyStructLazy()->GetGenericType());
  220. TCallableType* ctype2 = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types.size(), types.data(), nullptr, env);
  221. UNIT_ASSERT_EQUAL(ctype2->GetName(), "c2");
  222. UNIT_ASSERT_EQUAL(ctype2->GetReturnType()->GetKind(), TType::EKind::Void);
  223. UNIT_ASSERT_EQUAL(ctype2->GetArgumentsCount(), 2);
  224. UNIT_ASSERT_EQUAL(ctype2->GetArgumentType(0)->GetKind(), TType::EKind::Void);
  225. UNIT_ASSERT_EQUAL(ctype2->GetArgumentType(1)->GetKind(), TType::EKind::Struct);
  226. TCallableType* ctype2Cloned = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types.size(), types.data(), nullptr, env);
  227. UNIT_ASSERT(ctype2->IsSameType(*ctype2));
  228. UNIT_ASSERT(ctype2->IsSameType(*ctype2Cloned));
  229. UNIT_ASSERT(!ctype2->IsSameType(*ctype1));
  230. TVector<TType*> types2;
  231. types2.push_back(env.GetEmptyStructLazy()->GetGenericType());
  232. types2.push_back(env.GetVoidLazy()->GetGenericType());
  233. TCallableType* ctype2rev = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types2.size(), types2.data(), nullptr, env);
  234. UNIT_ASSERT(!ctype2->IsSameType(*ctype2rev));
  235. TVector<TType*> types3;
  236. types3.push_back(env.GetVoidLazy()->GetGenericType());
  237. types3.push_back(env.GetEmptyStructLazy()->GetGenericType());
  238. TCallableType* ctype2withPayload1 = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types.size(), types.data(), env.GetEmptyStructLazy(), env);
  239. UNIT_ASSERT(!ctype2withPayload1->IsSameType(*ctype2));
  240. TCallableType* ctype2withPayload2 = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types.size(), types.data(), env.GetListOfVoidLazy(), env);
  241. UNIT_ASSERT(!ctype2withPayload2->IsSameType(*ctype2withPayload1));
  242. TCallableType* ctype2withPayload2clone = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types.size(), types.data(), env.GetListOfVoidLazy(), env);
  243. UNIT_ASSERT(ctype2withPayload2clone->IsSameType(*ctype2withPayload2));
  244. TCallableType* ctype2optArg = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types.size(), types.data(), nullptr, env);
  245. ctype2optArg->SetOptionalArgumentsCount(0);
  246. UNIT_ASSERT(ctype2optArg->IsSameType(*ctype2));
  247. UNIT_ASSERT(ctype2optArg->IsConvertableTo(*ctype2));
  248. UNIT_ASSERT(ctype2->IsSameType(*ctype2optArg));
  249. UNIT_ASSERT(ctype2->IsConvertableTo(*ctype2optArg));
  250. UNIT_ASSERT_EXCEPTION(ctype2optArg->SetOptionalArgumentsCount(1), yexception);
  251. UNIT_ASSERT_EXCEPTION(ctype2optArg->SetOptionalArgumentsCount(3), yexception);
  252. }
  253. template<typename... T>
  254. struct TArgs { };
  255. template<typename... T>
  256. struct TOpt { };
  257. template<>
  258. struct TArgs<> {
  259. void Build(bool inc, TVector<TType*>& types, int& opts, TTypeEnvironment& env) const {
  260. Y_UNUSED(inc);
  261. Y_UNUSED(types);
  262. Y_UNUSED(opts);
  263. Y_UNUSED(env);
  264. }
  265. };
  266. template<typename... T>
  267. struct TArgs<TOpt<T...>>
  268. {
  269. void Build(bool, TVector<TType*>& types, int& opts, TTypeEnvironment& env) const {
  270. TArgs<T...>().Build(true, types, opts, env);
  271. }
  272. };
  273. template<typename H, typename... T>
  274. struct TArgs<H, T...>
  275. {
  276. void Build(bool inc, TVector<TType*>& types, int& opts, TTypeEnvironment& env) const {
  277. if (inc) {
  278. opts ++;
  279. }
  280. auto* type = TOptionalType::Create(env.GetEmptyTupleLazy()->GetGenericType(), env);
  281. types.push_back(type);
  282. TArgs<T...>().Build(inc, types, opts, env);
  283. }
  284. };
  285. template<typename... T1, typename... T2>
  286. void IsConvertableTo(const TArgs<T1...>& f1, const TArgs<T2...>& f2, TTypeEnvironment& env, bool result) {
  287. TVector<TType*> types1; int opts1 = 0;
  288. TVector<TType*> types2; int opts2 = 0;
  289. f1.Build(false, types1, opts1, env);
  290. f2.Build(false, types2, opts2, env);
  291. TCallableType* c1 = TCallableType::Create("c1", env.GetVoidLazy()->GetGenericType(), types1.size(), types1.data(), nullptr, env);
  292. c1->SetOptionalArgumentsCount(opts1);
  293. TCallableType* c2 = TCallableType::Create("c2", env.GetVoidLazy()->GetGenericType(), types2.size(), types2.data(), nullptr, env);
  294. c2->SetOptionalArgumentsCount(opts2);
  295. UNIT_ASSERT(c1->IsConvertableTo(*c2) == result);
  296. }
  297. Y_UNIT_TEST(TestCallableTypeWithOptionalArguments) {
  298. TScopedAlloc alloc(__LOCATION__);
  299. TTypeEnvironment env(alloc);
  300. IsConvertableTo(TArgs<TOpt<int,int,int>>(), TArgs<int,int,int>(), env, true);
  301. IsConvertableTo(TArgs<int,int>(), TArgs<int,int>(), env, true);
  302. IsConvertableTo(TArgs<int,int>(), TArgs<int,TOpt<int>>(), env, false);
  303. IsConvertableTo(TArgs<int,TOpt<int>>(), TArgs<int,int>(), env, true);
  304. IsConvertableTo(TArgs<TOpt<int,int>>(), TArgs<int,int>(), env, true);
  305. IsConvertableTo(TArgs<TOpt<int,int,int>>(), TArgs<int,TOpt<int>>(), env, true);
  306. IsConvertableTo(TArgs<TOpt<int,int>>(), TArgs<int,TOpt<int,int>>(), env, false);
  307. IsConvertableTo(TArgs<int,int,int>(), TArgs<int,TOpt<int>>(), env, false);
  308. }
  309. Y_UNIT_TEST(TestDictLiteral) {
  310. TScopedAlloc alloc(__LOCATION__);
  311. TTypeEnvironment env(alloc);
  312. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<char*>::Id, env);
  313. TDataType* dtype2 = TDataType::Create(NUdf::TDataType<ui32>::Id, env);
  314. TDictType* dict1Type = TDictType::Create(dtype1, env.GetVoidLazy()->GetGenericType(), env);
  315. TDictType* dict2Type = TDictType::Create(dtype1, dtype2, env);
  316. TVector<std::pair<TRuntimeNode, TRuntimeNode>> emptyItems;
  317. UNIT_ASSERT_NO_EXCEPTION(TDictLiteral::Create(emptyItems.size(), emptyItems.data(), dict1Type, env));
  318. TString u = "34567";
  319. TVector<std::pair<TRuntimeNode, TRuntimeNode>> someItems;
  320. someItems.push_back(std::make_pair(TRuntimeNode(TDataLiteral::Create(
  321. NUdf::TUnboxedValuePod::Embedded(u), dtype1, env), true),
  322. TRuntimeNode(TDataLiteral::Create(
  323. NUdf::TUnboxedValuePod((ui32)13), dtype2, env), true)));
  324. u = "878";
  325. someItems.push_back(std::make_pair(TRuntimeNode(TDataLiteral::Create(
  326. NUdf::TUnboxedValuePod::Embedded(u), dtype1, env), true),
  327. TRuntimeNode(TDataLiteral::Create(NUdf::TUnboxedValuePod((ui32)14), dtype2, env), true)));
  328. TDictLiteral* dict2 = TDictLiteral::Create(someItems.size(), someItems.data(), dict2Type, env);
  329. UNIT_ASSERT_EQUAL(dict2->GetItemsCount(), 2);
  330. UNIT_ASSERT_EQUAL(dict2->GetItem(0).first.GetNode()->GetType()->GetKind(), TType::EKind::Data);
  331. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*dict2->GetItem(0).first.GetNode()).AsValue().AsStringRef(), NUdf::TStringRef::Of("34567"));
  332. UNIT_ASSERT_EQUAL(dict2->GetItem(0).second.GetNode()->GetType()->GetKind(), TType::EKind::Data);
  333. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*dict2->GetItem(0).second.GetNode()).AsValue().Get<ui32>(), 13);
  334. UNIT_ASSERT_EQUAL(dict2->GetItem(1).first.GetNode()->GetType()->GetKind(), TType::EKind::Data);
  335. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*dict2->GetItem(1).first.GetNode()).AsValue().AsStringRef(), NUdf::TStringRef::Of("878"));
  336. UNIT_ASSERT_EQUAL(dict2->GetItem(1).second.GetNode()->GetType()->GetKind(), TType::EKind::Data);
  337. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*dict2->GetItem(1).second.GetNode()).AsValue().Get<ui32>(), 14);
  338. UNIT_ASSERT_EXCEPTION(TDictLiteral::Create(someItems.size(), someItems.data(), dict1Type, env), yexception);
  339. TDictType* dict2TypeDyn = TDictType::Create(dtype1, dtype2, env);
  340. UNIT_ASSERT_NO_EXCEPTION(TDictLiteral::Create(someItems.size(), someItems.data(), dict2TypeDyn, env));
  341. TVector<std::pair<TRuntimeNode, TRuntimeNode>> someDynItems;
  342. TCallableType* ctype = TCallableType::Create("c1", dtype1, 0, nullptr, nullptr, env);
  343. someDynItems.push_back(std::make_pair(
  344. TRuntimeNode(TCallable::Create(0, nullptr, ctype, env), false),
  345. TRuntimeNode(TDataLiteral::Create(NUdf::TUnboxedValuePod((ui32)123), dtype2, env), true)));
  346. UNIT_ASSERT_NO_EXCEPTION(TDictLiteral::Create(someDynItems.size(), someDynItems.data(), dict2TypeDyn, env));
  347. }
  348. Y_UNIT_TEST(TestCallable) {
  349. TScopedAlloc alloc(__LOCATION__);
  350. TTypeEnvironment env(alloc);
  351. TCallableType* ctype1 = TCallableType::Create("c1", env.GetTypeOfVoidLazy(),
  352. 0, nullptr, nullptr, env);
  353. TCallable* c1 = TCallable::Create(0, nullptr, ctype1, env);
  354. UNIT_ASSERT_EQUAL(c1->GetInputsCount(), 0);
  355. UNIT_ASSERT(!c1->HasResult());
  356. c1->SetResult(TRuntimeNode(env.GetVoidLazy(), true), env);
  357. UNIT_ASSERT(c1->HasResult());
  358. UNIT_ASSERT_EQUAL(c1->GetResult().GetStaticType()->GetKind(), TType::EKind::Void);
  359. TVector<TType*> ctype2args;
  360. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<char*>::Id, env);
  361. ctype2args.push_back(dtype1);
  362. ctype2args.push_back(dtype1);
  363. TCallableType* ctype2 = TCallableType::Create("c2", env.GetTypeOfVoidLazy(), ctype2args.size(), ctype2args.data(), nullptr, env);
  364. TCallableType* ctype2cloned = TCallableType::Create("c2", env.GetTypeOfVoidLazy(), ctype2args.size(), ctype2args.data(), nullptr, env);
  365. UNIT_ASSERT(ctype2cloned->IsSameType(*ctype2));
  366. UNIT_ASSERT(!ctype2cloned->IsSameType(*ctype1));
  367. TCallableType* ctype3 = TCallableType::Create("c1", dtype1, 0, nullptr, nullptr, env);
  368. TVector<TRuntimeNode> c2args;
  369. c2args.push_back(TRuntimeNode(TDataLiteral::Create(
  370. NUdf::TUnboxedValuePod::Embedded("abc"), dtype1, env), true));
  371. c2args.push_back(TRuntimeNode(TCallable::Create(0, nullptr, ctype3, env), false));
  372. TCallable* c2 = TCallable::Create(c2args.size(), c2args.data(), ctype2, env);
  373. UNIT_ASSERT_EQUAL(c2->GetInputsCount(), 2);
  374. UNIT_ASSERT_EQUAL(c2->GetInput(0).IsImmediate(), true);
  375. UNIT_ASSERT_EQUAL(c2->GetInput(0).GetNode()->GetType()->GetKind(), TType::EKind::Data);
  376. UNIT_ASSERT_EQUAL(c2->GetInput(1).IsImmediate(), false);
  377. UNIT_ASSERT_EQUAL(c2->GetInput(1).GetNode()->GetType()->GetKind(), TType::EKind::Callable);
  378. UNIT_ASSERT(!c2->HasResult());
  379. c2->SetResult(TRuntimeNode(env.GetVoidLazy(), true), env);
  380. UNIT_ASSERT(c2->HasResult());
  381. UNIT_ASSERT_EQUAL(c2->GetResult().GetStaticType()->GetKind(), TType::EKind::Void);
  382. }
  383. Y_UNIT_TEST(TestThrowingVisitor) {
  384. TScopedAlloc alloc(__LOCATION__);
  385. TTypeEnvironment env(alloc);
  386. TThrowingNodeVisitor visitor;
  387. UNIT_ASSERT_EXCEPTION(visitor.Visit(*env.GetTypeOfTypeLazy()), yexception);
  388. }
  389. Y_UNIT_TEST(TestEmptyVisitor) {
  390. TScopedAlloc alloc(__LOCATION__);
  391. TTypeEnvironment env(alloc);
  392. TEmptyNodeVisitor visitor;
  393. visitor.Visit(*env.GetTypeOfTypeLazy());
  394. }
  395. Y_UNIT_TEST(TesAnyType) {
  396. TScopedAlloc alloc(__LOCATION__);
  397. TTypeEnvironment env(alloc);
  398. UNIT_ASSERT(env.GetAnyTypeLazy()->IsSameType(*env.GetAnyTypeLazy()));
  399. }
  400. Y_UNIT_TEST(TestAny) {
  401. TScopedAlloc alloc(__LOCATION__);
  402. TTypeEnvironment env(alloc);
  403. TAny* emptyAny = TAny::Create(env);
  404. UNIT_ASSERT(!emptyAny->HasItem());
  405. TAny* emptyAny2 = TAny::Create(env);
  406. UNIT_ASSERT(!emptyAny->TNode::Equals(*emptyAny2));
  407. TDataType* dtype1 = TDataType::Create(NUdf::TDataType<char*>::Id, env);
  408. TString u = "34567";
  409. auto item1 = TRuntimeNode(TDataLiteral::Create(
  410. NUdf::TUnboxedValuePod::Embedded(u), dtype1, env), true);
  411. TAny* any1 = TAny::Create(env);
  412. any1->SetItem(item1);
  413. UNIT_ASSERT(any1->HasItem());
  414. UNIT_ASSERT_EQUAL(any1->GetItem().GetNode()->GetType()->GetKind(), TType::EKind::Data);
  415. UNIT_ASSERT_EQUAL(static_cast<const TDataLiteral&>(*any1->GetItem().GetNode()).AsValue().AsStringRef(), NUdf::TStringRef::Of("34567"));
  416. auto item2 = TRuntimeNode(TDataLiteral::Create(
  417. NUdf::TUnboxedValuePod::Embedded(u), dtype1, env), true);
  418. TAny* any2 = TAny::Create(env);
  419. any2->SetItem(item2);
  420. UNIT_ASSERT(any1->TNode::Equals(*any2));
  421. }
  422. Y_UNIT_TEST(TestTupleType) {
  423. TScopedAlloc alloc(__LOCATION__);
  424. TTypeEnvironment env(alloc);
  425. TTupleType* tempty = env.GetEmptyTupleLazy()->GetType();
  426. UNIT_ASSERT_EQUAL(tempty->GetKind(), TType::EKind::Tuple);
  427. UNIT_ASSERT_EQUAL(tempty->GetElementsCount(), 0);
  428. TVector<TType*> t1elems;
  429. t1elems.push_back(env.GetVoidLazy()->GetGenericType());
  430. TTupleType* t1 = TTupleType::Create(t1elems.size(), t1elems.data(), env);
  431. UNIT_ASSERT_EQUAL(t1->GetElementsCount(), 1);
  432. UNIT_ASSERT_EQUAL(t1->GetElementType(0)->GetKind(), TType::EKind::Void);
  433. TVector<TType*> t2elems;
  434. t2elems.push_back(env.GetEmptyStructLazy()->GetGenericType());
  435. t2elems.push_back(env.GetTypeOfVoidLazy());
  436. TTupleType* t2 = TTupleType::Create(t2elems.size(), t2elems.data(), env);
  437. UNIT_ASSERT_EQUAL(t2->GetElementsCount(), 2);
  438. UNIT_ASSERT_EQUAL(t2->GetElementType(0)->GetKind(), TType::EKind::Struct);
  439. UNIT_ASSERT_EQUAL(t2->GetElementType(1)->GetKind(), TType::EKind::Void);
  440. TTupleType* t2cloned = TTupleType::Create(t2elems.size(), t2elems.data(), env);
  441. UNIT_ASSERT(t2cloned->IsSameType(*t2cloned));
  442. UNIT_ASSERT(t2cloned->IsSameType(*t2));
  443. UNIT_ASSERT(!t2cloned->IsSameType(*t1));
  444. }
  445. Y_UNIT_TEST(TestTupleLiteral) {
  446. TScopedAlloc alloc(__LOCATION__);
  447. TTypeEnvironment env(alloc);
  448. TTupleType* temptyType = env.GetEmptyTupleLazy()->GetType();
  449. TTupleLiteral* tempty = TTupleLiteral::Create(0, nullptr, temptyType, env);
  450. UNIT_ASSERT_EQUAL(tempty->GetValuesCount(), 0);
  451. TVector<TType*> t1elems;
  452. t1elems.push_back(env.GetVoidLazy()->GetGenericType());
  453. TTupleType* t1type = TTupleType::Create(t1elems.size(), t1elems.data(), env);
  454. TVector<TRuntimeNode> t1values;
  455. t1values.push_back(TRuntimeNode(env.GetVoidLazy(), true));
  456. TTupleLiteral* t1 = TTupleLiteral::Create(t1values.size(), t1values.data(), t1type, env);
  457. UNIT_ASSERT_EQUAL(t1->GetValuesCount(), 1);
  458. UNIT_ASSERT_EQUAL(t1->GetValue(0).GetNode(), t1values[0].GetNode());
  459. UNIT_ASSERT_EXCEPTION(TTupleLiteral::Create(t1values.size(), t1values.data(), temptyType, env), yexception);
  460. TVector<TType*> t2elems;
  461. t2elems.push_back(env.GetEmptyStructLazy()->GetGenericType());
  462. TTupleType* t2type = TTupleType::Create(t2elems.size(), t2elems.data(), env);
  463. UNIT_ASSERT_EXCEPTION(TTupleLiteral::Create(t1values.size(), t1values.data(), t2type, env), yexception);
  464. TTupleType* t1typeDyn = TTupleType::Create(t1elems.size(), t1elems.data(), env);
  465. TVector<TRuntimeNode> t1DynValues;
  466. TCallableType* ctype = TCallableType::Create("c1", env.GetVoidLazy()->GetGenericType(),
  467. 0, nullptr, nullptr, env);
  468. t1DynValues.push_back(TRuntimeNode(TCallable::Create(0, nullptr, ctype, env), false));
  469. UNIT_ASSERT_NO_EXCEPTION(TTupleLiteral::Create(t1DynValues.size(), t1DynValues.data(), t1typeDyn, env));
  470. UNIT_ASSERT_NO_EXCEPTION(TTupleLiteral::Create(t1values.size(), t1values.data(), t1typeDyn, env));
  471. }
  472. Y_UNIT_TEST(TestVariantType) {
  473. TScopedAlloc alloc(__LOCATION__);
  474. TTypeEnvironment env(alloc);
  475. auto emptyStructType = env.GetEmptyStructLazy()->GetType();
  476. auto emptyTupleType = env.GetEmptyTupleLazy()->GetType();
  477. UNIT_ASSERT_EXCEPTION(TVariantType::Create(emptyStructType, env), yexception);
  478. UNIT_ASSERT_EXCEPTION(TVariantType::Create(emptyTupleType, env), yexception);
  479. // one element tuple
  480. TType* elements[2] = {
  481. TDataType::Create(NUdf::TDataType<i32>::Id, env),
  482. emptyStructType
  483. };
  484. auto tuple1type = TTupleType::Create(1, elements, env);
  485. auto var1tuple = TVariantType::Create(tuple1type, env);
  486. UNIT_ASSERT_VALUES_EQUAL(var1tuple->GetAlternativesCount(), 1);
  487. UNIT_ASSERT(var1tuple->GetUnderlyingType() == tuple1type);
  488. // two elements tuple
  489. auto tuple2type = TTupleType::Create(2, elements, env);
  490. auto var2tuple = TVariantType::Create(tuple2type, env);
  491. UNIT_ASSERT_VALUES_EQUAL(var2tuple->GetAlternativesCount(), 2);
  492. UNIT_ASSERT(var2tuple->GetUnderlyingType() == tuple2type);
  493. // one element struct
  494. TStructMember members[2] = {
  495. { "A", TDataType::Create(NUdf::TDataType<i32>::Id, env) },
  496. { "B", emptyStructType }
  497. };
  498. auto struct1type = TStructType::Create(1, members, env);
  499. auto var1struct = TVariantType::Create(struct1type, env);
  500. UNIT_ASSERT_VALUES_EQUAL(var1struct->GetAlternativesCount(), 1);
  501. UNIT_ASSERT(var1struct->GetUnderlyingType() == struct1type);
  502. // two elements struct
  503. auto struct2type = TStructType::Create(2, members, env);
  504. auto var2struct = TVariantType::Create(struct2type, env);
  505. UNIT_ASSERT_VALUES_EQUAL(var2struct->GetAlternativesCount(), 2);
  506. UNIT_ASSERT(var2struct->GetUnderlyingType() == struct2type);
  507. }
  508. Y_UNIT_TEST(TestVariantLiteral) {
  509. TScopedAlloc alloc(__LOCATION__);
  510. TTypeEnvironment env(alloc);
  511. auto emptyStructType = env.GetEmptyStructLazy()->GetType();
  512. // one element tuple
  513. auto dt = TDataType::Create(NUdf::TDataType<i32>::Id, env);
  514. TType* elements[2] = {
  515. dt,
  516. emptyStructType
  517. };
  518. auto tuple1type = TTupleType::Create(1, elements, env);
  519. auto var1tuple = TVariantType::Create(tuple1type, env);
  520. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(TRuntimeNode(env.GetEmptyTupleLazy(), true), 0, var1tuple, env), yexception);
  521. auto i32value = TRuntimeNode(TDataLiteral::Create(NUdf::TUnboxedValuePod((i32)42), dt, env), true);
  522. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(i32value, 23, var1tuple, env), yexception);
  523. auto varValue = TVariantLiteral::Create(i32value, 0, var1tuple, env);
  524. UNIT_ASSERT_VALUES_EQUAL(varValue->GetIndex(), 0);
  525. UNIT_ASSERT(varValue->GetItem() == i32value);
  526. // two elements tuple
  527. auto tuple2type = TTupleType::Create(2, elements, env);
  528. auto var2tuple = TVariantType::Create(tuple2type, env);
  529. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(TRuntimeNode(env.GetEmptyTupleLazy(), true), 0, var2tuple, env), yexception);
  530. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(i32value, 23, var2tuple, env), yexception);
  531. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(i32value, 1, var2tuple, env), yexception);
  532. varValue = TVariantLiteral::Create(i32value, 0, var2tuple, env);
  533. UNIT_ASSERT_VALUES_EQUAL(varValue->GetIndex(), 0);
  534. UNIT_ASSERT(varValue->GetItem() == i32value);
  535. varValue = TVariantLiteral::Create(TRuntimeNode(env.GetEmptyStructLazy(), true), 1, var2tuple, env);
  536. UNIT_ASSERT_VALUES_EQUAL(varValue->GetIndex(), 1);
  537. UNIT_ASSERT(varValue->GetItem() == TRuntimeNode(env.GetEmptyStructLazy(), true));
  538. // one element struct
  539. TStructMember members[2] = {
  540. { "A", TDataType::Create(NUdf::TDataType<i32>::Id, env) },
  541. { "B", emptyStructType }
  542. };
  543. auto struct1type = TStructType::Create(1, members, env);
  544. auto var1struct = TVariantType::Create(struct1type, env);
  545. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(TRuntimeNode(env.GetEmptyTupleLazy(), true), 0, var1struct, env), yexception);
  546. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(i32value, 23, var1struct, env), yexception);
  547. varValue = TVariantLiteral::Create(i32value, 0, var1struct, env);
  548. UNIT_ASSERT_VALUES_EQUAL(varValue->GetIndex(), 0);
  549. UNIT_ASSERT(varValue->GetItem() == i32value);
  550. // two elements struct
  551. auto struct2type = TStructType::Create(2, members, env);
  552. auto var2struct = TVariantType::Create(struct2type, env);
  553. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(TRuntimeNode(env.GetEmptyTupleLazy(), true), 0, var2struct, env), yexception);
  554. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(i32value, 23, var2struct, env), yexception);
  555. UNIT_ASSERT_EXCEPTION(TVariantLiteral::Create(i32value, 1, var2struct, env), yexception);
  556. varValue = TVariantLiteral::Create(i32value, 0, var2struct, env);
  557. UNIT_ASSERT_VALUES_EQUAL(varValue->GetIndex(), 0);
  558. UNIT_ASSERT(varValue->GetItem() == i32value);
  559. varValue = TVariantLiteral::Create(TRuntimeNode(env.GetEmptyStructLazy(), true), 1, var2struct, env);
  560. UNIT_ASSERT_VALUES_EQUAL(varValue->GetIndex(), 1);
  561. UNIT_ASSERT(varValue->GetItem() == TRuntimeNode(env.GetEmptyStructLazy(), true));
  562. }
  563. }
  564. }
  565. }