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

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

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