task_service_unittest.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/midi/task_service.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/callback.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/memory/ref_counted.h"
  11. #include "base/run_loop.h"
  12. #include "base/synchronization/lock.h"
  13. #include "base/test/test_simple_task_runner.h"
  14. #include "base/threading/thread_task_runner_handle.h"
  15. #include "base/time/time.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. namespace midi {
  18. namespace {
  19. enum {
  20. kDefaultRunner = TaskService::kDefaultRunnerId,
  21. kFirstRunner,
  22. kSecondRunner
  23. };
  24. base::WaitableEvent* GetEvent() {
  25. static base::WaitableEvent* event =
  26. new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL,
  27. base::WaitableEvent::InitialState::NOT_SIGNALED);
  28. return event;
  29. }
  30. void SignalEvent() {
  31. GetEvent()->Signal();
  32. }
  33. void WaitEvent() {
  34. GetEvent()->Wait();
  35. }
  36. void ResetEvent() {
  37. GetEvent()->Reset();
  38. }
  39. class TaskServiceClient {
  40. public:
  41. TaskServiceClient(TaskService* task_service)
  42. : task_service_(task_service),
  43. wait_task_event_(std::make_unique<base::WaitableEvent>(
  44. base::WaitableEvent::ResetPolicy::MANUAL,
  45. base::WaitableEvent::InitialState::NOT_SIGNALED)),
  46. count_(0u) {
  47. DCHECK(task_service);
  48. }
  49. TaskServiceClient(const TaskServiceClient&) = delete;
  50. TaskServiceClient& operator=(const TaskServiceClient&) = delete;
  51. bool Bind() { return task_service()->BindInstance(); }
  52. bool Unbind() { return task_service()->UnbindInstance(); }
  53. void PostBoundTask(TaskService::RunnerId runner_id) {
  54. task_service()->PostBoundTask(
  55. runner_id, base::BindOnce(&TaskServiceClient::IncrementCount,
  56. base::Unretained(this)));
  57. }
  58. void PostBoundSignalTask(TaskService::RunnerId runner_id) {
  59. task_service()->PostBoundTask(
  60. runner_id, base::BindOnce(&TaskServiceClient::SignalEvent,
  61. base::Unretained(this)));
  62. }
  63. void PostBoundWaitTask(TaskService::RunnerId runner_id) {
  64. wait_task_event_->Reset();
  65. task_service()->PostBoundTask(
  66. runner_id,
  67. base::BindOnce(&TaskServiceClient::WaitEvent, base::Unretained(this)));
  68. }
  69. void PostBoundDelayedSignalTask(TaskService::RunnerId runner_id) {
  70. task_service()->PostBoundDelayedTask(
  71. runner_id,
  72. base::BindOnce(&TaskServiceClient::SignalEvent, base::Unretained(this)),
  73. base::Milliseconds(100));
  74. }
  75. void WaitTask() { wait_task_event_->Wait(); }
  76. size_t count() {
  77. base::AutoLock lock(lock_);
  78. return count_;
  79. }
  80. private:
  81. TaskService* task_service() { return task_service_; }
  82. void IncrementCount() {
  83. base::AutoLock lock(lock_);
  84. count_++;
  85. }
  86. void SignalEvent() {
  87. IncrementCount();
  88. midi::SignalEvent();
  89. }
  90. void WaitEvent() {
  91. IncrementCount();
  92. wait_task_event_->Signal();
  93. midi::WaitEvent();
  94. }
  95. base::Lock lock_;
  96. raw_ptr<TaskService> task_service_;
  97. std::unique_ptr<base::WaitableEvent> wait_task_event_;
  98. size_t count_;
  99. };
  100. class MidiTaskServiceTest : public ::testing::Test {
  101. public:
  102. MidiTaskServiceTest() = default;
  103. MidiTaskServiceTest(const MidiTaskServiceTest&) = delete;
  104. MidiTaskServiceTest& operator=(const MidiTaskServiceTest&) = delete;
  105. protected:
  106. TaskService* task_service() { return &task_service_; }
  107. void RunUntilIdle() { task_runner_->RunUntilIdle(); }
  108. private:
  109. void SetUp() override {
  110. ResetEvent();
  111. task_runner_ = new base::TestSimpleTaskRunner();
  112. thread_task_runner_handle_ =
  113. std::make_unique<base::ThreadTaskRunnerHandle>(task_runner_);
  114. }
  115. void TearDown() override {
  116. thread_task_runner_handle_.reset();
  117. task_runner_.reset();
  118. }
  119. scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
  120. std::unique_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
  121. TaskService task_service_;
  122. };
  123. // Tests if posted tasks without calling BindInstance() are ignored.
  124. TEST_F(MidiTaskServiceTest, RunUnauthorizedBoundTask) {
  125. std::unique_ptr<TaskServiceClient> client =
  126. std::make_unique<TaskServiceClient>(task_service());
  127. client->PostBoundTask(kFirstRunner);
  128. // Destruct |client| immediately, then see if the posted task is just ignored.
  129. // If it isn't, another thread will touch the destructed instance and will
  130. // cause a crash due to a use-after-free.
  131. client = nullptr;
  132. }
  133. // Tests if invalid BindInstance() calls are correctly rejected, and it does not
  134. // make the service insanity.
  135. TEST_F(MidiTaskServiceTest, BindTwice) {
  136. std::unique_ptr<TaskServiceClient> client =
  137. std::make_unique<TaskServiceClient>(task_service());
  138. EXPECT_TRUE(client->Bind());
  139. // Should not be able to call BindInstance() twice before unbinding current
  140. // bound instance.
  141. EXPECT_FALSE(client->Bind());
  142. // Should be able to unbind only the first instance.
  143. EXPECT_TRUE(client->Unbind());
  144. EXPECT_FALSE(client->Unbind());
  145. }
  146. // Tests if posted static tasks can be processed correctly.
  147. TEST_F(MidiTaskServiceTest, RunStaticTask) {
  148. std::unique_ptr<TaskServiceClient> client =
  149. std::make_unique<TaskServiceClient>(task_service());
  150. EXPECT_TRUE(client->Bind());
  151. // Should be able to post a static task while an instance is bound.
  152. task_service()->PostStaticTask(kFirstRunner, base::BindOnce(&SignalEvent));
  153. WaitEvent();
  154. EXPECT_TRUE(client->Unbind());
  155. ResetEvent();
  156. EXPECT_TRUE(client->Bind());
  157. task_service()->PostStaticTask(kFirstRunner, base::BindOnce(&SignalEvent));
  158. // Should be able to unbind the instance to process a static task.
  159. EXPECT_TRUE(client->Unbind());
  160. WaitEvent();
  161. ResetEvent();
  162. // Should be able to post a static task without a bound instance.
  163. task_service()->PostStaticTask(kFirstRunner, base::BindOnce(&SignalEvent));
  164. WaitEvent();
  165. }
  166. // Tests functionalities to run bound tasks.
  167. TEST_F(MidiTaskServiceTest, RunBoundTasks) {
  168. std::unique_ptr<TaskServiceClient> client =
  169. std::make_unique<TaskServiceClient>(task_service());
  170. EXPECT_TRUE(client->Bind());
  171. // Tests if a post task run.
  172. EXPECT_EQ(0u, client->count());
  173. client->PostBoundSignalTask(kFirstRunner);
  174. WaitEvent();
  175. EXPECT_EQ(1u, client->count());
  176. // Tests if another posted task is handled correctly even if the instance is
  177. // unbound immediately. The posted task should run safely if it starts before
  178. // UnboundInstance() is call. Otherwise, it should be ignored. It completely
  179. // depends on timing.
  180. client->PostBoundTask(kFirstRunner);
  181. EXPECT_TRUE(client->Unbind());
  182. client = std::make_unique<TaskServiceClient>(task_service());
  183. // Tests if an immediate call of another BindInstance() works correctly.
  184. EXPECT_TRUE(client->Bind());
  185. // Runs two tasks in two runners.
  186. ResetEvent();
  187. client->PostBoundSignalTask(kFirstRunner);
  188. client->PostBoundTask(kSecondRunner);
  189. // Waits only the first runner completion to see if the second runner handles
  190. // the task correctly even if the bound instance is destructed.
  191. WaitEvent();
  192. EXPECT_TRUE(client->Unbind());
  193. client = nullptr;
  194. }
  195. // Tests if a blocking task does not block other task runners.
  196. TEST_F(MidiTaskServiceTest, RunBlockingTask) {
  197. std::unique_ptr<TaskServiceClient> client =
  198. std::make_unique<TaskServiceClient>(task_service());
  199. EXPECT_TRUE(client->Bind());
  200. // Posts a task that waits until the event is signaled.
  201. client->PostBoundWaitTask(kFirstRunner);
  202. // Confirms if the posted task starts. Now, the task should block in the task
  203. // until the second task is invoked.
  204. client->WaitTask();
  205. // Posts another task to the second runner. The task should be able to run
  206. // even though another posted task is blocking inside a critical section that
  207. // protects running tasks from an instance unbinding.
  208. client->PostBoundSignalTask(kSecondRunner);
  209. // Wait until the second task runs.
  210. WaitEvent();
  211. // UnbindInstance() should wait until any running task finishes so that the
  212. // instance can be destructed safely.
  213. EXPECT_TRUE(client->Unbind());
  214. EXPECT_EQ(2u, client->count());
  215. client = nullptr;
  216. }
  217. // Tests if a bound delayed task runs correctly.
  218. TEST_F(MidiTaskServiceTest, RunBoundDelayedTask) {
  219. std::unique_ptr<TaskServiceClient> client =
  220. std::make_unique<TaskServiceClient>(task_service());
  221. EXPECT_TRUE(client->Bind());
  222. // Posts a delayed task that signals after 100msec.
  223. client->PostBoundDelayedSignalTask(kFirstRunner);
  224. // Wait until the delayed task runs.
  225. WaitEvent();
  226. EXPECT_TRUE(client->Unbind());
  227. EXPECT_EQ(1u, client->count());
  228. client = nullptr;
  229. }
  230. // Tests if a bound task runs on the thread that bound the instance.
  231. TEST_F(MidiTaskServiceTest, RunBoundTaskOnDefaultRunner) {
  232. std::unique_ptr<TaskServiceClient> client =
  233. std::make_unique<TaskServiceClient>(task_service());
  234. EXPECT_TRUE(client->Bind());
  235. // Posts a task that increments the count on the caller thread.
  236. client->PostBoundTask(kDefaultRunner);
  237. // The posted task should not run until the current message loop is processed.
  238. EXPECT_EQ(0u, client->count());
  239. RunUntilIdle();
  240. EXPECT_EQ(1u, client->count());
  241. EXPECT_TRUE(client->Unbind());
  242. }
  243. } // namespace
  244. } // namespace midi