OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "modules/fetch/CompositeDataConsumerHandle.h" | |
6 | |
7 #include "modules/fetch/DataConsumerHandleTestUtil.h" | |
8 #include "platform/CrossThreadFunctional.h" | |
9 #include "platform/WaitableEvent.h" | |
10 #include "platform/heap/Handle.h" | |
11 #include "public/platform/Platform.h" | |
12 #include "public/platform/WebThread.h" | |
13 #include "public/platform/WebTraceLocation.h" | |
14 #include "testing/gmock/include/gmock/gmock.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 #include "wtf/Locker.h" | |
17 #include "wtf/PtrUtil.h" | |
18 #include <memory> | |
19 | |
20 namespace blink { | |
21 | |
22 namespace { | |
23 | |
24 using ::testing::ByMove; | |
25 using ::testing::InSequence; | |
26 using ::testing::Return; | |
27 using ::testing::StrictMock; | |
28 using Checkpoint = StrictMock<::testing::MockFunction<void(int)>>; | |
29 | |
30 const WebDataConsumerHandle::Result kShouldWait = WebDataConsumerHandle::ShouldW
ait; | |
31 const WebDataConsumerHandle::Result kOk = WebDataConsumerHandle::Ok; | |
32 const WebDataConsumerHandle::Flags kNone = WebDataConsumerHandle::FlagNone; | |
33 | |
34 class MockReader : public WebDataConsumerHandle::Reader { | |
35 public: | |
36 static std::unique_ptr<StrictMock<MockReader>> create() { return wrapUnique(
new StrictMock<MockReader>); } | |
37 | |
38 using Result = WebDataConsumerHandle::Result; | |
39 using Flags = WebDataConsumerHandle::Flags; | |
40 MOCK_METHOD4(read, Result(void*, size_t, Flags, size_t*)); | |
41 MOCK_METHOD3(beginRead, Result(const void**, Flags, size_t*)); | |
42 MOCK_METHOD1(endRead, Result(size_t)); | |
43 }; | |
44 | |
45 class MockHandle : public WebDataConsumerHandle { | |
46 public: | |
47 static std::unique_ptr<StrictMock<MockHandle>> create() { return wrapUnique(
new StrictMock<MockHandle>); } | |
48 | |
49 MOCK_METHOD1(obtainReader, std::unique_ptr<Reader>(Client*)); | |
50 | |
51 private: | |
52 const char* debugName() const override { return "MockHandle in CompositeData
ConsumerHandleTest"; } | |
53 }; | |
54 | |
55 class ThreadingRegistrationTest : public DataConsumerHandleTestUtil::ThreadingTe
stBase { | |
56 public: | |
57 using Self = ThreadingRegistrationTest; | |
58 static PassRefPtr<Self> create() { return adoptRef(new Self); } | |
59 | |
60 void run() | |
61 { | |
62 ThreadHolder holder(this); | |
63 m_waitableEvent = wrapUnique(new WaitableEvent()); | |
64 | |
65 postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::
createHandle, wrapPassRefPtr(this))); | |
66 postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::o
btainReader, wrapPassRefPtr(this))); | |
67 } | |
68 | |
69 private: | |
70 ThreadingRegistrationTest() = default; | |
71 | |
72 void createHandle() | |
73 { | |
74 m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::creat
e("handle1", m_context), &m_updater); | |
75 m_waitableEvent->signal(); | |
76 } | |
77 void obtainReader() | |
78 { | |
79 m_reader = m_handle->obtainReader(&m_client); | |
80 postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update,
wrapPassRefPtr(this))); | |
81 } | |
82 void update() | |
83 { | |
84 m_updater->update(DataConsumerHandle::create("handle2", m_context)); | |
85 m_updater.clear(); | |
86 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetRea
der, wrapPassRefPtr(this))); | |
87 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDo
ne, wrapPassRefPtr(this))); | |
88 } | |
89 | |
90 std::unique_ptr<WebDataConsumerHandle> m_handle; | |
91 CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater; | |
92 }; | |
93 | |
94 class ThreadingRegistrationDeleteHandleTest : public DataConsumerHandleTestUtil:
:ThreadingTestBase { | |
95 public: | |
96 using Self = ThreadingRegistrationDeleteHandleTest; | |
97 static PassRefPtr<Self> create() { return adoptRef(new Self); } | |
98 | |
99 void run() | |
100 { | |
101 ThreadHolder holder(this); | |
102 m_waitableEvent = wrapUnique(new WaitableEvent()); | |
103 | |
104 postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::
createHandle, wrapPassRefPtr(this))); | |
105 postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::o
btainReader, wrapPassRefPtr(this))); | |
106 } | |
107 | |
108 private: | |
109 ThreadingRegistrationDeleteHandleTest() = default; | |
110 | |
111 void createHandle() | |
112 { | |
113 m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::creat
e("handle1", m_context), &m_updater); | |
114 m_waitableEvent->signal(); | |
115 } | |
116 | |
117 void obtainReader() | |
118 { | |
119 m_reader = m_handle->obtainReader(&m_client); | |
120 postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update,
wrapPassRefPtr(this))); | |
121 } | |
122 void update() | |
123 { | |
124 m_updater->update(DataConsumerHandle::create("handle2", m_context)); | |
125 m_updater.clear(); | |
126 m_handle = nullptr; | |
127 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetRea
der, wrapPassRefPtr(this))); | |
128 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDo
ne, wrapPassRefPtr(this))); | |
129 } | |
130 | |
131 std::unique_ptr<WebDataConsumerHandle> m_handle; | |
132 CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater; | |
133 }; | |
134 | |
135 class ThreadingRegistrationDeleteReaderTest : public DataConsumerHandleTestUtil:
:ThreadingTestBase { | |
136 public: | |
137 using Self = ThreadingRegistrationDeleteReaderTest; | |
138 static PassRefPtr<Self> create() { return adoptRef(new Self); } | |
139 | |
140 void run() | |
141 { | |
142 ThreadHolder holder(this); | |
143 m_waitableEvent = wrapUnique(new WaitableEvent()); | |
144 | |
145 postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::
createHandle, wrapPassRefPtr(this))); | |
146 postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::o
btainReader, wrapPassRefPtr(this))); | |
147 } | |
148 | |
149 private: | |
150 ThreadingRegistrationDeleteReaderTest() = default; | |
151 | |
152 void createHandle() | |
153 { | |
154 m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::creat
e("handle1", m_context), &m_updater); | |
155 m_waitableEvent->signal(); | |
156 } | |
157 | |
158 void obtainReader() | |
159 { | |
160 m_reader = m_handle->obtainReader(&m_client); | |
161 postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update,
wrapPassRefPtr(this))); | |
162 } | |
163 void update() | |
164 { | |
165 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetRea
der, wrapPassRefPtr(this))); | |
166 m_updater->update(DataConsumerHandle::create("handle2", m_context)); | |
167 m_updater.clear(); | |
168 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetRea
der, wrapPassRefPtr(this))); | |
169 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDo
ne, wrapPassRefPtr(this))); | |
170 } | |
171 | |
172 std::unique_ptr<WebDataConsumerHandle> m_handle; | |
173 CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater; | |
174 }; | |
175 | |
176 class ThreadingUpdatingReaderWhileUpdatingTest : public DataConsumerHandleTestUt
il::ThreadingTestBase { | |
177 public: | |
178 using Self = ThreadingUpdatingReaderWhileUpdatingTest; | |
179 static PassRefPtr<Self> create() { return adoptRef(new Self); } | |
180 | |
181 void run() | |
182 { | |
183 ThreadHolder holder(this); | |
184 m_waitableEvent = wrapUnique(new WaitableEvent()); | |
185 m_updateEvent = wrapUnique(new WaitableEvent()); | |
186 | |
187 postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::
createHandle, wrapPassRefPtr(this))); | |
188 postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::o
btainReader, wrapPassRefPtr(this))); | |
189 } | |
190 | |
191 private: | |
192 ThreadingUpdatingReaderWhileUpdatingTest() = default; | |
193 | |
194 void createHandle() | |
195 { | |
196 m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::creat
e("handle1", m_context), &m_updater); | |
197 m_waitableEvent->signal(); | |
198 } | |
199 | |
200 void obtainReader() | |
201 { | |
202 m_reader = m_handle->obtainReader(&m_client); | |
203 postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update,
wrapPassRefPtr(this))); | |
204 m_updateEvent->wait(); | |
205 } | |
206 | |
207 void update() | |
208 { | |
209 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::reobtain
Reader, wrapPassRefPtr(this))); | |
210 m_updater->update(DataConsumerHandle::create("handle2", m_context)); | |
211 m_updater.clear(); | |
212 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetRea
der, wrapPassRefPtr(this))); | |
213 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDo
ne, wrapPassRefPtr(this))); | |
214 m_updateEvent->signal(); | |
215 } | |
216 | |
217 void reobtainReader() | |
218 { | |
219 m_reader = nullptr; | |
220 m_reader = m_handle->obtainReader(&m_client); | |
221 } | |
222 | |
223 std::unique_ptr<WebDataConsumerHandle> m_handle; | |
224 CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater; | |
225 std::unique_ptr<WaitableEvent> m_updateEvent; | |
226 }; | |
227 | |
228 class ThreadingRegistrationUpdateTwiceAtOneTimeTest : public DataConsumerHandleT
estUtil::ThreadingTestBase { | |
229 public: | |
230 using Self = ThreadingRegistrationUpdateTwiceAtOneTimeTest; | |
231 static PassRefPtr<Self> create() { return adoptRef(new Self); } | |
232 | |
233 void run() | |
234 { | |
235 ThreadHolder holder(this); | |
236 m_waitableEvent = wrapUnique(new WaitableEvent()); | |
237 m_updateEvent = wrapUnique(new WaitableEvent()); | |
238 | |
239 postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::
createHandle, wrapPassRefPtr(this))); | |
240 postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::o
btainReader, wrapPassRefPtr(this))); | |
241 } | |
242 | |
243 private: | |
244 ThreadingRegistrationUpdateTwiceAtOneTimeTest() = default; | |
245 | |
246 void createHandle() | |
247 { | |
248 m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::creat
e("handle1", m_context), &m_updater); | |
249 m_waitableEvent->signal(); | |
250 } | |
251 | |
252 void obtainReader() | |
253 { | |
254 m_reader = m_handle->obtainReader(&m_client); | |
255 postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update,
wrapPassRefPtr(this))); | |
256 // Stalls this thread while updating handles. | |
257 m_updateEvent->wait(); | |
258 } | |
259 void update() | |
260 { | |
261 m_updater->update(DataConsumerHandle::create("handle2", m_context)); | |
262 m_updater->update(DataConsumerHandle::create("handle3", m_context)); | |
263 m_updateEvent->signal(); | |
264 m_updater.clear(); | |
265 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetRea
der, wrapPassRefPtr(this))); | |
266 postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDo
ne, wrapPassRefPtr(this))); | |
267 } | |
268 | |
269 std::unique_ptr<WebDataConsumerHandle> m_handle; | |
270 CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater; | |
271 std::unique_ptr<WaitableEvent> m_updateEvent; | |
272 }; | |
273 | |
274 TEST(CompositeDataConsumerHandleTest, Read) | |
275 { | |
276 char buffer[20]; | |
277 size_t size = 0; | |
278 DataConsumerHandleTestUtil::NoopClient client; | |
279 Checkpoint checkpoint; | |
280 | |
281 std::unique_ptr<MockHandle> handle1 = MockHandle::create(); | |
282 std::unique_ptr<MockHandle> handle2 = MockHandle::create(); | |
283 | |
284 // They will be adopted by |obtainReader|. | |
285 MockReader* reader1 = MockReader::create().release(); | |
286 MockReader* reader2 = MockReader::create().release(); | |
287 | |
288 InSequence s; | |
289 EXPECT_CALL(checkpoint, Call(0)); | |
290 EXPECT_CALL(*handle1, obtainReader(&client)).WillOnce(Return(ByMove(WTF::wra
pUnique(reader1)))); | |
291 EXPECT_CALL(checkpoint, Call(1)); | |
292 EXPECT_CALL(*reader1, read(buffer, sizeof(buffer), kNone, &size)).WillOnce(R
eturn(kOk)); | |
293 EXPECT_CALL(checkpoint, Call(2)); | |
294 EXPECT_CALL(*handle2, obtainReader(&client)).WillOnce(Return(ByMove(WTF::wra
pUnique(reader2)))); | |
295 EXPECT_CALL(checkpoint, Call(3)); | |
296 EXPECT_CALL(*reader2, read(buffer, sizeof(buffer), kNone, &size)).WillOnce(R
eturn(kOk)); | |
297 EXPECT_CALL(checkpoint, Call(4)); | |
298 | |
299 CompositeDataConsumerHandle::Updater* updater = nullptr; | |
300 std::unique_ptr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle:
:create(std::move(handle1), &updater); | |
301 checkpoint.Call(0); | |
302 std::unique_ptr<WebDataConsumerHandle::Reader> reader = handle->obtainReader
(&client); | |
303 checkpoint.Call(1); | |
304 EXPECT_EQ(kOk, reader->read(buffer, sizeof(buffer), kNone, &size)); | |
305 checkpoint.Call(2); | |
306 updater->update(std::move(handle2)); | |
307 checkpoint.Call(3); | |
308 EXPECT_EQ(kOk, reader->read(buffer, sizeof(buffer), kNone, &size)); | |
309 checkpoint.Call(4); | |
310 } | |
311 | |
312 TEST(CompositeDataConsumerHandleTest, TwoPhaseRead) | |
313 { | |
314 const void* p = nullptr; | |
315 size_t size = 0; | |
316 Checkpoint checkpoint; | |
317 | |
318 std::unique_ptr<MockHandle> handle1 = MockHandle::create(); | |
319 std::unique_ptr<MockHandle> handle2 = MockHandle::create(); | |
320 | |
321 // They are adopted by |obtainReader|. | |
322 MockReader* reader1 = MockReader::create().release(); | |
323 MockReader* reader2 = MockReader::create().release(); | |
324 | |
325 InSequence s; | |
326 EXPECT_CALL(checkpoint, Call(0)); | |
327 EXPECT_CALL(*handle1, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wra
pUnique(reader1)))); | |
328 EXPECT_CALL(checkpoint, Call(1)); | |
329 EXPECT_CALL(*reader1, beginRead(&p, kNone, &size)).WillOnce(Return(kOk)); | |
330 EXPECT_CALL(checkpoint, Call(2)); | |
331 EXPECT_CALL(*reader1, endRead(0)).WillOnce(Return(kOk)); | |
332 EXPECT_CALL(checkpoint, Call(3)); | |
333 EXPECT_CALL(*handle2, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wra
pUnique(reader2)))); | |
334 EXPECT_CALL(checkpoint, Call(4)); | |
335 EXPECT_CALL(*reader2, beginRead(&p, kNone, &size)).WillOnce(Return(kOk)); | |
336 EXPECT_CALL(checkpoint, Call(5)); | |
337 EXPECT_CALL(*reader2, endRead(0)).WillOnce(Return(kOk)); | |
338 EXPECT_CALL(checkpoint, Call(6)); | |
339 | |
340 CompositeDataConsumerHandle::Updater* updater = nullptr; | |
341 std::unique_ptr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle:
:create(std::move(handle1), &updater); | |
342 checkpoint.Call(0); | |
343 std::unique_ptr<WebDataConsumerHandle::Reader> reader = handle->obtainReader
(nullptr); | |
344 checkpoint.Call(1); | |
345 EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size)); | |
346 checkpoint.Call(2); | |
347 EXPECT_EQ(kOk, reader->endRead(0)); | |
348 checkpoint.Call(3); | |
349 updater->update(std::move(handle2)); | |
350 checkpoint.Call(4); | |
351 EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size)); | |
352 checkpoint.Call(5); | |
353 EXPECT_EQ(kOk, reader->endRead(0)); | |
354 checkpoint.Call(6); | |
355 } | |
356 | |
357 TEST(CompositeDataConsumerHandleTest, HangingTwoPhaseRead) | |
358 { | |
359 const void* p = nullptr; | |
360 size_t size = 0; | |
361 Checkpoint checkpoint; | |
362 | |
363 std::unique_ptr<MockHandle> handle1 = MockHandle::create(); | |
364 std::unique_ptr<MockHandle> handle2 = MockHandle::create(); | |
365 std::unique_ptr<MockHandle> handle3 = MockHandle::create(); | |
366 | |
367 // They are adopted by |obtainReader|. | |
368 MockReader* reader1 = MockReader::create().release(); | |
369 MockReader* reader2 = MockReader::create().release(); | |
370 MockReader* reader3 = MockReader::create().release(); | |
371 | |
372 InSequence s; | |
373 EXPECT_CALL(checkpoint, Call(0)); | |
374 EXPECT_CALL(*handle1, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wra
pUnique(reader1)))); | |
375 EXPECT_CALL(checkpoint, Call(1)); | |
376 EXPECT_CALL(*reader1, beginRead(&p, kNone, &size)).WillOnce(Return(kOk)); | |
377 EXPECT_CALL(checkpoint, Call(2)); | |
378 EXPECT_CALL(checkpoint, Call(3)); | |
379 EXPECT_CALL(*reader1, endRead(0)).WillOnce(Return(kOk)); | |
380 EXPECT_CALL(*handle2, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wra
pUnique(reader2)))); | |
381 EXPECT_CALL(checkpoint, Call(4)); | |
382 EXPECT_CALL(*reader2, beginRead(&p, kNone, &size)).WillOnce(Return(kShouldWa
it)); | |
383 EXPECT_CALL(checkpoint, Call(5)); | |
384 EXPECT_CALL(*handle3, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wra
pUnique(reader3)))); | |
385 EXPECT_CALL(checkpoint, Call(6)); | |
386 EXPECT_CALL(*reader3, beginRead(&p, kNone, &size)).WillOnce(Return(kOk)); | |
387 EXPECT_CALL(checkpoint, Call(7)); | |
388 EXPECT_CALL(*reader3, endRead(0)).WillOnce(Return(kOk)); | |
389 EXPECT_CALL(checkpoint, Call(8)); | |
390 | |
391 CompositeDataConsumerHandle::Updater* updater = nullptr; | |
392 std::unique_ptr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle:
:create(std::move(handle1), &updater); | |
393 checkpoint.Call(0); | |
394 std::unique_ptr<WebDataConsumerHandle::Reader> reader = handle->obtainReader
(nullptr); | |
395 checkpoint.Call(1); | |
396 EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size)); | |
397 checkpoint.Call(2); | |
398 updater->update(std::move(handle2)); | |
399 checkpoint.Call(3); | |
400 EXPECT_EQ(kOk, reader->endRead(0)); | |
401 checkpoint.Call(4); | |
402 EXPECT_EQ(kShouldWait, reader->beginRead(&p, kNone, &size)); | |
403 checkpoint.Call(5); | |
404 updater->update(std::move(handle3)); | |
405 checkpoint.Call(6); | |
406 EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size)); | |
407 checkpoint.Call(7); | |
408 EXPECT_EQ(kOk, reader->endRead(0)); | |
409 checkpoint.Call(8); | |
410 } | |
411 | |
412 TEST(CompositeDataConsumerHandleTest, RegisterClientOnDifferentThreads) | |
413 { | |
414 RefPtr<ThreadingRegistrationTest> test = ThreadingRegistrationTest::create()
; | |
415 test->run(); | |
416 | |
417 EXPECT_EQ( | |
418 "A reader is attached to handle1 on the reading thread.\n" | |
419 "A reader is detached from handle1 on the reading thread.\n" | |
420 "A reader is attached to handle2 on the reading thread.\n" | |
421 "A reader is detached from handle2 on the reading thread.\n", | |
422 test->result()); | |
423 } | |
424 | |
425 TEST(CompositeDataConsumerHandleTest, DeleteHandleWhileUpdating) | |
426 { | |
427 RefPtr<ThreadingRegistrationDeleteHandleTest> test = ThreadingRegistrationDe
leteHandleTest::create(); | |
428 test->run(); | |
429 | |
430 EXPECT_EQ( | |
431 "A reader is attached to handle1 on the reading thread.\n" | |
432 "A reader is detached from handle1 on the reading thread.\n" | |
433 "A reader is attached to handle2 on the reading thread.\n" | |
434 "A reader is detached from handle2 on the reading thread.\n", | |
435 test->result()); | |
436 } | |
437 | |
438 TEST(CompositeDataConsumerHandleTest, DeleteReaderWhileUpdating) | |
439 { | |
440 RefPtr<ThreadingRegistrationDeleteReaderTest> test = ThreadingRegistrationDe
leteReaderTest::create(); | |
441 test->run(); | |
442 | |
443 EXPECT_EQ( | |
444 "A reader is attached to handle1 on the reading thread.\n" | |
445 "A reader is detached from handle1 on the reading thread.\n", | |
446 test->result()); | |
447 } | |
448 | |
449 TEST(CompositeDataConsumerHandleTest, UpdateReaderWhileUpdating) | |
450 { | |
451 RefPtr<ThreadingUpdatingReaderWhileUpdatingTest> test = ThreadingUpdatingRea
derWhileUpdatingTest::create(); | |
452 test->run(); | |
453 | |
454 EXPECT_EQ( | |
455 "A reader is attached to handle1 on the reading thread.\n" | |
456 "A reader is detached from handle1 on the reading thread.\n" | |
457 "A reader is attached to handle2 on the reading thread.\n" | |
458 "A reader is detached from handle2 on the reading thread.\n", | |
459 test->result()); | |
460 } | |
461 | |
462 TEST(CompositeDataConsumerHandleTest, UpdateTwiceAtOnce) | |
463 { | |
464 RefPtr<ThreadingRegistrationUpdateTwiceAtOneTimeTest> test = ThreadingRegist
rationUpdateTwiceAtOneTimeTest::create(); | |
465 test->run(); | |
466 | |
467 EXPECT_EQ( | |
468 "A reader is attached to handle1 on the reading thread.\n" | |
469 "A reader is detached from handle1 on the reading thread.\n" | |
470 "A reader is attached to handle3 on the reading thread.\n" | |
471 "A reader is detached from handle3 on the reading thread.\n", | |
472 test->result()); | |
473 } | |
474 | |
475 TEST(CompositeDataConsumerHandleTest, DoneHandleNotification) | |
476 { | |
477 RefPtr<DataConsumerHandleTestUtil::ThreadingHandleNotificationTest> test = D
ataConsumerHandleTestUtil::ThreadingHandleNotificationTest::create(); | |
478 CompositeDataConsumerHandle::Updater* updater = nullptr; | |
479 // Test this function returns. | |
480 test->run(CompositeDataConsumerHandle::create(createDoneDataConsumerHandle()
, &updater)); | |
481 } | |
482 | |
483 TEST(CompositeDataConsumerHandleTest, DoneHandleNoNotification) | |
484 { | |
485 RefPtr<DataConsumerHandleTestUtil::ThreadingHandleNoNotificationTest> test =
DataConsumerHandleTestUtil::ThreadingHandleNoNotificationTest::create(); | |
486 CompositeDataConsumerHandle::Updater* updater = nullptr; | |
487 // Test this function doesn't crash. | |
488 test->run(CompositeDataConsumerHandle::create(createDoneDataConsumerHandle()
, &updater)); | |
489 } | |
490 | |
491 } // namespace | |
492 | |
493 } // namespace blink | |
OLD | NEW |