Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: media/midi/task_service_unittest.cc

Issue 2741713002: Web MIDI: implement TaskService (Closed)
Patch Set: offline review: merge reply task to bound task Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« media/midi/task_service.cc ('K') | « media/midi/task_service.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
5 #include "media/midi/task_service.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/run_loop.h"
15 #include "base/synchronization/lock.h"
16 #include "base/test/test_simple_task_runner.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "base/time/time.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace midi {
22
23 namespace {
24
25 enum {
26 kDefaultRunner = TaskService::kDefaultRunnerId,
27 kFirstRunner,
28 kSecondRunner
29 };
30
31 base::WaitableEvent* GetEvent() {
32 static base::WaitableEvent* event =
33 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL,
34 base::WaitableEvent::InitialState::NOT_SIGNALED);
35 return event;
36 }
37
38 void SignalEvent() {
39 GetEvent()->Signal();
40 }
41
42 void WaitEvent() {
43 GetEvent()->Wait();
44 }
45
46 void ResetEvent() {
47 GetEvent()->Reset();
48 }
49
50 class TaskServiceClient {
51 public:
52 TaskServiceClient(TaskService* task_service)
53 : task_service_(task_service),
54 wait_task_event_(base::MakeUnique<base::WaitableEvent>(
55 base::WaitableEvent::ResetPolicy::MANUAL,
56 base::WaitableEvent::InitialState::NOT_SIGNALED)),
57 count_(0u) {
58 DCHECK(task_service);
59 }
60
61 bool Bind() { return task_service()->BindInstance(); }
62
63 bool Unbind() { return task_service()->UnbindInstance(); }
64
65 void PostBoundTask(TaskService::RunnerId runner_id) {
66 task_service()->PostBoundTask(
67 runner_id, base::BindOnce(&TaskServiceClient::IncrementCount,
68 base::Unretained(this)));
69 }
70
71 void PostBoundSignalTask(TaskService::RunnerId runner_id) {
72 task_service()->PostBoundTask(
73 runner_id, base::BindOnce(&TaskServiceClient::SignalEvent,
74 base::Unretained(this)));
75 }
76
77 void PostBoundWaitTask(TaskService::RunnerId runner_id) {
78 wait_task_event_->Reset();
79 task_service()->PostBoundTask(
80 runner_id,
81 base::BindOnce(&TaskServiceClient::WaitEvent, base::Unretained(this)));
82 }
83
84 void PostBoundDelayedSignalTask(TaskService::RunnerId runner_id) {
85 task_service()->PostBoundDelayedTask(
86 runner_id,
87 base::BindOnce(&TaskServiceClient::SignalEvent, base::Unretained(this)),
88 base::TimeDelta::FromMilliseconds(100));
89 }
90
91 void WaitTask() { wait_task_event_->Wait(); }
92
93 size_t count() {
94 base::AutoLock lock(lock_);
95 return count_;
96 }
97
98 private:
99 TaskService* task_service() { return task_service_; }
100
101 void IncrementCount() {
102 base::AutoLock lock(lock_);
103 count_++;
104 }
105
106 void SignalEvent() {
107 midi::SignalEvent();
108 IncrementCount();
109 }
110
111 void WaitEvent() {
112 wait_task_event_->Signal();
113 midi::WaitEvent();
114 IncrementCount();
115 }
116
117 base::Lock lock_;
118 TaskService* task_service_;
119 std::unique_ptr<base::WaitableEvent> wait_task_event_;
120 size_t count_;
121
122 DISALLOW_COPY_AND_ASSIGN(TaskServiceClient);
123 };
124
125 class MidiTaskServiceTest : public ::testing::Test {
126 public:
127 MidiTaskServiceTest() {}
128
129 protected:
130 TaskService* task_service() { return &task_service_; }
131 void RunUntilIdle() { task_runner_->RunUntilIdle(); }
132
133 private:
134 void SetUp() override {
135 ResetEvent();
136 task_runner_ = new base::TestSimpleTaskRunner();
137 thread_task_runner_handle_ =
138 base::MakeUnique<base::ThreadTaskRunnerHandle>(task_runner_);
139 }
140
141 void TearDown() override {
142 thread_task_runner_handle_.reset();
143 task_runner_ = NULL;
144 }
145
146 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
147 std::unique_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
148 TaskService task_service_;
149
150 DISALLOW_COPY_AND_ASSIGN(MidiTaskServiceTest);
151 };
152
153 // Tests if posted static tasks can be processed without any bound instance.
154 TEST_F(MidiTaskServiceTest, RunStaticTask) {
155 task_service()->PostStaticTask(kFirstRunner, base::BindOnce(&SignalEvent));
156 WaitEvent();
157 }
158
159 // Tests if posted tasks without calling BindInstance() are ignored.
160 TEST_F(MidiTaskServiceTest, RunUnauthorizedBoundTask) {
161 std::unique_ptr<TaskServiceClient> client =
162 base::MakeUnique<TaskServiceClient>(task_service());
163
164 client->PostBoundTask(kFirstRunner);
165
166 // Destruct |client| immediately, then see if the posted task is just ignored.
167 client = nullptr;
168 }
169
170 // Tests if invalid BindInstance() calls are correctly rejected, and it does not
171 // make the service insanity.
172 TEST_F(MidiTaskServiceTest, BindTwice) {
173 std::unique_ptr<TaskServiceClient> client =
174 base::MakeUnique<TaskServiceClient>(task_service());
175
176 EXPECT_TRUE(client->Bind());
177
178 // Should not be able to call BindInstance() twice before unbinding current
179 // bound instance.
180 EXPECT_FALSE(client->Bind());
181
182 // Should be able to unbind only the first instance.
183 EXPECT_TRUE(client->Unbind());
184 EXPECT_FALSE(client->Unbind());
185 }
186
187 // Tests if posted static tasks can be processed even with a bound instance.
188 TEST_F(MidiTaskServiceTest, RunStaticTaskWithBoundInstance) {
189 std::unique_ptr<TaskServiceClient> client =
190 base::MakeUnique<TaskServiceClient>(task_service());
191
192 EXPECT_TRUE(client->Bind());
193 // Should be able to post a static task even with a bound instance.
194 task_service()->PostStaticTask(kFirstRunner, base::BindOnce(&SignalEvent));
195 WaitEvent();
196 EXPECT_TRUE(client->Unbind());
197
198 ResetEvent();
199
200 EXPECT_TRUE(client->Bind());
201 task_service()->PostStaticTask(kFirstRunner, base::Bind(&SignalEvent));
202 // Should be able to unbind the instance to process a static task.
203 EXPECT_TRUE(client->Unbind());
204 WaitEvent();
205 }
206
207 // Tests functionalities to run bound tasks.
208 TEST_F(MidiTaskServiceTest, RunBoundTasks) {
209 std::unique_ptr<TaskServiceClient> client =
210 base::MakeUnique<TaskServiceClient>(task_service());
211
212 EXPECT_TRUE(client->Bind());
213
214 // Tests if a post task run.
215 EXPECT_EQ(0u, client->count());
216 client->PostBoundSignalTask(kFirstRunner);
217 WaitEvent();
218 EXPECT_EQ(1u, client->count());
219
220 // Tests if another posted task is handled correctly even if the instance is
221 // unbound immediately. The posted task should run safely if it starts before
222 // UnboundInstance() is call. Otherwise, it should be ignored. It completely
223 // depends on timing.
224 client->PostBoundTask(kFirstRunner);
225 EXPECT_TRUE(client->Unbind());
226 client = base::MakeUnique<TaskServiceClient>(task_service());
227
228 // Tests if an immediate call of another BindInstance() works correctly.
229 EXPECT_TRUE(client->Bind());
230
231 // Runs two tasks in two runners.
232 ResetEvent();
233 client->PostBoundSignalTask(kFirstRunner);
234 client->PostBoundTask(kSecondRunner);
235
236 // Waits only the first runner completion to see if the second runner handles
237 // the task correctly even if the bound instance is destructed.
238 WaitEvent();
239 EXPECT_TRUE(client->Unbind());
240 client = nullptr;
241 }
242
243 // Tests if a blocking task does not block other task runners.
244 TEST_F(MidiTaskServiceTest, RunBlockingTask) {
245 std::unique_ptr<TaskServiceClient> client =
246 base::MakeUnique<TaskServiceClient>(task_service());
247
248 EXPECT_TRUE(client->Bind());
249
250 // Posts a task that waits until the event is signaled.
251 client->PostBoundWaitTask(kFirstRunner);
252 // Confirms if the posted task starts. Now, the task should block in the task
253 // until the second task is invoked.
254 client->WaitTask();
255
256 // Posts another task to the second runner. The task should be able to run
257 // even though another posted task is blocking inside a critical section that
258 // protects running tasks from an instance unbinding.
259 client->PostBoundSignalTask(kSecondRunner);
260
261 // Wait until the second task runs.
262 WaitEvent();
263
264 // UnbindInstance() should wait until any running task finishes so that the
265 // instance can be destructed safely.
266 EXPECT_TRUE(client->Unbind());
267 EXPECT_EQ(2u, client->count());
268 client = nullptr;
269 }
270
271 // Tests if a bound delayed task runs correctly.
272 TEST_F(MidiTaskServiceTest, RunBoundDelayedTask) {
273 std::unique_ptr<TaskServiceClient> client =
274 base::MakeUnique<TaskServiceClient>(task_service());
275
276 EXPECT_TRUE(client->Bind());
277
278 // Posts a delayed task that signals after 100msec.
279 client->PostBoundDelayedSignalTask(kFirstRunner);
280
281 // Wait until the delayed task runs.
282 WaitEvent();
283
284 EXPECT_TRUE(client->Unbind());
285 EXPECT_EQ(1u, client->count());
286 client = nullptr;
287 }
288
289 // Tests if a bound task runs on the thread that bound the instance.
290 TEST_F(MidiTaskServiceTest, RunBoundTaskOnDefaultRunner) {
291 std::unique_ptr<TaskServiceClient> client =
292 base::MakeUnique<TaskServiceClient>(task_service());
293
294 EXPECT_TRUE(client->Bind());
295
296 // Posts a reply task that increments the count on the caller thread.
297 client->PostBoundTask(kDefaultRunner);
298
299 // The reply task should not run until the current message loop is processed.
300 EXPECT_EQ(0u, client->count());
301 RunUntilIdle();
302 EXPECT_EQ(1u, client->count());
303
304 EXPECT_TRUE(client->Unbind());
305 }
306
307 } // namespace
308
309 } // namespace midi
OLDNEW
« media/midi/task_service.cc ('K') | « media/midi/task_service.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698