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

Side by Side Diff: Source/modules/fetch/CompositeDataConsumerHandleTest.cpp

Issue 1162043007: Introduce CompositeDataConsumerHandle. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 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
OLDNEW
(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 "config.h"
6 #include "modules/fetch/CompositeDataConsumerHandle.h"
7
8 #include "platform/Task.h"
9 #include "platform/ThreadSafeFunctional.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 "public/platform/WebWaitableEvent.h"
15 #include "wtf/Locker.h"
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 namespace blink {
21
22 namespace {
23
24 using Result = WebDataConsumerHandle::Result;
25 using Flags = WebDataConsumerHandle::Flags;
26 using ::testing::InSequence;
27 using ::testing::Return;
28 using ::testing::StrictMock;
29 using Checkpoint = StrictMock<::testing::MockFunction<void(int)>>;
30
31 const Result kShouldWait = WebDataConsumerHandle::ShouldWait;
32 const Result kDone = WebDataConsumerHandle::Done;
33 const Result kOk = WebDataConsumerHandle::Ok;
34 const Result kUnexpectedError = WebDataConsumerHandle::UnexpectedError;
35 const Flags kNone = WebDataConsumerHandle::FlagNone;
36
37 class NoopClient final : public WebDataConsumerHandle::Client {
38 public:
39 void didGetReadable() override { }
40 };
41
42 class MockReader : public WebDataConsumerHandle::Reader {
43 public:
44 static PassOwnPtr<StrictMock<MockReader>> create() { return adoptPtr(new Str ictMock<MockReader>); }
45
46 MOCK_METHOD4(read, Result(void*, size_t, Flags, size_t*));
47 MOCK_METHOD3(beginRead, Result(const void**, Flags, size_t*));
48 MOCK_METHOD1(endRead, Result(size_t));
49 };
50
51 class MockHandle : public WebDataConsumerHandle {
52 public:
53 static PassOwnPtr<StrictMock<MockHandle>> create() { return adoptPtr(new Str ictMock<MockHandle>); }
54
55 MOCK_METHOD1(obtainReaderInternal, Reader*(Client*));
56 };
57
58 class ThreadingTestBase : public ThreadSafeRefCounted<ThreadingTestBase> {
59 public:
60 class Context : public ThreadSafeRefCounted<Context> {
61 public:
62 static PassRefPtr<Context> create() { return adoptRef(new Context); }
63 void recordAttach(const String& handle)
64 {
65 MutexLocker locker(m_loggingMutex);
66 m_result.append("A reader is attached to " + handle.isolatedCopy() + " on " + threadName() + ".\n");
67 }
68 void recordDetach(const String& handle)
69 {
70 MutexLocker locker(m_loggingMutex);
71 m_result.append("A reader is detached from " + handle.isolatedCopy() + " on " + threadName() + ".\n");
72 }
73
74 const String& result()
75 {
76 MutexLocker locker(m_loggingMutex);
77 return m_result;
78 }
79 WebThread* readingThread() { return m_readingThread.get(); }
80 WebThread* updatingThread() { return m_updatingThread.get(); }
81
82 private:
83 Context()
84 {
85 m_readingThread = adoptPtr(Platform::current()->createThread("readin g thread"));
86 m_updatingThread = adoptPtr(Platform::current()->createThread("updat ing thread"));
87 }
88 String threadName()
89 {
90 if (m_readingThread->isCurrentThread())
91 return "the reading thread";
92 if (m_updatingThread->isCurrentThread())
93 return "the updating thread";
94 return "an unknown thread";
95 }
96
97 OwnPtr<WebThread> m_readingThread;
98 OwnPtr<WebThread> m_updatingThread;
99 Mutex m_loggingMutex;
100 String m_result;
101 };
102
103 class ReaderImpl final : public WebDataConsumerHandle::Reader {
104 public:
105 ReaderImpl(const String& name, PassRefPtr<Context> context) : m_name(nam e.isolatedCopy()), m_context(context)
106 {
107 m_context->recordAttach(m_name);
108 }
109 ~ReaderImpl() override { m_context->recordDetach(m_name); }
110 Result read(void*, size_t, Flags, size_t*) override { return kShouldWait ; }
111 Result beginRead(const void**, Flags, size_t*) override { return kShould Wait; }
112 Result endRead(size_t) override { return kUnexpectedError; }
113
114 private:
115 const String m_name;
116 RefPtr<Context> m_context;
117 };
118 class DataConsumerHandle final : public WebDataConsumerHandle {
119 public:
120 DataConsumerHandle(const String& name, PassRefPtr<Context> context) : m_ name(name.isolatedCopy()), m_context(context) { }
121
122 private:
123 Reader* obtainReaderInternal(Client*) { return new ReaderImpl(m_name, m_ context); }
124 const String m_name;
125 RefPtr<Context> m_context;
126 };
127
128 void resetReader() { m_reader = nullptr; }
129 void signalDone() { m_waitableEvent->signal(); }
130 const String& result() { return m_context->result(); }
131 WebThread* readingThread() { return m_context->readingThread(); }
132 WebThread* updatingThread() { return m_context->updatingThread(); }
133
134 protected:
135 RefPtr<Context> m_context;
136 OwnPtr<CompositeDataConsumerHandle> m_handle;
137 OwnPtr<WebDataConsumerHandle::Reader> m_reader;
138 OwnPtr<WebWaitableEvent> m_waitableEvent;
139 NoopClient m_client;
140 };
141
142 class ThreadingRegistrationTest : public ThreadingTestBase {
143 public:
144 using Self = ThreadingRegistrationTest;
145 void run()
146 {
147 m_context = Context::create();
148 m_waitableEvent = adoptPtr(Platform::current()->createWaitableEvent());
149 m_handle = CompositeDataConsumerHandle::create(adoptPtr(new DataConsumer Handle("handle1", m_context)));
150
151 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::obta inReader, this)));
152
153 m_waitableEvent->wait();
154 }
155
156 private:
157 void obtainReader()
158 {
159 m_reader = m_handle->obtainReader(&m_client);
160 updatingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::upd ate, this)));
161 }
162 void update()
163 {
164 m_handle->update(adoptPtr(new DataConsumerHandle("handle2", m_context))) ;
165 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::rese tReader, this)));
166 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::sign alDone, this)));
167 }
168 };
169
170 class ThreadingRegistrationDeleteHandleTest : public ThreadingTestBase {
171 public:
172 using Self = ThreadingRegistrationDeleteHandleTest;
173 void run()
174 {
175 m_context = Context::create();
176 m_waitableEvent = adoptPtr(Platform::current()->createWaitableEvent());
177 m_handle = CompositeDataConsumerHandle::create(adoptPtr(new DataConsumer Handle("handle1", m_context)));
178
179 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::obta inReader, this)));
180
181 m_waitableEvent->wait();
182 }
183
184 private:
185 void obtainReader()
186 {
187 m_reader = m_handle->obtainReader(&m_client);
188 updatingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::upd ate, this)));
189 }
190 void update()
191 {
192 m_handle->update(adoptPtr(new DataConsumerHandle("handle2", m_context))) ;
193 m_handle = nullptr;
194 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::rese tReader, this)));
195 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::sign alDone, this)));
196 }
197 };
198
199 class ThreadingRegistrationDeleteReaderTest : public ThreadingTestBase {
200 public:
201 using Self = ThreadingRegistrationDeleteReaderTest;
202 void run()
203 {
204 m_context = Context::create();
205 m_waitableEvent = adoptPtr(Platform::current()->createWaitableEvent());
206 m_handle = CompositeDataConsumerHandle::create(adoptPtr(new DataConsumer Handle("handle1", m_context)));
207
208 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::obta inReader, this)));
209
210 m_waitableEvent->wait();
211 }
212
213 private:
214 void obtainReader()
215 {
216 m_reader = m_handle->obtainReader(&m_client);
217 updatingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::upd ate, this)));
218 }
219 void update()
220 {
221 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::rese tReader, this)));
222 m_handle->update(adoptPtr(new DataConsumerHandle("handle2", m_context))) ;
223 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::rese tReader, this)));
224 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::sign alDone, this)));
225 }
226 };
227
228 class ThreadingRegistrationUpdateTwiceAtOneTimeTest : public ThreadingTestBase {
229 public:
230 using Self = ThreadingRegistrationUpdateTwiceAtOneTimeTest;
231 void run()
232 {
233 m_context = Context::create();
234 m_waitableEvent = adoptPtr(Platform::current()->createWaitableEvent());
235 m_handle = CompositeDataConsumerHandle::create(adoptPtr(new DataConsumer Handle("handle1", m_context)));
236
237 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::obta inReader, this)));
238
239 m_waitableEvent->wait();
240 }
241
242 private:
243 void obtainReader()
244 {
245 m_reader = m_handle->obtainReader(&m_client);
246 updatingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::upd ate, this)));
247 }
248 void update()
249 {
250 m_handle->update(adoptPtr(new DataConsumerHandle("handle2", m_context))) ;
251 m_handle->update(adoptPtr(new DataConsumerHandle("handle3", m_context))) ;
252 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::rese tReader, this)));
253 readingThread()->postTask(FROM_HERE, new Task(threadSafeBind(&Self::sign alDone, this)));
254 }
255 };
256
257 TEST(CompositeDataConsumerHandleTest, CreateWaitingHandle)
258 {
259 char buffer[20];
260 const void* p = nullptr;
261 size_t size = 0;
262 OwnPtr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle::createWa itingHandle();
263 OwnPtr<WebDataConsumerHandle::Reader> reader = handle->obtainReader(nullptr) ;
264
265 EXPECT_EQ(kShouldWait, reader->read(buffer, sizeof(buffer), kNone, &size));
266 EXPECT_EQ(kShouldWait, reader->beginRead(&p, kNone, &size));
267 EXPECT_EQ(kUnexpectedError, reader->endRead(99));
268 }
269
270 TEST(CompositeDataConsumerHandleTest, CreateDoneHandle)
271 {
272 char buffer[20];
273 const void* p = nullptr;
274 size_t size = 0;
275 OwnPtr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle::createDo neHandle();
276 OwnPtr<WebDataConsumerHandle::Reader> reader = handle->obtainReader(nullptr) ;
277
278 EXPECT_EQ(kDone, reader->read(buffer, sizeof(buffer), kNone, &size));
279 EXPECT_EQ(kDone, reader->beginRead(&p, kNone, &size));
280 EXPECT_EQ(kUnexpectedError, reader->endRead(99));
281 (void)kOk;
282 }
283
284 TEST(CompositeDataConsumerHandleTest, Read)
285 {
286 char buffer[20];
287 size_t size = 0;
288 NoopClient client;
289 Checkpoint checkpoint;
290
291 OwnPtr<MockHandle> handle1 = MockHandle::create();
292 OwnPtr<MockHandle> handle2 = MockHandle::create();
293 OwnPtr<MockReader> reader1 = MockReader::create();
294 OwnPtr<MockReader> reader2 = MockReader::create();
295
296 InSequence s;
297 EXPECT_CALL(checkpoint, Call(0));
298 EXPECT_CALL(*handle1, obtainReaderInternal(&client)).WillOnce(Return(reader1 .get()));
299 EXPECT_CALL(checkpoint, Call(1));
300 EXPECT_CALL(*reader1, read(buffer, sizeof(buffer), kNone, &size)).WillOnce(R eturn(kOk));
301 EXPECT_CALL(checkpoint, Call(2));
302 EXPECT_CALL(*handle2, obtainReaderInternal(&client)).WillOnce(Return(reader2 .get()));
303 EXPECT_CALL(checkpoint, Call(3));
304 EXPECT_CALL(*reader2, read(buffer, sizeof(buffer), kNone, &size)).WillOnce(R eturn(kOk));
305 EXPECT_CALL(checkpoint, Call(4));
306
307 // They are adopted by |obtainReader|.
308 (void)reader1.leakPtr();
309 (void)reader2.leakPtr();
310
311 OwnPtr<CompositeDataConsumerHandle> handle = CompositeDataConsumerHandle::cr eate(handle1.release());
312 checkpoint.Call(0);
313 OwnPtr<CompositeDataConsumerHandle::Reader> reader = handle->obtainReader(&c lient);
314 checkpoint.Call(1);
315 EXPECT_EQ(kOk, reader->read(buffer, sizeof(buffer), kNone, &size));
316 checkpoint.Call(2);
317 handle->update(handle2.release());
318 checkpoint.Call(3);
319 EXPECT_EQ(kOk, reader->read(buffer, sizeof(buffer), kNone, &size));
320 checkpoint.Call(4);
321 }
322
323 TEST(CompositeDataConsumerHandleTest, TwoPhaseRead)
324 {
325 const void* p = nullptr;
326 size_t size = 0;
327 Checkpoint checkpoint;
328
329 OwnPtr<MockHandle> handle1 = MockHandle::create();
330 OwnPtr<MockHandle> handle2 = MockHandle::create();
331 OwnPtr<MockReader> reader1 = MockReader::create();
332 OwnPtr<MockReader> reader2 = MockReader::create();
333
334 InSequence s;
335 EXPECT_CALL(checkpoint, Call(0));
336 EXPECT_CALL(*handle1, obtainReaderInternal(nullptr)).WillOnce(Return(reader1 .get()));
337 EXPECT_CALL(checkpoint, Call(1));
338 EXPECT_CALL(*reader1, beginRead(&p, kNone, &size)).WillOnce(Return(kOk));
339 EXPECT_CALL(checkpoint, Call(2));
340 EXPECT_CALL(*reader1, endRead(0)).WillOnce(Return(kOk));
341 EXPECT_CALL(checkpoint, Call(3));
342 EXPECT_CALL(*handle2, obtainReaderInternal(nullptr)).WillOnce(Return(reader2 .get()));
343 EXPECT_CALL(checkpoint, Call(4));
344 EXPECT_CALL(*reader2, beginRead(&p, kNone, &size)).WillOnce(Return(kOk));
345 EXPECT_CALL(checkpoint, Call(5));
346 EXPECT_CALL(*reader2, endRead(0)).WillOnce(Return(kOk));
347 EXPECT_CALL(checkpoint, Call(6));
348
349 // They are adopted by |obtainReader|.
350 (void)reader1.leakPtr();
351 (void)reader2.leakPtr();
352
353 OwnPtr<CompositeDataConsumerHandle> handle = CompositeDataConsumerHandle::cr eate(handle1.release());
354 checkpoint.Call(0);
355 OwnPtr<CompositeDataConsumerHandle::Reader> reader = handle->obtainReader(nu llptr);
356 checkpoint.Call(1);
357 EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size));
358 checkpoint.Call(2);
359 EXPECT_EQ(kOk, reader->endRead(0));
360 checkpoint.Call(3);
361 handle->update(handle2.release());
362 checkpoint.Call(4);
363 EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size));
364 checkpoint.Call(5);
365 EXPECT_EQ(kOk, reader->endRead(0));
366 checkpoint.Call(6);
367 }
368
369 TEST(CompositeDataConsumerHandleTest, RegisterClientOnDifferentThreads)
370 {
371 ThreadingRegistrationTest test;
372 test.run();
373
374 EXPECT_EQ(
375 "A reader is attached to handle1 on the reading thread.\n"
376 "A reader is detached from handle1 on the reading thread.\n"
377 "A reader is attached to handle2 on the reading thread.\n"
378 "A reader is detached from handle2 on the reading thread.\n",
379 test.result());
380 }
381
382 TEST(CompositeDataConsumerHandleTest, DeleteHandleWhileUpdating)
383 {
384 ThreadingRegistrationDeleteHandleTest test;
385 test.run();
386
387 EXPECT_EQ(
388 "A reader is attached to handle1 on the reading thread.\n"
389 "A reader is detached from handle1 on the reading thread.\n"
390 "A reader is attached to handle2 on the reading thread.\n"
391 "A reader is detached from handle2 on the reading thread.\n",
392 test.result());
393 }
394
395 TEST(CompositeDataConsumerHandleTest, DeleteReaderWhileUpdating)
396 {
397 ThreadingRegistrationDeleteReaderTest test;
398 test.run();
399
400 EXPECT_EQ(
401 "A reader is attached to handle1 on the reading thread.\n"
402 "A reader is detached from handle1 on the reading thread.\n",
403 test.result());
404 }
405
406 TEST(CompositeDataConsumerHandleTest, UpdateTwiceAtOnce)
407 {
408 ThreadingRegistrationUpdateTwiceAtOneTimeTest test;
409 test.run();
410
411 EXPECT_EQ(
412 "A reader is attached to handle1 on the reading thread.\n"
413 "A reader is detached from handle1 on the reading thread.\n"
414 "A reader is attached to handle3 on the reading thread.\n"
415 "A reader is detached from handle3 on the reading thread.\n",
416 test.result());
417 }
418
419 } // namespace
420
421 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698