maybe_ut.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. #include <util/generic/string.h>
  2. #include <util/generic/vector.h>
  3. #include <util/stream/str.h>
  4. #include <library/cpp/testing/unittest/registar.h>
  5. #include "maybe.h"
  6. class TIncrementOnDestroy {
  7. private:
  8. int* Ptr_;
  9. public:
  10. TIncrementOnDestroy(int* ptr) noexcept
  11. : Ptr_(ptr)
  12. {
  13. }
  14. ~TIncrementOnDestroy() {
  15. ++*Ptr_;
  16. }
  17. };
  18. Y_UNIT_TEST_SUITE(TMaybeTest) {
  19. Y_UNIT_TEST(TestStatic) {
  20. using T1 = TMaybe<int>;
  21. static_assert(std::is_trivially_copy_constructible<T1>::value, "");
  22. static_assert(std::is_trivially_destructible<T1>::value, "");
  23. using T2 = TMaybe<TString*>;
  24. static_assert(std::is_trivially_copy_constructible<T2>::value, "");
  25. static_assert(std::is_trivially_destructible<T2>::value, "");
  26. using T3 = TMaybe<TMaybe<double>>;
  27. static_assert(std::is_trivially_copy_constructible<T3>::value, "");
  28. static_assert(std::is_trivially_destructible<T3>::value, "");
  29. using T4 = TMaybe<TString>;
  30. static_assert(!std::is_trivially_copy_constructible<T4>::value, "");
  31. static_assert(!std::is_trivially_destructible<T4>::value, "");
  32. }
  33. Y_UNIT_TEST(TestWarning) {
  34. TMaybe<size_t> x;
  35. TStringStream ss;
  36. TString line;
  37. while (ss.ReadLine(line)) {
  38. x = line.size();
  39. }
  40. if (x == 5u) {
  41. ss << "5\n";
  42. }
  43. }
  44. Y_UNIT_TEST(TTestConstructorDestructor) {
  45. int a = 0;
  46. int b = 0;
  47. TMaybe<TIncrementOnDestroy>();
  48. UNIT_ASSERT_VALUES_EQUAL(a, b);
  49. TMaybe<TIncrementOnDestroy>(TIncrementOnDestroy(&a));
  50. b += 2;
  51. UNIT_ASSERT_VALUES_EQUAL(a, b);
  52. {
  53. TMaybe<TIncrementOnDestroy> m1 = TIncrementOnDestroy(&a);
  54. b += 1;
  55. UNIT_ASSERT_VALUES_EQUAL(a, b);
  56. TMaybe<TIncrementOnDestroy> m2 = m1;
  57. UNIT_ASSERT_VALUES_EQUAL(a, b);
  58. TMaybe<TIncrementOnDestroy> m3;
  59. m3 = m1;
  60. UNIT_ASSERT_VALUES_EQUAL(a, b);
  61. }
  62. b += 3;
  63. UNIT_ASSERT_VALUES_EQUAL(a, b);
  64. {
  65. TMaybe<TIncrementOnDestroy> m4 = TIncrementOnDestroy(&a);
  66. b += 1;
  67. UNIT_ASSERT_VALUES_EQUAL(a, b);
  68. m4 = TIncrementOnDestroy(&a);
  69. b += 1;
  70. UNIT_ASSERT_VALUES_EQUAL(a, b);
  71. m4.Clear();
  72. b += 1;
  73. UNIT_ASSERT_VALUES_EQUAL(a, b);
  74. m4.Clear();
  75. UNIT_ASSERT_VALUES_EQUAL(a, b);
  76. }
  77. }
  78. Y_UNIT_TEST(TestAssignmentClear) {
  79. TMaybe<int> m5;
  80. UNIT_ASSERT(!m5.Defined());
  81. UNIT_ASSERT(m5.Empty());
  82. UNIT_ASSERT(m5 == TMaybe<int>());
  83. UNIT_ASSERT(m5 == Nothing());
  84. UNIT_ASSERT(m5 != TMaybe<int>(4));
  85. m5 = 4;
  86. UNIT_ASSERT(m5.Defined());
  87. UNIT_ASSERT(!m5.Empty());
  88. UNIT_ASSERT_VALUES_EQUAL(4, m5.GetRef());
  89. UNIT_ASSERT(m5 == TMaybe<int>(4));
  90. UNIT_ASSERT(m5 != TMaybe<int>(3));
  91. UNIT_ASSERT(m5 != TMaybe<int>());
  92. UNIT_ASSERT(m5 != Nothing());
  93. m5 = TMaybe<int>(5);
  94. UNIT_ASSERT(m5.Defined());
  95. UNIT_ASSERT_VALUES_EQUAL(5, m5.GetRef());
  96. UNIT_ASSERT(m5 == TMaybe<int>(5));
  97. UNIT_ASSERT(m5 != TMaybe<int>(4));
  98. m5 = TMaybe<int>();
  99. UNIT_ASSERT(m5.Empty());
  100. UNIT_ASSERT(m5 == TMaybe<int>());
  101. UNIT_ASSERT(m5 == Nothing());
  102. UNIT_ASSERT(m5 != TMaybe<int>(5));
  103. m5 = 4;
  104. m5 = Nothing();
  105. UNIT_ASSERT(m5.Empty());
  106. UNIT_ASSERT(m5 == TMaybe<int>());
  107. UNIT_ASSERT(m5 == Nothing());
  108. UNIT_ASSERT(m5 != TMaybe<int>(5));
  109. m5 = {};
  110. UNIT_ASSERT(m5.Empty());
  111. }
  112. Y_UNIT_TEST(TestInPlace) {
  113. TMaybe<int> m;
  114. UNIT_ASSERT(!m);
  115. m.ConstructInPlace(1);
  116. UNIT_ASSERT(m == 1);
  117. auto& x = m.ConstructInPlace(2);
  118. UNIT_ASSERT(m == 2);
  119. x = 7;
  120. UNIT_ASSERT(m == 7);
  121. }
  122. Y_UNIT_TEST(TestMove) {
  123. struct TMovable {
  124. int Flag = 0;
  125. TMovable(int flag)
  126. : Flag(flag)
  127. {
  128. }
  129. TMovable(const TMovable&) = delete;
  130. TMovable& operator=(const TMovable&) = delete;
  131. TMovable(TMovable&& other) {
  132. std::swap(Flag, other.Flag);
  133. }
  134. TMovable& operator=(TMovable&& other) {
  135. std::swap(Flag, other.Flag);
  136. return *this;
  137. }
  138. };
  139. // Move ctor from value
  140. TMovable value1(1);
  141. TMaybe<TMovable> m1(std::move(value1));
  142. UNIT_ASSERT(m1.Defined());
  143. UNIT_ASSERT_VALUES_EQUAL(m1->Flag, 1);
  144. // Move assignment from value
  145. TMovable value2(2);
  146. TMaybe<TMovable> m2;
  147. m2 = std::move(value2);
  148. UNIT_ASSERT(m2.Defined());
  149. UNIT_ASSERT_VALUES_EQUAL(m2->Flag, 2);
  150. // Move ctor from maybe
  151. TMaybe<TMovable> m3(std::move(m1));
  152. UNIT_ASSERT(m3.Defined());
  153. UNIT_ASSERT_VALUES_EQUAL(m3->Flag, 1);
  154. // Move assignment from maybe
  155. TMaybe<TMovable> m4;
  156. m4 = std::move(m2);
  157. UNIT_ASSERT(m4.Defined());
  158. UNIT_ASSERT_VALUES_EQUAL(m4->Flag, 2);
  159. // Move value from temporary maybe instance
  160. TMovable o5 = *MakeMaybe<TMovable>(5);
  161. UNIT_ASSERT_VALUES_EQUAL(o5.Flag, 5);
  162. TMovable o6 = MakeMaybe<TMovable>(6).GetRef();
  163. UNIT_ASSERT_VALUES_EQUAL(o6.Flag, 6);
  164. }
  165. Y_UNIT_TEST(TestCast) {
  166. // Undefined maybe casts to undefined maybe
  167. TMaybe<short> shortMaybe;
  168. const auto undefinedMaybe = shortMaybe.Cast<long>();
  169. UNIT_ASSERT(!undefinedMaybe.Defined());
  170. // Defined maybe casts to defined maybe of another type
  171. shortMaybe = 34;
  172. const auto longMaybe = shortMaybe.Cast<long>();
  173. UNIT_ASSERT(longMaybe.Defined());
  174. UNIT_ASSERT_VALUES_EQUAL(34, longMaybe.GetRef());
  175. }
  176. Y_UNIT_TEST(TestGetOr) {
  177. UNIT_ASSERT_VALUES_EQUAL(TMaybe<TString>().GetOrElse("xxx"), TString("xxx"));
  178. UNIT_ASSERT_VALUES_EQUAL(TMaybe<TString>("yyy").GetOrElse("xxx"), TString("yyy"));
  179. {
  180. TString xxx = "xxx";
  181. UNIT_ASSERT_VALUES_EQUAL(TMaybe<TString>().GetOrElse(xxx).append('x'), TString("xxxx"));
  182. UNIT_ASSERT_VALUES_EQUAL(xxx, "xxxx");
  183. }
  184. {
  185. TString xxx = "xxx";
  186. UNIT_ASSERT_VALUES_EQUAL(TMaybe<TString>("yyy").GetOrElse(xxx).append('x'), TString("yyyx"));
  187. UNIT_ASSERT_VALUES_EQUAL(xxx, "xxx");
  188. }
  189. }
  190. /*
  191. ==
  192. !=
  193. <
  194. <=
  195. >
  196. >=
  197. */
  198. Y_UNIT_TEST(TestCompareEqualEmpty) {
  199. TMaybe<int> m1;
  200. TMaybe<int> m2;
  201. UNIT_ASSERT(m1 == m2);
  202. UNIT_ASSERT(!(m1 != m2));
  203. UNIT_ASSERT(!(m1 < m2));
  204. UNIT_ASSERT(m1 <= m2);
  205. UNIT_ASSERT(!(m1 > m2));
  206. UNIT_ASSERT(m1 >= m2);
  207. }
  208. Y_UNIT_TEST(TestCompareEqualNonEmpty) {
  209. TMaybe<int> m1{1};
  210. TMaybe<int> m2{1};
  211. UNIT_ASSERT(m1 == m2);
  212. UNIT_ASSERT(!(m1 != m2));
  213. UNIT_ASSERT(!(m1 < m2));
  214. UNIT_ASSERT(m1 <= m2);
  215. UNIT_ASSERT(!(m1 > m2));
  216. UNIT_ASSERT(m1 >= m2);
  217. }
  218. Y_UNIT_TEST(TestCompareOneLessThanOther) {
  219. TMaybe<int> m1{1};
  220. TMaybe<int> m2{2};
  221. UNIT_ASSERT(!(m1 == m2));
  222. UNIT_ASSERT(m1 != m2);
  223. UNIT_ASSERT(m1 < m2);
  224. UNIT_ASSERT(m1 <= m2);
  225. UNIT_ASSERT(!(m1 > m2));
  226. UNIT_ASSERT(!(m1 >= m2));
  227. }
  228. Y_UNIT_TEST(TestCompareTMaybeAndT_Equal) {
  229. TMaybe<int> m{1};
  230. int v{1};
  231. UNIT_ASSERT(m == v);
  232. UNIT_ASSERT(!(m != v));
  233. UNIT_ASSERT(!(m < v));
  234. UNIT_ASSERT(m <= v);
  235. UNIT_ASSERT(!(m > v));
  236. UNIT_ASSERT(m >= v);
  237. UNIT_ASSERT(v == m);
  238. UNIT_ASSERT(!(v != m));
  239. UNIT_ASSERT(!(v < m));
  240. UNIT_ASSERT(v <= m);
  241. UNIT_ASSERT(!(v > m));
  242. UNIT_ASSERT(v >= m);
  243. }
  244. Y_UNIT_TEST(TestCompareTMaybeAndT_TMaybeLessThanT) {
  245. TMaybe<int> m{1};
  246. int v{2};
  247. UNIT_ASSERT(!(m == v));
  248. UNIT_ASSERT(m != v);
  249. UNIT_ASSERT(m < v);
  250. UNIT_ASSERT(m <= v);
  251. UNIT_ASSERT(!(m > v));
  252. UNIT_ASSERT(!(m >= v));
  253. UNIT_ASSERT(!(v == m));
  254. UNIT_ASSERT(v != m);
  255. UNIT_ASSERT(!(v < m));
  256. UNIT_ASSERT(!(v <= m));
  257. UNIT_ASSERT(v > m);
  258. UNIT_ASSERT(v >= m);
  259. }
  260. Y_UNIT_TEST(TestCompareTMaybeAndT_TMaybeGreaterThanT) {
  261. TMaybe<int> m{2};
  262. int v{1};
  263. UNIT_ASSERT(!(m == v));
  264. UNIT_ASSERT(m != v);
  265. UNIT_ASSERT(!(m < v));
  266. UNIT_ASSERT(!(m <= v));
  267. UNIT_ASSERT(m > v);
  268. UNIT_ASSERT(m >= v);
  269. UNIT_ASSERT(!(v == m));
  270. UNIT_ASSERT(v != m);
  271. UNIT_ASSERT(v < m);
  272. UNIT_ASSERT(v <= m);
  273. UNIT_ASSERT(!(v > m));
  274. UNIT_ASSERT(!(v >= m));
  275. }
  276. Y_UNIT_TEST(TestCompareEmptyTMaybeAndT) {
  277. TMaybe<int> m;
  278. int v{1};
  279. UNIT_ASSERT(!(m == v));
  280. UNIT_ASSERT(m != v);
  281. UNIT_ASSERT(m < v);
  282. UNIT_ASSERT(m <= v);
  283. UNIT_ASSERT(!(m > v));
  284. UNIT_ASSERT(!(m >= v));
  285. UNIT_ASSERT(!(v == m));
  286. UNIT_ASSERT(v != m);
  287. UNIT_ASSERT(!(v < m));
  288. UNIT_ASSERT(!(v <= m));
  289. UNIT_ASSERT(v > m);
  290. UNIT_ASSERT(v >= m);
  291. }
  292. Y_UNIT_TEST(TestCompareEmptyTMaybeAndNothing) {
  293. TMaybe<int> m;
  294. auto n = Nothing();
  295. UNIT_ASSERT(m == n);
  296. UNIT_ASSERT(!(m != n));
  297. UNIT_ASSERT(!(m < n));
  298. UNIT_ASSERT(m <= n);
  299. UNIT_ASSERT(!(m > n));
  300. UNIT_ASSERT(m >= n);
  301. UNIT_ASSERT(n == m);
  302. UNIT_ASSERT(!(n != m));
  303. UNIT_ASSERT(!(n < m));
  304. UNIT_ASSERT(n <= m);
  305. UNIT_ASSERT(!(n > m));
  306. UNIT_ASSERT(n >= m);
  307. }
  308. Y_UNIT_TEST(TestCompareNonEmptyTMaybeAndNothing) {
  309. TMaybe<int> m{1};
  310. auto n = Nothing();
  311. UNIT_ASSERT(!(m == n));
  312. UNIT_ASSERT(m != n);
  313. UNIT_ASSERT(!(m < n));
  314. UNIT_ASSERT(!(m <= n));
  315. UNIT_ASSERT(m > n);
  316. UNIT_ASSERT(m >= n);
  317. UNIT_ASSERT(!(n == m));
  318. UNIT_ASSERT(n != m);
  319. UNIT_ASSERT(n < m);
  320. UNIT_ASSERT(n <= m);
  321. UNIT_ASSERT(!(n > m));
  322. UNIT_ASSERT(!(n >= m));
  323. }
  324. Y_UNIT_TEST(TestCompareTMaybeAndConvertibleT_Equal) {
  325. TMaybe<size_t> m{1};
  326. unsigned int v{1};
  327. UNIT_ASSERT(m == v);
  328. UNIT_ASSERT(!(m != v));
  329. UNIT_ASSERT(!(m < v));
  330. UNIT_ASSERT(m <= v);
  331. UNIT_ASSERT(!(m > v));
  332. UNIT_ASSERT(m >= v);
  333. UNIT_ASSERT(v == m);
  334. UNIT_ASSERT(!(v != m));
  335. UNIT_ASSERT(!(v < m));
  336. UNIT_ASSERT(v <= m);
  337. UNIT_ASSERT(!(v > m));
  338. UNIT_ASSERT(v >= m);
  339. }
  340. Y_UNIT_TEST(TestCompareTMaybeAndConvertibleT_TMaybeLessThanT) {
  341. TMaybe<size_t> m{1};
  342. unsigned int v{2};
  343. UNIT_ASSERT(!(m == v));
  344. UNIT_ASSERT(m != v);
  345. UNIT_ASSERT(m < v);
  346. UNIT_ASSERT(m <= v);
  347. UNIT_ASSERT(!(m > v));
  348. UNIT_ASSERT(!(m >= v));
  349. UNIT_ASSERT(!(v == m));
  350. UNIT_ASSERT(v != m);
  351. UNIT_ASSERT(!(v < m));
  352. UNIT_ASSERT(!(v <= m));
  353. UNIT_ASSERT(v > m);
  354. UNIT_ASSERT(v >= m);
  355. }
  356. Y_UNIT_TEST(TestCompareTMaybeAndConvertibleT_TMaybeGreaterThanT) {
  357. TMaybe<size_t> m{2};
  358. unsigned int v{1};
  359. UNIT_ASSERT(!(m == v));
  360. UNIT_ASSERT(m != v);
  361. UNIT_ASSERT(!(m < v));
  362. UNIT_ASSERT(!(m <= v));
  363. UNIT_ASSERT(m > v);
  364. UNIT_ASSERT(m >= v);
  365. UNIT_ASSERT(!(v == m));
  366. UNIT_ASSERT(v != m);
  367. UNIT_ASSERT(v < m);
  368. UNIT_ASSERT(v <= m);
  369. UNIT_ASSERT(!(v > m));
  370. UNIT_ASSERT(!(v >= m));
  371. }
  372. Y_UNIT_TEST(TestCompareEmptyTMaybeAndConvertibleT) {
  373. TMaybe<size_t> m;
  374. unsigned int v{1};
  375. UNIT_ASSERT(!(m == v));
  376. UNIT_ASSERT(m != v);
  377. UNIT_ASSERT(m < v);
  378. UNIT_ASSERT(m <= v);
  379. UNIT_ASSERT(!(m > v));
  380. UNIT_ASSERT(!(m >= v));
  381. UNIT_ASSERT(!(v == m));
  382. UNIT_ASSERT(v != m);
  383. UNIT_ASSERT(!(v < m));
  384. UNIT_ASSERT(!(v <= m));
  385. UNIT_ASSERT(v > m);
  386. UNIT_ASSERT(v >= m);
  387. }
  388. Y_UNIT_TEST(TestMakeMaybe) {
  389. {
  390. auto m1 = MakeMaybe<int>(1);
  391. UNIT_ASSERT(*m1 == 1);
  392. }
  393. {
  394. struct TMockClass {
  395. TMockClass(int i)
  396. : I_(i)
  397. {
  398. }
  399. TMockClass(const TMockClass& other)
  400. : I_(other.I_)
  401. {
  402. IsCopyConstructorCalled_ = true;
  403. }
  404. TMockClass& operator=(const TMockClass& other) {
  405. if (this != &other) {
  406. I_ = other.I_;
  407. IsCopyAssignmentOperatorCalled_ = true;
  408. }
  409. return *this;
  410. }
  411. TMockClass(TMockClass&& other)
  412. : I_(other.I_)
  413. {
  414. IsMoveConstructorCalled_ = true;
  415. }
  416. TMockClass& operator=(TMockClass&& other) {
  417. if (this != &other) {
  418. I_ = other.I_;
  419. IsMoveAssignmentOperatorCalled_ = true;
  420. }
  421. return *this;
  422. }
  423. int I_;
  424. bool IsCopyConstructorCalled_{false};
  425. bool IsMoveConstructorCalled_{false};
  426. bool IsCopyAssignmentOperatorCalled_{false};
  427. bool IsMoveAssignmentOperatorCalled_{false};
  428. };
  429. auto m2 = MakeMaybe<TMockClass>(1);
  430. UNIT_ASSERT(m2->I_ == 1);
  431. UNIT_ASSERT(!m2->IsCopyConstructorCalled_);
  432. UNIT_ASSERT(!m2->IsMoveConstructorCalled_);
  433. UNIT_ASSERT(!m2->IsCopyAssignmentOperatorCalled_);
  434. UNIT_ASSERT(!m2->IsMoveAssignmentOperatorCalled_);
  435. }
  436. {
  437. auto m3 = MakeMaybe<TVector<int>>({1, 2, 3, 4, 5});
  438. UNIT_ASSERT(m3->size() == 5);
  439. UNIT_ASSERT(m3->at(0) == 1);
  440. UNIT_ASSERT(m3->at(1) == 2);
  441. UNIT_ASSERT(m3->at(2) == 3);
  442. UNIT_ASSERT(m3->at(3) == 4);
  443. UNIT_ASSERT(m3->at(4) == 5);
  444. }
  445. {
  446. struct TMockStruct4 {
  447. TMockStruct4(int a, int b, int c)
  448. : A_(a)
  449. , B_(b)
  450. , C_(c)
  451. {
  452. }
  453. int A_;
  454. int B_;
  455. int C_;
  456. };
  457. auto m4 = MakeMaybe<TMockStruct4>(1, 2, 3);
  458. UNIT_ASSERT(m4->A_ == 1);
  459. UNIT_ASSERT(m4->B_ == 2);
  460. UNIT_ASSERT(m4->C_ == 3);
  461. }
  462. {
  463. struct TMockStruct5 {
  464. TMockStruct5(const TVector<int>& vec, bool someFlag)
  465. : Vec_(vec)
  466. , SomeFlag_(someFlag)
  467. {
  468. }
  469. TVector<int> Vec_;
  470. bool SomeFlag_;
  471. };
  472. auto m5 = MakeMaybe<TMockStruct5>({1, 2, 3}, true);
  473. UNIT_ASSERT(m5->Vec_.size() == 3);
  474. UNIT_ASSERT(m5->Vec_[0] == 1);
  475. UNIT_ASSERT(m5->Vec_[1] == 2);
  476. UNIT_ASSERT(m5->Vec_[2] == 3);
  477. UNIT_ASSERT(m5->SomeFlag_);
  478. }
  479. }
  480. Y_UNIT_TEST(TestSwappingUsingMemberSwap) {
  481. {
  482. TMaybe<int> m1 = 1;
  483. TMaybe<int> m2 = 2;
  484. UNIT_ASSERT(*m1 == 1);
  485. UNIT_ASSERT(*m2 == 2);
  486. m1.Swap(m2);
  487. UNIT_ASSERT(*m1 == 2);
  488. UNIT_ASSERT(*m2 == 1);
  489. }
  490. {
  491. TMaybe<int> m1 = 1;
  492. TMaybe<int> m2 = Nothing();
  493. UNIT_ASSERT(*m1 == 1);
  494. UNIT_ASSERT(m2 == Nothing());
  495. m1.Swap(m2);
  496. UNIT_ASSERT(m1 == Nothing());
  497. UNIT_ASSERT(*m2 == 1);
  498. }
  499. {
  500. TMaybe<int> m1 = Nothing();
  501. TMaybe<int> m2 = 1;
  502. UNIT_ASSERT(m1 == Nothing());
  503. UNIT_ASSERT(*m2 == 1);
  504. m1.Swap(m2);
  505. UNIT_ASSERT(*m1 == 1);
  506. UNIT_ASSERT(m2 == Nothing());
  507. }
  508. }
  509. Y_UNIT_TEST(TestSwappingUsingMemberLittleSwap) {
  510. {
  511. TMaybe<int> m1 = 1;
  512. TMaybe<int> m2 = 2;
  513. UNIT_ASSERT(*m1 == 1);
  514. UNIT_ASSERT(*m2 == 2);
  515. m1.swap(m2);
  516. UNIT_ASSERT(*m1 == 2);
  517. UNIT_ASSERT(*m2 == 1);
  518. }
  519. {
  520. TMaybe<int> m1 = 1;
  521. TMaybe<int> m2 = Nothing();
  522. UNIT_ASSERT(*m1 == 1);
  523. UNIT_ASSERT(m2 == Nothing());
  524. m1.swap(m2);
  525. UNIT_ASSERT(m1 == Nothing());
  526. UNIT_ASSERT(*m2 == 1);
  527. }
  528. {
  529. TMaybe<int> m1 = Nothing();
  530. TMaybe<int> m2 = 1;
  531. UNIT_ASSERT(m1 == Nothing());
  532. UNIT_ASSERT(*m2 == 1);
  533. m1.swap(m2);
  534. UNIT_ASSERT(*m1 == 1);
  535. UNIT_ASSERT(m2 == Nothing());
  536. }
  537. }
  538. Y_UNIT_TEST(TestSwappingUsingGlobalSwap) {
  539. {
  540. TMaybe<int> m1 = 1;
  541. TMaybe<int> m2 = 2;
  542. UNIT_ASSERT(*m1 == 1);
  543. UNIT_ASSERT(*m2 == 2);
  544. ::Swap(m1, m2);
  545. UNIT_ASSERT(*m1 == 2);
  546. UNIT_ASSERT(*m2 == 1);
  547. }
  548. {
  549. TMaybe<int> m1 = 1;
  550. TMaybe<int> m2 = Nothing();
  551. UNIT_ASSERT(*m1 == 1);
  552. UNIT_ASSERT(m2 == Nothing());
  553. ::Swap(m1, m2);
  554. UNIT_ASSERT(m1 == Nothing());
  555. UNIT_ASSERT(*m2 == 1);
  556. }
  557. {
  558. TMaybe<int> m1 = Nothing();
  559. TMaybe<int> m2 = 1;
  560. UNIT_ASSERT(m1 == Nothing());
  561. UNIT_ASSERT(*m2 == 1);
  562. ::Swap(m1, m2);
  563. UNIT_ASSERT(*m1 == 1);
  564. UNIT_ASSERT(m2 == Nothing());
  565. }
  566. }
  567. Y_UNIT_TEST(TestSwappingUsingGlobalDoSwap) {
  568. {
  569. TMaybe<int> m1 = 1;
  570. TMaybe<int> m2 = 2;
  571. UNIT_ASSERT(*m1 == 1);
  572. UNIT_ASSERT(*m2 == 2);
  573. ::DoSwap(m1, m2);
  574. UNIT_ASSERT(*m1 == 2);
  575. UNIT_ASSERT(*m2 == 1);
  576. }
  577. {
  578. TMaybe<int> m1 = 1;
  579. TMaybe<int> m2 = Nothing();
  580. UNIT_ASSERT(*m1 == 1);
  581. UNIT_ASSERT(m2 == Nothing());
  582. ::DoSwap(m1, m2);
  583. UNIT_ASSERT(m1 == Nothing());
  584. UNIT_ASSERT(*m2 == 1);
  585. }
  586. {
  587. TMaybe<int> m1 = Nothing();
  588. TMaybe<int> m2 = 1;
  589. UNIT_ASSERT(m1 == Nothing());
  590. UNIT_ASSERT(*m2 == 1);
  591. ::DoSwap(m1, m2);
  592. UNIT_ASSERT(*m1 == 1);
  593. UNIT_ASSERT(m2 == Nothing());
  594. }
  595. }
  596. Y_UNIT_TEST(TestSwappingUsingStdSwap) {
  597. {
  598. TMaybe<int> m1 = 1;
  599. TMaybe<int> m2 = 2;
  600. UNIT_ASSERT(*m1 == 1);
  601. UNIT_ASSERT(*m2 == 2);
  602. ::std::swap(m1, m2);
  603. UNIT_ASSERT(*m1 == 2);
  604. UNIT_ASSERT(*m2 == 1);
  605. }
  606. {
  607. TMaybe<int> m1 = 1;
  608. TMaybe<int> m2 = Nothing();
  609. UNIT_ASSERT(*m1 == 1);
  610. UNIT_ASSERT(m2 == Nothing());
  611. ::std::swap(m1, m2);
  612. UNIT_ASSERT(m1 == Nothing());
  613. UNIT_ASSERT(*m2 == 1);
  614. }
  615. {
  616. TMaybe<int> m1 = Nothing();
  617. TMaybe<int> m2 = 1;
  618. UNIT_ASSERT(m1 == Nothing());
  619. UNIT_ASSERT(*m2 == 1);
  620. ::std::swap(m1, m2);
  621. UNIT_ASSERT(*m1 == 1);
  622. UNIT_ASSERT(m2 == Nothing());
  623. }
  624. }
  625. Y_UNIT_TEST(TestOutputStreamEmptyMaybe) {
  626. TString s;
  627. TStringOutput output(s);
  628. output << TMaybe<int>();
  629. UNIT_ASSERT_EQUAL("(empty maybe)", s);
  630. }
  631. Y_UNIT_TEST(TestOutputStreamNothing) {
  632. TString s;
  633. TStringOutput output(s);
  634. output << Nothing();
  635. UNIT_ASSERT_VALUES_EQUAL("(empty maybe)", s);
  636. }
  637. Y_UNIT_TEST(TestOutputStreamDefinedMaybe) {
  638. TString s;
  639. TStringOutput output(s);
  640. output << TMaybe<int>(42);
  641. UNIT_ASSERT_EQUAL("42", s);
  642. }
  643. Y_UNIT_TEST(TestMaybeCovarianceImplicit) {
  644. struct TestStruct {
  645. TestStruct(int value)
  646. : Value_(value)
  647. {
  648. }
  649. operator int() const {
  650. return Value_;
  651. }
  652. static TMaybe<int> Unwrap(TMaybe<TestStruct> testStructMaybe) {
  653. return testStructMaybe;
  654. }
  655. int Value_;
  656. };
  657. TMaybe<int> testMaybeFull = TestStruct::Unwrap(TMaybe<int>(42));
  658. UNIT_ASSERT(testMaybeFull.Defined());
  659. UNIT_ASSERT_EQUAL(testMaybeFull.GetRef(), 42);
  660. TMaybe<int> testMaybeEmpty = TestStruct::Unwrap(TMaybe<int>());
  661. UNIT_ASSERT(!testMaybeEmpty.Defined());
  662. }
  663. Y_UNIT_TEST(TestMaybeCovarianceExplicit) {
  664. struct TestStruct {
  665. explicit TestStruct(int value)
  666. : Value_(value)
  667. {
  668. }
  669. int Value_;
  670. };
  671. TMaybe<TestStruct> testStructMaybeFull(TMaybe<int>(42));
  672. UNIT_ASSERT(testStructMaybeFull.Defined());
  673. UNIT_ASSERT_EQUAL(testStructMaybeFull.GetRef().Value_, 42);
  674. TMaybe<int> empty;
  675. TMaybe<TestStruct> testStructMaybeEmpty(empty);
  676. UNIT_ASSERT(!testStructMaybeEmpty.Defined());
  677. }
  678. Y_UNIT_TEST(TestMaybeCovarianceAssign) {
  679. struct TestStruct {
  680. explicit TestStruct(int value)
  681. : Value_(value)
  682. {
  683. }
  684. TestStruct& operator=(int value) {
  685. Value_ = value;
  686. return *this;
  687. }
  688. int Value_;
  689. };
  690. TMaybe<TestStruct> testStructMaybe(Nothing());
  691. UNIT_ASSERT(!testStructMaybe.Defined());
  692. testStructMaybe = TMaybe<int>(42);
  693. UNIT_ASSERT(testStructMaybe.Defined());
  694. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().Value_, 42);
  695. testStructMaybe = TMaybe<int>(23);
  696. UNIT_ASSERT(testStructMaybe.Defined());
  697. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().Value_, 23);
  698. testStructMaybe = TMaybe<int>();
  699. UNIT_ASSERT(!testStructMaybe.Defined());
  700. }
  701. Y_UNIT_TEST(TestMaybeCovarianceNonTrivial) {
  702. struct TestStruct {
  703. enum {
  704. FromValue,
  705. FromMaybe,
  706. };
  707. TestStruct(int value)
  708. : Value_(value)
  709. , From_(FromValue)
  710. {
  711. }
  712. TestStruct(TMaybe<int> value)
  713. : Value_(value.Defined() ? value.GetRef() : 0)
  714. , From_(FromMaybe)
  715. {
  716. }
  717. int Value_;
  718. int From_;
  719. };
  720. TMaybe<TestStruct> testStructFromMaybe(TMaybe<int>(42));
  721. UNIT_ASSERT(testStructFromMaybe.Defined());
  722. UNIT_ASSERT_EQUAL(testStructFromMaybe.GetRef().From_, TestStruct::FromMaybe);
  723. UNIT_ASSERT_EQUAL(testStructFromMaybe.GetRef().Value_, 42);
  724. TMaybe<int> empty;
  725. TMaybe<TestStruct> testStructFromEmptyMaybe(empty);
  726. UNIT_ASSERT(testStructFromEmptyMaybe.Defined());
  727. UNIT_ASSERT_EQUAL(testStructFromEmptyMaybe.GetRef().From_, TestStruct::FromMaybe);
  728. UNIT_ASSERT_EQUAL(testStructFromEmptyMaybe.GetRef().Value_, 0);
  729. TMaybe<TestStruct> testStructFromValue(23);
  730. UNIT_ASSERT(testStructFromValue.Defined());
  731. UNIT_ASSERT_EQUAL(testStructFromValue.GetRef().From_, TestStruct::FromValue);
  732. UNIT_ASSERT_EQUAL(testStructFromValue.GetRef().Value_, 23);
  733. }
  734. Y_UNIT_TEST(TestMaybeCovarianceNonTrivialAssign) {
  735. struct TestStruct {
  736. enum {
  737. FromValue,
  738. FromMaybe,
  739. };
  740. TestStruct(int value)
  741. : Value_(value)
  742. , From_(FromValue)
  743. {
  744. }
  745. TestStruct(TMaybe<int> value)
  746. : Value_(value.Defined() ? value.GetRef() : 0)
  747. , From_(FromMaybe)
  748. {
  749. }
  750. TestStruct& operator=(int value) {
  751. Value_ = value;
  752. From_ = FromValue;
  753. return *this;
  754. }
  755. TestStruct& operator=(TMaybe<int> value) {
  756. Value_ = value.Defined() ? value.GetRef() : 0;
  757. From_ = FromMaybe;
  758. return *this;
  759. }
  760. int Value_;
  761. int From_;
  762. };
  763. TMaybe<TestStruct> testStructMaybe(Nothing());
  764. testStructMaybe = TMaybe<int>(42);
  765. UNIT_ASSERT(testStructMaybe.Defined());
  766. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().From_, TestStruct::FromMaybe);
  767. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().Value_, 42);
  768. testStructMaybe = TMaybe<int>();
  769. UNIT_ASSERT(testStructMaybe.Defined());
  770. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().From_, TestStruct::FromMaybe);
  771. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().Value_, 0);
  772. testStructMaybe = 23;
  773. UNIT_ASSERT(testStructMaybe.Defined());
  774. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().From_, TestStruct::FromValue);
  775. UNIT_ASSERT_EQUAL(testStructMaybe.GetRef().Value_, 23);
  776. }
  777. Y_UNIT_TEST(TestMaybeConvertion) {
  778. struct TSrc {};
  779. struct TDst {
  780. bool FromMaybeConstructorApplied;
  781. explicit TDst(TSrc)
  782. : FromMaybeConstructorApplied(false)
  783. {
  784. }
  785. explicit TDst(TMaybe<TSrc>)
  786. : FromMaybeConstructorApplied(true)
  787. {
  788. }
  789. TDst& operator=(TSrc) {
  790. FromMaybeConstructorApplied = false;
  791. return *this;
  792. }
  793. TDst& operator=(TMaybe<TSrc>) {
  794. FromMaybeConstructorApplied = true;
  795. return *this;
  796. }
  797. };
  798. auto m = TMaybe<TDst>(TMaybe<TSrc>());
  799. UNIT_ASSERT(m.Defined());
  800. UNIT_ASSERT(m->FromMaybeConstructorApplied);
  801. m = TMaybe<TSrc>();
  802. UNIT_ASSERT(m.Defined());
  803. UNIT_ASSERT(m->FromMaybeConstructorApplied);
  804. }
  805. Y_UNIT_TEST(TestOnEmptyException) {
  806. TMaybe<TStringBuf> v;
  807. UNIT_ASSERT_EXCEPTION_CONTAINS(v.GetRef(), yexception, "StringBuf");
  808. }
  809. }