TestLibCorePromise.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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(promise_map)
  50. {
  51. Core::EventLoop loop;
  52. auto promise = MUST(Core::Promise<int>::try_create());
  53. auto mapped_promise = promise->map<int>([](int result) {
  54. return result * 2;
  55. });
  56. loop.deferred_invoke([=] {
  57. promise->resolve(21);
  58. });
  59. auto result = mapped_promise->await();
  60. EXPECT(!result.is_error());
  61. EXPECT_EQ(result.value(), 42);
  62. }
  63. TEST_CASE(promise_map_already_resolved)
  64. {
  65. Core::EventLoop loop;
  66. auto promise = MUST(Core::Promise<int>::try_create());
  67. promise->resolve(21);
  68. auto mapped_promise = promise->map<int>([](int result) {
  69. return result * 2;
  70. });
  71. auto result = mapped_promise->await();
  72. EXPECT(!result.is_error());
  73. EXPECT_EQ(result.value(), 42);
  74. }
  75. TEST_CASE(threaded_promise_instantly_resolved)
  76. {
  77. Core::EventLoop loop;
  78. bool resolved = false;
  79. bool rejected = true;
  80. Optional<pthread_t> thread_id;
  81. auto promise = Core::ThreadedPromise<int>::create();
  82. auto thread = Threading::Thread::construct([&, promise] {
  83. thread_id = pthread_self();
  84. promise->resolve(42);
  85. return 0;
  86. });
  87. thread->start();
  88. promise
  89. ->when_resolved([&](int result) {
  90. EXPECT(thread_id.has_value());
  91. EXPECT(pthread_equal(thread_id.value(), pthread_self()));
  92. resolved = true;
  93. rejected = false;
  94. EXPECT_EQ(result, 42);
  95. })
  96. .when_rejected([](Error&&) {
  97. VERIFY_NOT_REACHED();
  98. });
  99. promise->await();
  100. EXPECT(promise->has_completed());
  101. EXPECT(resolved);
  102. EXPECT(!rejected);
  103. MUST(thread->join());
  104. }
  105. TEST_CASE(threaded_promise_resolved_later)
  106. {
  107. Core::EventLoop loop;
  108. bool unblock_thread = false;
  109. bool resolved = false;
  110. bool rejected = true;
  111. Optional<pthread_t> thread_id;
  112. auto promise = Core::ThreadedPromise<int>::create();
  113. auto thread = Threading::Thread::construct([&, promise] {
  114. thread_id = pthread_self();
  115. while (!unblock_thread)
  116. usleep(500);
  117. promise->resolve(42);
  118. return 0;
  119. });
  120. thread->start();
  121. promise
  122. ->when_resolved([&]() {
  123. EXPECT(thread_id.has_value());
  124. EXPECT(pthread_equal(thread_id.value(), pthread_self()));
  125. EXPECT(unblock_thread);
  126. resolved = true;
  127. rejected = false;
  128. })
  129. .when_rejected([](Error&&) {
  130. VERIFY_NOT_REACHED();
  131. });
  132. Core::EventLoop::current().deferred_invoke([&]() { unblock_thread = true; });
  133. promise->await();
  134. EXPECT(promise->has_completed());
  135. EXPECT(unblock_thread);
  136. EXPECT(resolved);
  137. EXPECT(!rejected);
  138. MUST(thread->join());
  139. }
  140. TEST_CASE(threaded_promise_synchronously_resolved)
  141. {
  142. Core::EventLoop loop;
  143. bool resolved = false;
  144. bool rejected = true;
  145. auto thread_id = pthread_self();
  146. auto promise = Core::ThreadedPromise<int>::create();
  147. promise->resolve(1337);
  148. promise
  149. ->when_resolved([&]() {
  150. EXPECT(pthread_equal(thread_id, pthread_self()));
  151. resolved = true;
  152. rejected = false;
  153. })
  154. .when_rejected([](Error&&) {
  155. VERIFY_NOT_REACHED();
  156. });
  157. promise->await();
  158. EXPECT(promise->has_completed());
  159. EXPECT(resolved);
  160. EXPECT(!rejected);
  161. }