Index: Source/modules/fetch/DataConsumerTeeTest.cpp |
diff --git a/Source/modules/fetch/DataConsumerTeeTest.cpp b/Source/modules/fetch/DataConsumerTeeTest.cpp |
index d43e9d09f03d8b3b82bf3bac7507edc8bc9c8099..c4a58dc126624bcfcfb1a5fe7a51bf3cc4affbb0 100644 |
--- a/Source/modules/fetch/DataConsumerTeeTest.cpp |
+++ b/Source/modules/fetch/DataConsumerTeeTest.cpp |
@@ -25,6 +25,12 @@ |
namespace blink { |
namespace { |
+using ::testing::InSequence; |
+using ::testing::Return; |
+using ::testing::StrictMock; |
+using ::testing::_; |
+using Checkpoint = StrictMock<::testing::MockFunction<void(int)>>; |
+ |
using Result = WebDataConsumerHandle::Result; |
using Thread = DataConsumerHandleTestUtil::Thread; |
const WebDataConsumerHandle::Flags kNone = WebDataConsumerHandle::FlagNone; |
@@ -32,6 +38,8 @@ const Result kOk = WebDataConsumerHandle::Ok; |
const Result kShouldWait = WebDataConsumerHandle::ShouldWait; |
const Result kDone = WebDataConsumerHandle::Done; |
const Result kUnexpectedError = WebDataConsumerHandle::UnexpectedError; |
+const FetchDataConsumerHandle::Reader::BlobSizePolicy kDisallowBlobWithInvalidSize = FetchDataConsumerHandle::Reader::DisallowBlobWithInvalidSize; |
+const FetchDataConsumerHandle::Reader::BlobSizePolicy kAllowBlobWithInvalidSize = FetchDataConsumerHandle::Reader::AllowBlobWithInvalidSize; |
using Command = DataConsumerHandleTestUtil::Command; |
using Handle = DataConsumerHandleTestUtil::ReplayingHandle; |
@@ -137,20 +145,21 @@ private: |
OwnPtr<WebWaitableEvent> m_waitableEvent; |
}; |
+template<typename Handle> |
class TeeCreationThread { |
public: |
- void run(PassOwnPtr<WebDataConsumerHandle> src, OwnPtr<WebDataConsumerHandle>* dest1, OwnPtr<WebDataConsumerHandle>* dest2) |
+ void run(PassOwnPtr<Handle> src, OwnPtr<Handle>* dest1, OwnPtr<Handle>* dest2) |
{ |
m_thread = adoptPtr(new Thread("src thread", Thread::WithExecutionContext)); |
m_waitableEvent = adoptPtr(Platform::current()->createWaitableEvent()); |
- m_thread->thread()->postTask(FROM_HERE, new Task(threadSafeBind(&TeeCreationThread::runInternal, AllowCrossThreadAccess(this), src, AllowCrossThreadAccess(dest1), AllowCrossThreadAccess(dest2)))); |
+ m_thread->thread()->postTask(FROM_HERE, new Task(threadSafeBind(&TeeCreationThread<Handle>::runInternal, AllowCrossThreadAccess(this), src, AllowCrossThreadAccess(dest1), AllowCrossThreadAccess(dest2)))); |
m_waitableEvent->wait(); |
} |
Thread* thread() { return m_thread.get(); } |
private: |
- void runInternal(PassOwnPtr<WebDataConsumerHandle> src, OwnPtr<WebDataConsumerHandle>* dest1, OwnPtr<WebDataConsumerHandle>* dest2) |
+ void runInternal(PassOwnPtr<Handle> src, OwnPtr<Handle>* dest1, OwnPtr<Handle>* dest2) |
{ |
DataConsumerTee::create(m_thread->executionContext(), src, dest1, dest2); |
m_waitableEvent->signal(); |
@@ -160,6 +169,31 @@ private: |
OwnPtr<WebWaitableEvent> m_waitableEvent; |
}; |
+// TODO(hiroshige): Merge similar classes into DataConsumerHandleTestUtil.h/cpp. |
+class MockFetchDataConsumerHandle : public FetchDataConsumerHandle { |
+public: |
+ static PassOwnPtr<StrictMock<MockFetchDataConsumerHandle>> create() { return adoptPtr(new StrictMock<MockFetchDataConsumerHandle>); } |
+ MOCK_METHOD1(obtainReaderInternal, Reader*(Client*)); |
+}; |
+ |
+class MockFetchDataConsumerReader : public FetchDataConsumerHandle::Reader { |
+public: |
+ static PassOwnPtr<StrictMock<MockFetchDataConsumerReader>> create() { return adoptPtr(new StrictMock<MockFetchDataConsumerReader>); } |
+ |
+ using Result = WebDataConsumerHandle::Result; |
+ using Flags = WebDataConsumerHandle::Flags; |
+ MOCK_METHOD4(read, Result(void*, size_t, Flags, size_t*)); |
+ MOCK_METHOD3(beginRead, Result(const void**, Flags, size_t*)); |
+ MOCK_METHOD1(endRead, Result(size_t)); |
+ MOCK_METHOD1(drainAsBlobDataHandle, PassRefPtr<BlobDataHandle>(BlobSizePolicy)); |
+ |
+ ~MockFetchDataConsumerReader() override |
+ { |
+ destruct(); |
+ } |
+ MOCK_METHOD0(destruct, void()); |
+}; |
+ |
TEST(DataConsumerTeeTest, CreateDone) |
{ |
OwnPtr<Handle> src(Handle::create()); |
@@ -167,7 +201,7 @@ TEST(DataConsumerTeeTest, CreateDone) |
src->add(Command(Command::Done)); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -200,7 +234,7 @@ TEST(DataConsumerTeeTest, Read) |
src->add(Command(Command::Wait)); |
src->add(Command(Command::Done)); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -234,7 +268,7 @@ TEST(DataConsumerTeeTest, TwoPhaseRead) |
src->add(Command(Command::Wait)); |
src->add(Command(Command::Done)); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -263,7 +297,7 @@ TEST(DataConsumerTeeTest, Error) |
src->add(Command(Command::Data, "world")); |
src->add(Command(Command::Error)); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -293,7 +327,7 @@ TEST(DataConsumerTeeTest, StopSource) |
src->add(Command(Command::Data, "hello, ")); |
src->add(Command(Command::Data, "world")); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -322,7 +356,7 @@ TEST(DataConsumerTeeTest, DetachSource) |
src->add(Command(Command::Data, "hello, ")); |
src->add(Command(Command::Data, "world")); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -350,7 +384,7 @@ TEST(DataConsumerTeeTest, DetachSourceAfterReadingDone) |
src->add(Command(Command::Data, "world")); |
src->add(Command(Command::Done)); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -381,7 +415,7 @@ TEST(DataConsumerTeeTest, DetachOneDestination) |
src->add(Command(Command::Data, "world")); |
src->add(Command(Command::Done)); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -406,7 +440,7 @@ TEST(DataConsumerTeeTest, DetachBothDestinationsShouldStopSourceReader) |
src->add(Command(Command::Data, "hello, ")); |
src->add(Command(Command::Data, "world")); |
- OwnPtr<TeeCreationThread> t = adoptPtr(new TeeCreationThread()); |
+ OwnPtr<TeeCreationThread<WebDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<WebDataConsumerHandle>()); |
t->run(src.release(), &dest1, &dest2); |
ASSERT_TRUE(dest1); |
@@ -420,5 +454,97 @@ TEST(DataConsumerTeeTest, DetachBothDestinationsShouldStopSourceReader) |
context->detached()->wait(); |
} |
+TEST(FetchDataConsumerTeeTest, Create) |
+{ |
+ RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(); |
+ OwnPtr<MockFetchDataConsumerHandle> src(MockFetchDataConsumerHandle::create()); |
+ OwnPtr<MockFetchDataConsumerReader> reader(MockFetchDataConsumerReader::create()); |
+ |
+ Checkpoint checkpoint; |
+ InSequence s; |
+ EXPECT_CALL(checkpoint, Call(1)); |
+ EXPECT_CALL(*src, obtainReaderInternal(_)).WillOnce(Return(reader.get())); |
+ EXPECT_CALL(*reader, drainAsBlobDataHandle(kAllowBlobWithInvalidSize)).WillOnce(Return(blobDataHandle)); |
+ EXPECT_CALL(*reader, destruct()); |
+ EXPECT_CALL(checkpoint, Call(2)); |
+ |
+ // |reader| is adopted by |obtainReader|. |
+ ASSERT_TRUE(reader.leakPtr()); |
+ |
+ OwnPtr<FetchDataConsumerHandle> dest1, dest2; |
+ OwnPtr<TeeCreationThread<FetchDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<FetchDataConsumerHandle>()); |
+ |
+ checkpoint.Call(1); |
+ t->run(src.release(), &dest1, &dest2); |
+ checkpoint.Call(2); |
+ |
+ ASSERT_TRUE(dest1); |
+ ASSERT_TRUE(dest2); |
+ EXPECT_EQ(blobDataHandle, dest1->obtainReader(nullptr)->drainAsBlobDataHandle(kAllowBlobWithInvalidSize)); |
+ EXPECT_EQ(blobDataHandle, dest2->obtainReader(nullptr)->drainAsBlobDataHandle(kAllowBlobWithInvalidSize)); |
+} |
+ |
+TEST(FetchDataConsumerTeeTest, CreateFromBlobWithInvalidSize) |
+{ |
+ RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), -1); |
+ OwnPtr<MockFetchDataConsumerHandle> src(MockFetchDataConsumerHandle::create()); |
+ OwnPtr<MockFetchDataConsumerReader> reader(MockFetchDataConsumerReader::create()); |
+ |
+ Checkpoint checkpoint; |
+ InSequence s; |
+ EXPECT_CALL(checkpoint, Call(1)); |
+ EXPECT_CALL(*src, obtainReaderInternal(_)).WillOnce(Return(reader.get())); |
+ EXPECT_CALL(*reader, drainAsBlobDataHandle(kAllowBlobWithInvalidSize)).WillOnce(Return(blobDataHandle)); |
+ EXPECT_CALL(*reader, destruct()); |
+ EXPECT_CALL(checkpoint, Call(2)); |
+ |
+ // |reader| is adopted by |obtainReader|. |
+ ASSERT_TRUE(reader.leakPtr()); |
+ |
+ OwnPtr<FetchDataConsumerHandle> dest1, dest2; |
+ OwnPtr<TeeCreationThread<FetchDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<FetchDataConsumerHandle>()); |
+ |
+ checkpoint.Call(1); |
+ t->run(src.release(), &dest1, &dest2); |
+ checkpoint.Call(2); |
+ |
+ ASSERT_TRUE(dest1); |
+ ASSERT_TRUE(dest2); |
+ EXPECT_FALSE(dest1->obtainReader(nullptr)->drainAsBlobDataHandle(kDisallowBlobWithInvalidSize)); |
+ EXPECT_EQ(blobDataHandle, dest1->obtainReader(nullptr)->drainAsBlobDataHandle(kAllowBlobWithInvalidSize)); |
+ EXPECT_FALSE(dest2->obtainReader(nullptr)->drainAsBlobDataHandle(kDisallowBlobWithInvalidSize)); |
+ EXPECT_EQ(blobDataHandle, dest2->obtainReader(nullptr)->drainAsBlobDataHandle(kAllowBlobWithInvalidSize)); |
+} |
+ |
+TEST(FetchDataConsumerTeeTest, CreateDone) |
+{ |
+ OwnPtr<Handle> src(Handle::create()); |
+ OwnPtr<FetchDataConsumerHandle> dest1, dest2; |
+ |
+ src->add(Command(Command::Done)); |
+ |
+ OwnPtr<TeeCreationThread<FetchDataConsumerHandle>> t = adoptPtr(new TeeCreationThread<FetchDataConsumerHandle>()); |
+ t->run(createFetchDataConsumerHandleFromWebHandle(src.release()), &dest1, &dest2); |
+ |
+ ASSERT_TRUE(dest1); |
+ ASSERT_TRUE(dest2); |
+ |
+ EXPECT_FALSE(dest1->obtainReader(nullptr)->drainAsBlobDataHandle(kAllowBlobWithInvalidSize)); |
+ EXPECT_FALSE(dest2->obtainReader(nullptr)->drainAsBlobDataHandle(kAllowBlobWithInvalidSize)); |
+ |
+ HandleReader r1, r2; |
+ r1.start(dest1.release()); |
+ r2.start(dest2.release()); |
+ |
+ r1.waitableEvent()->wait(); |
+ r2.waitableEvent()->wait(); |
+ |
+ EXPECT_EQ(kDone, r1.finalResult()); |
+ EXPECT_EQ(String(), r1.readString()); |
+ |
+ EXPECT_EQ(kDone, r2.finalResult()); |
+ EXPECT_EQ(String(), r2.readString()); |
+} |
+ |
} // namespace |
} // namespace blink |