py_stream_ut.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include "ut3/py_test_engine.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. using namespace NPython;
  4. Y_UNIT_TEST_SUITE(TPyStreamTest) {
  5. void Ui32StreamValidator(const NUdf::TUnboxedValuePod& value) {
  6. UNIT_ASSERT(value);
  7. UNIT_ASSERT(value.IsBoxed());
  8. NUdf::TUnboxedValue item;
  9. ui32 expected = 0;
  10. NUdf::EFetchStatus status;
  11. while (true) {
  12. status = value.Fetch(item);
  13. if (status != NUdf::EFetchStatus::Ok) break;
  14. ui32 actual = item.Get<ui32>();
  15. UNIT_ASSERT_EQUAL(actual, expected);
  16. expected++;
  17. }
  18. UNIT_ASSERT_EQUAL(status, NUdf::EFetchStatus::Finish);
  19. UNIT_ASSERT_EQUAL(expected, 10);
  20. }
  21. struct TTestStream final: NUdf::TBoxedValue {
  22. TTestStream(ui32 maxValue, ui32 yieldOn = Max<ui32>())
  23. : Current_(0)
  24. , YieldOn_(yieldOn)
  25. , MaxValue_(maxValue)
  26. {
  27. }
  28. private:
  29. NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) override {
  30. if (Current_ == YieldOn_) {
  31. return NUdf::EFetchStatus::Yield;
  32. } else if (Current_ >= MaxValue_) {
  33. return NUdf::EFetchStatus::Finish;
  34. }
  35. result = NUdf::TUnboxedValuePod(Current_++);
  36. return NUdf::EFetchStatus::Ok;
  37. }
  38. ui32 Current_, YieldOn_, MaxValue_;
  39. };
  40. Y_UNIT_TEST(FromGenerator) {
  41. TPythonTestEngine engine;
  42. engine.ToMiniKQL<NUdf::TStream<ui32>>(
  43. "def Test():\n"
  44. " num = 0\n"
  45. " while num < 10:\n"
  46. " yield num\n"
  47. " num += 1\n",
  48. Ui32StreamValidator);
  49. }
  50. Y_UNIT_TEST(FromGeneratorFactory) {
  51. TPythonTestEngine engine;
  52. engine.ToMiniKQL<NUdf::TStream<ui32>>(
  53. "def first_10():\n"
  54. " num = 0\n"
  55. " while num < 10:\n"
  56. " yield num\n"
  57. " num += 1\n"
  58. "def Test():\n"
  59. " return first_10\n",
  60. Ui32StreamValidator);
  61. }
  62. Y_UNIT_TEST(FromIterator) {
  63. TPythonTestEngine engine;
  64. engine.ToMiniKQL<NUdf::TStream<ui32>>(
  65. "def Test():\n"
  66. " return iter(range(10))\n",
  67. Ui32StreamValidator);
  68. }
  69. Y_UNIT_TEST(FromIterable) {
  70. TPythonTestEngine engine;
  71. engine.ToMiniKQL<NUdf::TStream<ui32>>(
  72. "def Test():\n"
  73. #if PY_MAJOR_VERSION >= 3
  74. " return range(10)\n",
  75. #else
  76. " return xrange(10)\n",
  77. #endif
  78. Ui32StreamValidator);
  79. }
  80. Y_UNIT_TEST(FromCustomIterable) {
  81. TPythonTestEngine engine;
  82. engine.ToMiniKQL<NUdf::TStream<ui32>>(
  83. "class T:\n"
  84. " def __init__(self, l):\n"
  85. " self.l = l\n"
  86. " def __len__(self):\n"
  87. " return len(self.l)\n"
  88. " def __nonzero__(self):\n"
  89. " return bool(self.l)\n"
  90. " def __iter__(self):\n"
  91. " return iter(self.l)\n"
  92. "\n"
  93. "def Test():\n"
  94. " return T(list(range(10)))\n",
  95. Ui32StreamValidator);
  96. }
  97. Y_UNIT_TEST(FromList) {
  98. TPythonTestEngine engine;
  99. engine.ToMiniKQL<NUdf::TStream<ui32>>(
  100. "def Test():\n"
  101. " return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
  102. Ui32StreamValidator);
  103. }
  104. Y_UNIT_TEST(ToPython) {
  105. TPythonTestEngine engine;
  106. engine.ToPython<NUdf::TStream<ui32>>(
  107. [](const TType* /*type*/, const NUdf::IValueBuilder& /*vb*/) {
  108. return NUdf::TUnboxedValuePod(new TTestStream(10));
  109. },
  110. "def Test(value):\n"
  111. " import yql\n"
  112. " assert repr(value) == '<yql.TStream>'\n"
  113. " assert type(value).__name__ == 'TStream'\n"
  114. " assert list(value) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n");
  115. }
  116. Y_UNIT_TEST(ToPythonAndBackAsIs) {
  117. TPythonTestEngine engine;
  118. engine.ToPythonAndBack<NUdf::TStream<ui32>>(
  119. [](const TType* /*type*/, const NUdf::IValueBuilder& /*vb*/) {
  120. return NUdf::TUnboxedValuePod(new TTestStream(10));
  121. },
  122. "def Test(value): return value",
  123. Ui32StreamValidator
  124. );
  125. }
  126. Y_UNIT_TEST(YieldingStreamFromPython) {
  127. TPythonTestEngine engine;
  128. engine.ToMiniKQL<NUdf::TStream<ui32>>(
  129. "import yql\n"
  130. "def Test():\n"
  131. " yield 0\n"
  132. " yield 1\n"
  133. " yield yql.TYieldIteration\n"
  134. " yield 2\n",
  135. [](const NUdf::TUnboxedValuePod& value) {
  136. UNIT_ASSERT(value);
  137. UNIT_ASSERT(value.IsBoxed());
  138. NUdf::TUnboxedValue item;
  139. ui32 expected = 0;
  140. NUdf::EFetchStatus status;
  141. while ((status = value.Fetch(item)) == NUdf::EFetchStatus::Ok) {
  142. ui32 actual = item.Get<ui32>();
  143. UNIT_ASSERT_EQUAL(actual, expected);
  144. expected++;
  145. }
  146. UNIT_ASSERT_EQUAL(status, NUdf::EFetchStatus::Yield);
  147. UNIT_ASSERT_EQUAL(expected, 2);
  148. });
  149. }
  150. Y_UNIT_TEST(YieldingStreamFromCpp) {
  151. TPythonTestEngine engine;
  152. engine.ToPython<NUdf::TStream<ui32>>(
  153. [](const TType* /*type*/, const NUdf::IValueBuilder& /*vb*/) {
  154. return NUdf::TUnboxedValuePod(new TTestStream(5, 2));
  155. },
  156. "import yql\n"
  157. "def Test(value):\n"
  158. " assert repr(value) == '<yql.TStream>'\n"
  159. " assert type(value).__name__ == 'TStream'\n"
  160. " assert next(value) == 0\n"
  161. " assert next(value) == 1\n"
  162. " try:\n"
  163. " next(value)\n"
  164. " except yql.TYieldIteration:\n"
  165. " pass\n"
  166. " else:\n"
  167. " assert False, 'Expected yql.TYieldIteration'\n");
  168. }
  169. Y_UNIT_TEST(FromCppListIterator) {
  170. TPythonTestEngine engine;
  171. engine.ToPythonAndBack<NUdf::TListType<ui32>, NUdf::TStream<ui32>>(
  172. [](const TType*, const NUdf::IValueBuilder& vb) {
  173. NUdf::TUnboxedValue *items = nullptr;
  174. const auto a = vb.NewArray(10U, items);
  175. ui32 i = 0U;
  176. std::generate_n(items, 10U, [&i](){ return NUdf::TUnboxedValuePod(i++); });
  177. return a;
  178. },
  179. "def Test(value): return iter(value)",
  180. Ui32StreamValidator
  181. );
  182. }
  183. }