TestLibCorePromise.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibCore/EventLoop.h>
  7. #include <LibCore/Promise.h>
  8. #include <LibCore/ThreadedPromise.h>
  9. #include <LibTest/TestSuite.h>
  10. #include <LibThreading/Thread.h>
  11. #include <unistd.h>
  12. TEST_CASE(promise_await_async_event)
  13. {
  14. Core::EventLoop loop;
  15. auto promise = MUST(Core::Promise<int>::try_create());
  16. loop.deferred_invoke([=] {
  17. promise->resolve(42);
  18. });
  19. auto result = promise->await();
  20. EXPECT(!result.is_error());
  21. EXPECT_EQ(result.value(), 42);
  22. }
  23. TEST_CASE(promise_await_async_event_rejection)
  24. {
  25. Core::EventLoop loop;
  26. auto promise = MUST(Core::Promise<int>::try_create());
  27. loop.deferred_invoke([=] {
  28. promise->reject(AK::Error::from_string_literal("lol no"));
  29. });
  30. auto result = promise->await();
  31. EXPECT(result.is_error());
  32. EXPECT_EQ(result.error().string_literal(), "lol no"sv);
  33. }
  34. TEST_CASE(promise_chain_handlers)
  35. {
  36. Core::EventLoop loop;
  37. bool resolved = false;
  38. bool rejected = false;
  39. NonnullRefPtr<Core::Promise<int>> promise = MUST(Core::Promise<int>::try_create())
  40. ->when_resolved([&](int&) -> ErrorOr<void> { resolved = true; return {}; })
  41. .when_rejected([&](AK::Error const&) { rejected = true; });
  42. loop.deferred_invoke([=] {
  43. promise->resolve(42);
  44. });
  45. (void)promise->await();
  46. EXPECT(resolved);
  47. EXPECT(!rejected);
  48. }
  49. TEST_CASE(infallible_promise_chain_handlers)
  50. {
  51. Core::EventLoop loop;
  52. bool resolved = false;
  53. bool rejected = false;
  54. NonnullRefPtr<Core::Promise<int>> promise = MUST(Core::Promise<int>::try_create())
  55. ->when_resolved([&](int&) { resolved = true; })
  56. .when_rejected([&](AK::Error const&) { rejected = true; });
  57. loop.deferred_invoke([=] {
  58. promise->resolve(42);
  59. });
  60. (void)promise->await();
  61. EXPECT(resolved);
  62. EXPECT(!rejected);
  63. }
  64. TEST_CASE(promise_map)
  65. {
  66. Core::EventLoop loop;
  67. auto promise = MUST(Core::Promise<int>::try_create());
  68. auto mapped_promise = promise->map<int>([](int result) {
  69. return result * 2;
  70. });
  71. loop.deferred_invoke([=] {
  72. promise->resolve(21);
  73. });
  74. auto result = mapped_promise->await();
  75. EXPECT(!result.is_error());
  76. EXPECT_EQ(result.value(), 42);
  77. }
  78. TEST_CASE(promise_map_already_resolved)
  79. {
  80. Core::EventLoop loop;
  81. auto promise = MUST(Core::Promise<int>::try_create());
  82. promise->resolve(21);
  83. auto mapped_promise = promise->map<int>([](int result) {
  84. return result * 2;
  85. });
  86. auto result = mapped_promise->await();
  87. EXPECT(!result.is_error());
  88. EXPECT_EQ(result.value(), 42);
  89. }
  90. TEST_CASE(threaded_promise_instantly_resolved)
  91. {
  92. Core::EventLoop loop;
  93. bool resolved = false;
  94. bool rejected = true;
  95. Optional<pthread_t> thread_id;
  96. auto promise = Core::ThreadedPromise<int>::create();
  97. auto thread = Threading::Thread::construct([&, promise] {
  98. thread_id = pthread_self();
  99. promise->resolve(42);
  100. return 0;
  101. });
  102. thread->start();
  103. promise
  104. ->when_resolved([&](int result) {
  105. EXPECT(thread_id.has_value());
  106. EXPECT(pthread_equal(thread_id.value(), pthread_self()));
  107. resolved = true;
  108. rejected = false;
  109. EXPECT_EQ(result, 42);
  110. })
  111. .when_rejected([](Error&&) {
  112. VERIFY_NOT_REACHED();
  113. });
  114. promise->await();
  115. EXPECT(promise->has_completed());
  116. EXPECT(resolved);
  117. EXPECT(!rejected);
  118. MUST(thread->join());
  119. }
  120. TEST_CASE(threaded_promise_resolved_later)
  121. {
  122. Core::EventLoop loop;
  123. IGNORE_USE_IN_ESCAPING_LAMBDA bool unblock_thread = false;
  124. bool resolved = false;
  125. bool rejected = true;
  126. Optional<pthread_t> thread_id;
  127. auto promise = Core::ThreadedPromise<int>::create();
  128. auto thread = Threading::Thread::construct([&, promise] {
  129. thread_id = pthread_self();
  130. while (!unblock_thread)
  131. usleep(500);
  132. promise->resolve(42);
  133. return 0;
  134. });
  135. thread->start();
  136. promise
  137. ->when_resolved([&]() {
  138. EXPECT(thread_id.has_value());
  139. EXPECT(pthread_equal(thread_id.value(), pthread_self()));
  140. EXPECT(unblock_thread);
  141. resolved = true;
  142. rejected = false;
  143. })
  144. .when_rejected([](Error&&) {
  145. VERIFY_NOT_REACHED();
  146. });
  147. Core::EventLoop::current().deferred_invoke([&]() { unblock_thread = true; });
  148. promise->await();
  149. EXPECT(promise->has_completed());
  150. EXPECT(unblock_thread);
  151. EXPECT(resolved);
  152. EXPECT(!rejected);
  153. MUST(thread->join());
  154. }
  155. TEST_CASE(threaded_promise_synchronously_resolved)
  156. {
  157. Core::EventLoop loop;
  158. bool resolved = false;
  159. bool rejected = true;
  160. auto thread_id = pthread_self();
  161. auto promise = Core::ThreadedPromise<int>::create();
  162. promise->resolve(1337);
  163. promise
  164. ->when_resolved([&]() {
  165. EXPECT(pthread_equal(thread_id, pthread_self()));
  166. resolved = true;
  167. rejected = false;
  168. })
  169. .when_rejected([](Error&&) {
  170. VERIFY_NOT_REACHED();
  171. });
  172. promise->await();
  173. EXPECT(promise->has_completed());
  174. EXPECT(resolved);
  175. EXPECT(!rejected);
  176. }