mkql_wide_map_ut.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. #include "mkql_computation_node_ut.h"
  2. #include <yql/essentials/minikql/mkql_runtime_version.h>
  3. namespace NKikimr {
  4. namespace NMiniKQL {
  5. #if !defined(MKQL_RUNTIME_VERSION) || MKQL_RUNTIME_VERSION >= 18u
  6. Y_UNIT_TEST_SUITE(TMiniKQLWideMapTest) {
  7. Y_UNIT_TEST_LLVM(TestSimpleSwap) {
  8. TSetup<LLVM> setup;
  9. TProgramBuilder& pb = *setup.PgmBuilder;
  10. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  11. const auto tupleType = pb.NewTupleType({dataType, dataType, dataType});
  12. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-1))});
  13. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2))});
  14. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-3))});
  15. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(dataType)});
  16. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  17. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.ExpandMap(pb.ToFlow(list),
  18. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U)}; }),
  19. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple({items[2U], items[1U], items[0U] }); }
  20. ));
  21. const auto graph = setup.BuildGraph(pgmReturn);
  22. const auto iterator = graph->GetValue().GetListIterator();
  23. NUdf::TUnboxedValue item;
  24. UNIT_ASSERT(iterator.Next(item));
  25. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -1);
  26. UNIT_ASSERT(!item.GetElement(1));
  27. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 1);
  28. UNIT_ASSERT(iterator.Next(item));
  29. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -2);
  30. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 2);
  31. UNIT_ASSERT(!item.GetElement(2));
  32. UNIT_ASSERT(iterator.Next(item));
  33. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -3);
  34. UNIT_ASSERT(!item.GetElement(1));
  35. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 3);
  36. UNIT_ASSERT(iterator.Next(item));
  37. UNIT_ASSERT(!item.GetElement(0));
  38. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  39. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 4);
  40. UNIT_ASSERT(!iterator.Next(item));
  41. UNIT_ASSERT(!iterator.Next(item));
  42. }
  43. Y_UNIT_TEST_LLVM(TestThinLambda) {
  44. TSetup<LLVM> setup;
  45. TProgramBuilder& pb = *setup.PgmBuilder;
  46. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  47. const auto tupleType = pb.NewTupleType({dataType});
  48. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1))});
  49. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(dataType)});
  50. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3))});
  51. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4))});
  52. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  53. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.WideMap(pb.ExpandMap(pb.ToFlow(list),
  54. [&](TRuntimeNode) -> TRuntimeNode::TList { return {}; }),
  55. [&](TRuntimeNode::TList items) { return items; }),
  56. [&](TRuntimeNode::TList) -> TRuntimeNode { return pb.NewTuple({}); }
  57. ));
  58. const auto graph = setup.BuildGraph(pgmReturn);
  59. const auto iterator = graph->GetValue().GetListIterator();
  60. NUdf::TUnboxedValue item;
  61. UNIT_ASSERT(iterator.Next(item));
  62. UNIT_ASSERT(iterator.Next(item));
  63. UNIT_ASSERT(iterator.Next(item));
  64. UNIT_ASSERT(iterator.Next(item));
  65. UNIT_ASSERT(!iterator.Next(item));
  66. UNIT_ASSERT(!iterator.Next(item));
  67. }
  68. Y_UNIT_TEST_LLVM(TestWideMap) {
  69. TSetup<LLVM> setup;
  70. TProgramBuilder& pb = *setup.PgmBuilder;
  71. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  72. const auto tupleType = pb.NewTupleType({dataType, dataType, dataType});
  73. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-1))});
  74. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2))});
  75. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-3))});
  76. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(dataType)});
  77. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  78. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.WideMap(pb.ExpandMap(pb.ToFlow(list),
  79. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U)}; }),
  80. [&](TRuntimeNode::TList items) -> TRuntimeNode::TList { return {pb.AggrMin(items[0], items[1]), pb.AggrMax(items[1], items[2]), pb.AggrAdd(items[0], items[2])}; }),
  81. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); }
  82. ));
  83. const auto graph = setup.BuildGraph(pgmReturn);
  84. const auto iterator = graph->GetValue().GetListIterator();
  85. NUdf::TUnboxedValue item;
  86. UNIT_ASSERT(iterator.Next(item));
  87. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  88. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -1);
  89. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 0);
  90. UNIT_ASSERT(iterator.Next(item));
  91. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 2);
  92. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 2);
  93. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -2);
  94. UNIT_ASSERT(iterator.Next(item));
  95. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 3);
  96. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -3);
  97. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 0);
  98. UNIT_ASSERT(iterator.Next(item));
  99. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 4);
  100. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  101. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 4);
  102. UNIT_ASSERT(!iterator.Next(item));
  103. UNIT_ASSERT(!iterator.Next(item));
  104. }
  105. Y_UNIT_TEST_LLVM(TestDotCalculateUnusedField) {
  106. TSetup<LLVM> setup;
  107. TProgramBuilder& pb = *setup.PgmBuilder;
  108. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  109. const auto tupleType = pb.NewTupleType({dataType, dataType, dataType});
  110. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewOptional(pb.NewDataLiteral<i32>(0)), pb.NewOptional(pb.NewDataLiteral<i32>(-1))});
  111. const auto data2 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-2))});
  112. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-3))});
  113. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-4))});
  114. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  115. const auto landmine = pb.NewDataLiteral<NUdf::EDataSlot::String>("ACHTUNG MINEN!");
  116. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.WideMap(pb.ExpandMap(pb.ToFlow(list),
  117. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U)}; }),
  118. [&](TRuntimeNode::TList items) -> TRuntimeNode::TList { return {pb.Mul(items.front(), items.back()), pb.Unwrap(items[1], landmine, __FILE__, __LINE__, 0), pb.Add(items.front(), items.back())}; }),
  119. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple({items.back(), items.front()}); }
  120. ));
  121. const auto graph = setup.BuildGraph(pgmReturn);
  122. const auto iterator = graph->GetValue().GetListIterator();
  123. NUdf::TUnboxedValue item;
  124. UNIT_ASSERT(iterator.Next(item));
  125. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 0);
  126. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -1);
  127. UNIT_ASSERT(iterator.Next(item));
  128. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 0);
  129. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -4);
  130. UNIT_ASSERT(iterator.Next(item));
  131. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 0);
  132. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -9);
  133. UNIT_ASSERT(iterator.Next(item));
  134. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 0);
  135. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -16);
  136. UNIT_ASSERT(!iterator.Next(item));
  137. UNIT_ASSERT(!iterator.Next(item));
  138. }
  139. Y_UNIT_TEST_LLVM(TestPasstroughtFieldsAsIs) {
  140. TSetup<LLVM> setup;
  141. TProgramBuilder& pb = *setup.PgmBuilder;
  142. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  143. const auto tupleType = pb.NewTupleType({dataType, dataType, dataType});
  144. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewOptional(pb.NewDataLiteral<i32>(-5)), pb.NewOptional(pb.NewDataLiteral<i32>(-1))});
  145. const auto data2 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-4)), pb.NewOptional(pb.NewDataLiteral<i32>(-2))});
  146. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewOptional(pb.NewDataLiteral<i32>(-7)), pb.NewOptional(pb.NewDataLiteral<i32>(-3))});
  147. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-4))});
  148. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  149. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.WideMap(pb.ExpandMap(pb.ToFlow(list),
  150. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U)}; }),
  151. [&](TRuntimeNode::TList items) -> TRuntimeNode::TList { return {items.front(), pb.Minus(items[1u]), items.back()}; }),
  152. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); }
  153. ));
  154. const auto graph = setup.BuildGraph(pgmReturn);
  155. const auto iterator = graph->GetValue().GetListIterator();
  156. NUdf::TUnboxedValue item;
  157. UNIT_ASSERT(iterator.Next(item));
  158. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  159. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 5);
  160. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -1);
  161. UNIT_ASSERT(iterator.Next(item));
  162. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 2);
  163. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  164. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -2);
  165. UNIT_ASSERT(iterator.Next(item));
  166. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 3);
  167. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 7);
  168. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -3);
  169. UNIT_ASSERT(iterator.Next(item));
  170. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 4);
  171. UNIT_ASSERT(!item.GetElement(1));
  172. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -4);
  173. UNIT_ASSERT(!iterator.Next(item));
  174. UNIT_ASSERT(!iterator.Next(item));
  175. }
  176. Y_UNIT_TEST_LLVM(TestPasstroughtFieldSplitAsIs) {
  177. TSetup<LLVM> setup;
  178. TProgramBuilder& pb = *setup.PgmBuilder;
  179. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  180. const auto tupleType = pb.NewTupleType({dataType, dataType, dataType});
  181. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewOptional(pb.NewDataLiteral<i32>(-5)), pb.NewOptional(pb.NewDataLiteral<i32>(-1))});
  182. const auto data2 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-4)), pb.NewOptional(pb.NewDataLiteral<i32>(-2))});
  183. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewOptional(pb.NewDataLiteral<i32>(-7)), pb.NewOptional(pb.NewDataLiteral<i32>(-3))});
  184. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-4))});
  185. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  186. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.WideMap(pb.ExpandMap(pb.ToFlow(list),
  187. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U)}; }),
  188. [&](TRuntimeNode::TList items) -> TRuntimeNode::TList { return {items[1U], pb.Mul(items.front(), items.back()), items[1U]}; }),
  189. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); }
  190. ));
  191. const auto graph = setup.BuildGraph(pgmReturn);
  192. const auto iterator = graph->GetValue().GetListIterator();
  193. NUdf::TUnboxedValue item;
  194. UNIT_ASSERT(iterator.Next(item));
  195. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -5);
  196. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -1);
  197. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -5);
  198. UNIT_ASSERT(iterator.Next(item));
  199. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -4);
  200. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -4);
  201. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -4);
  202. UNIT_ASSERT(iterator.Next(item));
  203. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -7);
  204. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -9);
  205. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), -7);
  206. UNIT_ASSERT(iterator.Next(item));
  207. UNIT_ASSERT(!item.GetElement(0));
  208. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -16);
  209. UNIT_ASSERT(!item.GetElement(2));
  210. UNIT_ASSERT(!iterator.Next(item));
  211. UNIT_ASSERT(!iterator.Next(item));
  212. }
  213. Y_UNIT_TEST_LLVM(TestFieldBothWayPasstroughtAndArg) {
  214. TSetup<LLVM> setup;
  215. TProgramBuilder& pb = *setup.PgmBuilder;
  216. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  217. const auto tupleType = pb.NewTupleType({dataType, dataType, dataType});
  218. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewOptional(pb.NewDataLiteral<i32>(-5)), pb.NewOptional(pb.NewDataLiteral<i32>(-1))});
  219. const auto data2 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-4)), pb.NewOptional(pb.NewDataLiteral<i32>(-2))});
  220. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewOptional(pb.NewDataLiteral<i32>(-7)), pb.NewOptional(pb.NewDataLiteral<i32>(-3))});
  221. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-4))});
  222. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  223. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.WideMap(pb.ExpandMap(pb.ToFlow(list),
  224. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U)}; }),
  225. [&](TRuntimeNode::TList items) -> TRuntimeNode::TList { return {items[1U], pb.Sub(items.front(), items.back()), pb.Minus(items[1U])}; }),
  226. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); }
  227. ));
  228. const auto graph = setup.BuildGraph(pgmReturn);
  229. const auto iterator = graph->GetValue().GetListIterator();
  230. NUdf::TUnboxedValue item;
  231. UNIT_ASSERT(iterator.Next(item));
  232. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -5);
  233. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 2);
  234. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 5);
  235. UNIT_ASSERT(iterator.Next(item));
  236. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -4);
  237. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  238. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 4);
  239. UNIT_ASSERT(iterator.Next(item));
  240. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -7);
  241. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 6);
  242. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(2).template Get<i32>(), 7);
  243. UNIT_ASSERT(iterator.Next(item));
  244. UNIT_ASSERT(!item.GetElement(0));
  245. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 8);
  246. UNIT_ASSERT(!item.GetElement(2));
  247. UNIT_ASSERT(!iterator.Next(item));
  248. UNIT_ASSERT(!iterator.Next(item));
  249. }
  250. Y_UNIT_TEST_LLVM(TestPasstroughtFieldSplitAndFirstUnused) {
  251. TSetup<LLVM> setup;
  252. TProgramBuilder& pb = *setup.PgmBuilder;
  253. const auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  254. const auto tupleType = pb.NewTupleType({dataType, dataType, dataType});
  255. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewOptional(pb.NewDataLiteral<i32>(-5)), pb.NewOptional(pb.NewDataLiteral<i32>(-3))});
  256. const auto data2 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-4)), pb.NewOptional(pb.NewDataLiteral<i32>(-6))});
  257. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewOptional(pb.NewDataLiteral<i32>(-7)), pb.NewOptional(pb.NewDataLiteral<i32>(-9))});
  258. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(dataType), pb.NewOptional(pb.NewDataLiteral<i32>(-1))});
  259. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  260. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.WideMap(pb.ExpandMap(pb.ToFlow(list),
  261. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U)}; }),
  262. [&](TRuntimeNode::TList items) -> TRuntimeNode::TList { return {items[1U], pb.AggrAdd(items.front(), items.back()), items[1U]}; }),
  263. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple({items[1], items[2]}); }
  264. ));
  265. const auto graph = setup.BuildGraph(pgmReturn);
  266. const auto iterator = graph->GetValue().GetListIterator();
  267. NUdf::TUnboxedValue item;
  268. UNIT_ASSERT(iterator.Next(item));
  269. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -2);
  270. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -5);
  271. UNIT_ASSERT(iterator.Next(item));
  272. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -4);
  273. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -4);
  274. UNIT_ASSERT(iterator.Next(item));
  275. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), -6);
  276. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), -7);
  277. UNIT_ASSERT(iterator.Next(item));
  278. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 3);
  279. UNIT_ASSERT(!item.GetElement(1));
  280. UNIT_ASSERT(!iterator.Next(item));
  281. UNIT_ASSERT(!iterator.Next(item));
  282. }
  283. }
  284. #endif
  285. }
  286. }