Chromium Code Reviews| Index: third_party/WebKit/Source/modules/fetch/BlobBytesConsumerTest.cpp |
| diff --git a/third_party/WebKit/Source/modules/fetch/BlobBytesConsumerTest.cpp b/third_party/WebKit/Source/modules/fetch/BlobBytesConsumerTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..af1ddabcdcf78aab819438b819aea33b9427881e |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/modules/fetch/BlobBytesConsumerTest.cpp |
| @@ -0,0 +1,438 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "modules/fetch/BlobBytesConsumer.h" |
| + |
| +#include "core/dom/Document.h" |
| +#include "core/loader/ThreadableLoader.h" |
| +#include "core/testing/DummyPageHolder.h" |
| +#include "modules/fetch/BytesConsumerTestUtil.h" |
| +#include "modules/fetch/DataConsumerHandleTestUtil.h" |
| +#include "platform/blob/BlobData.h" |
| +#include "platform/network/EncodedFormData.h" |
| +#include "platform/network/ResourceError.h" |
| +#include "platform/network/ResourceResponse.h" |
| +#include "platform/testing/UnitTestHelpers.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "wtf/Vector.h" |
| +#include "wtf/text/WTFString.h" |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +using Command = DataConsumerHandleTestUtil::Command; |
| +using PublicState = BytesConsumer::PublicState; |
| +using ReplayingHandle = DataConsumerHandleTestUtil::ReplayingHandle; |
| +using Result = BytesConsumer::Result; |
| + |
| +String toString(const Vector<char>& v) |
| +{ |
| + return String(v.data(), v.size()); |
| +} |
| + |
| +class TestThreadableLoader : public ThreadableLoader { |
| +public: |
| + ~TestThreadableLoader() override |
| + { |
| + EXPECT_FALSE(m_shouldBeCancelled && !m_isCancelled) << "The loader should be cancelled but is not cancelled."; |
| + } |
| + |
| + void start(const ResourceRequest& request) override |
| + { |
| + m_isStarted = true; |
| + } |
| + |
| + void overrideTimeout(unsigned long timeoutMilliseconds) override |
| + { |
| + ADD_FAILURE() << "overrideTimeout should not be called."; |
| + } |
| + |
| + void cancel() override |
| + { |
| + m_isCancelled = true; |
| + } |
| + |
| + bool isStarted() const { return m_isStarted; } |
| + bool isCancelled() const { return m_isCancelled; } |
| + void setShouldBeCancelled() { m_shouldBeCancelled = true; } |
| + |
| +private: |
| + bool m_isStarted = false; |
| + bool m_isCancelled = false; |
| + bool m_shouldBeCancelled = false; |
| +}; |
| + |
| +class TestClient final : public GarbageCollectedFinalized<TestClient>, public BytesConsumer::Client { |
| + USING_GARBAGE_COLLECTED_MIXIN(TestClient); |
| +public: |
| + void onStateChange() override { ++m_numOnStateChangeCalled; } |
| + int numOnStateChangeCalled() const { return m_numOnStateChangeCalled; } |
| + |
| +private: |
| + int m_numOnStateChangeCalled = 0; |
| +}; |
| + |
| +class BlobBytesConsumerTest : public ::testing::Test { |
| +public: |
| + BlobBytesConsumerTest() |
| + : m_dummyPageHolder(DummyPageHolder::create(IntSize(1, 1))) {} |
| + |
| + Document& document() { return m_dummyPageHolder->document(); } |
| + |
| +private: |
| + std::unique_ptr<DummyPageHolder> m_dummyPageHolder; |
| +}; |
| + |
| +TEST_F(BlobBytesConsumerTest, Read) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create(); |
| + src->add(Command(Command::Data, "hello, ")); |
| + src->add(Command(Command::Wait)); |
| + src->add(Command(Command::Data, "world")); |
| + src->add(Command(Command::Done)); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle(BytesConsumer::BlobSizePolicy::AllowBlobWithInvalidSize)); |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + consumer->didReceiveResponse(0, ResourceResponse(), std::move(src)); |
| + consumer->didFinishLoading(0, 0); |
| + |
| + auto result = (new BytesConsumerTestUtil::Reader(consumer))->run(); |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ("hello, world", toString(result.second)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, TwoPhaseRead) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create(); |
| + src->add(Command(Command::Data, "hello, ")); |
| + src->add(Command(Command::Wait)); |
| + src->add(Command(Command::Data, "world")); |
| + src->add(Command(Command::Done)); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle(BytesConsumer::BlobSizePolicy::AllowBlobWithInvalidSize)); |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + consumer->didReceiveResponse(0, ResourceResponse(), std::move(src)); |
| + consumer->didFinishLoading(0, 0); |
| + |
| + auto result = (new BytesConsumerTestUtil::TwoPhaseReader(consumer))->run(); |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ("hello, world", toString(result.second)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, FailLoading) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + int numOnStateChangeCalled = client->numOnStateChangeCalled(); |
| + consumer->didFail(ResourceError()); |
| + |
| + EXPECT_EQ(numOnStateChangeCalled + 1, client->numOnStateChangeCalled()); |
| + EXPECT_EQ(PublicState::Errored, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Error, consumer->read(buffer, sizeof(buffer), &read)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, FailLoadingAfterResponseReceived) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + int numOnStateChangeCalled = client->numOnStateChangeCalled(); |
| + consumer->didReceiveResponse(0, ResourceResponse(), createWaitingDataConsumerHandle()); |
| + EXPECT_EQ(numOnStateChangeCalled + 1, client->numOnStateChangeCalled()); |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + consumer->didFail(ResourceError()); |
| + EXPECT_EQ(numOnStateChangeCalled + 2, client->numOnStateChangeCalled()); |
| + EXPECT_EQ(PublicState::Errored, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Error, consumer->read(buffer, sizeof(buffer), &read)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, FailAccessControlCheck) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + int numOnStateChangeCalled = client->numOnStateChangeCalled(); |
| + consumer->didFailAccessControlCheck(ResourceError()); |
| + EXPECT_EQ(numOnStateChangeCalled + 1, client->numOnStateChangeCalled()); |
| + |
| + EXPECT_EQ(PublicState::Errored, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Error, consumer->read(buffer, sizeof(buffer), &read)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, FailRedirectCheck) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + int numOnStateChangeCalled = client->numOnStateChangeCalled(); |
| + consumer->didFailRedirectCheck(); |
| + EXPECT_EQ(numOnStateChangeCalled + 1, client->numOnStateChangeCalled()); |
| + |
| + EXPECT_EQ(Result::Error, consumer->read(buffer, sizeof(buffer), &read)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, CancelBeforeStarting) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + |
| + consumer->cancel(); |
| + // This should be FALSE in production, but TRUE here because we set the |
| + // loader before starting loading in tests. |
| + EXPECT_TRUE(loader->isCancelled()); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(PublicState::Closed, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Done, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_FALSE(loader->isStarted()); |
| + EXPECT_EQ(0, client->numOnStateChangeCalled()); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, CancelAfterStarting) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_EQ(0, client->numOnStateChangeCalled()); |
| + |
| + consumer->cancel(); |
| + EXPECT_TRUE(loader->isCancelled()); |
| + EXPECT_EQ(PublicState::Closed, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Done, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_EQ(0, client->numOnStateChangeCalled()); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, ReadLastChunkBeforeDidFinishLoadingArrives) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create(); |
| + src->add(Command(Command::Data, "hello")); |
| + src->add(Command(Command::Done)); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + char buffer[128]; |
| + size_t read = 0; |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_EQ(0, client->numOnStateChangeCalled()); |
| + |
| + consumer->didReceiveResponse(0, ResourceResponse(), std::move(src)); |
| + EXPECT_EQ(1, client->numOnStateChangeCalled()); |
| + testing::runPendingTasks(); |
| + EXPECT_EQ(2, client->numOnStateChangeCalled()); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Ok, consumer->read(buffer, sizeof(buffer), &read)); |
|
hiroshige
2016/09/13 08:35:44
How about testing |read| and the contents of |buff
yhirano
2016/09/14 07:33:25
Done.
|
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + |
| + consumer->didFinishLoading(0, 0); |
| + EXPECT_EQ(3, client->numOnStateChangeCalled()); |
| + EXPECT_EQ(PublicState::Closed, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Done, consumer->read(buffer, sizeof(buffer), &read)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, ReadLastChunkAfterDidFinishLoadingArrives) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + TestClient* client = new TestClient(); |
| + consumer->setClient(client); |
| + std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create(); |
| + src->add(Command(Command::Data, "hello")); |
| + src->add(Command(Command::Done)); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + char buffer[128]; |
| + size_t read = 0; |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + EXPECT_EQ(0, client->numOnStateChangeCalled()); |
| + |
| + consumer->didReceiveResponse(0, ResourceResponse(), std::move(src)); |
| + EXPECT_EQ(1, client->numOnStateChangeCalled()); |
| + testing::runPendingTasks(); |
| + EXPECT_EQ(2, client->numOnStateChangeCalled()); |
| + |
| + consumer->didFinishLoading(0, 0); |
| + testing::runPendingTasks(); |
| + EXPECT_EQ(2, client->numOnStateChangeCalled()); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Ok, consumer->read(buffer, sizeof(buffer), &read)); |
|
hiroshige
2016/09/13 08:35:44
How about testing |read| and the contents of |buff
yhirano
2016/09/14 07:33:25
Done.
|
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_EQ(Result::Done, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_EQ(2, client->numOnStateChangeCalled()); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, DrainAsBlobDataHandle) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + RefPtr<BlobDataHandle> result = consumer->drainAsBlobDataHandle(BytesConsumer::BlobSizePolicy::DisallowBlobWithInvalidSize); |
| + ASSERT_TRUE(result); |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle(BytesConsumer::BlobSizePolicy::DisallowBlobWithInvalidSize)); |
| + EXPECT_EQ(12345u, result->size()); |
| +} |
| + |
| + |
| +TEST_F(BlobBytesConsumerTest, DrainAsBlobDataHandle_2) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), -1); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + RefPtr<BlobDataHandle> result = consumer->drainAsBlobDataHandle(BytesConsumer::BlobSizePolicy::AllowBlobWithInvalidSize); |
| + ASSERT_TRUE(result); |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle(BytesConsumer::BlobSizePolicy::AllowBlobWithInvalidSize)); |
| + EXPECT_EQ(UINT64_MAX, result->size()); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, DrainAsBlobDataHandle_3) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), -1); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle(BytesConsumer::BlobSizePolicy::DisallowBlobWithInvalidSize)); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, DrainAsFormData) |
| +{ |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + |
| + EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState()); |
| + EXPECT_FALSE(loader->isStarted()); |
| + |
| + RefPtr<EncodedFormData> result = consumer->drainAsFormData(); |
| + ASSERT_TRUE(result); |
| + ASSERT_EQ(1u, result->elements().size()); |
| + ASSERT_EQ(FormDataElement::encodedBlob, result->elements()[0].m_type); |
| + ASSERT_TRUE(result->elements()[0].m_optionalBlobDataHandle); |
| + EXPECT_EQ(12345u, result->elements()[0].m_optionalBlobDataHandle->size()); |
| + EXPECT_EQ(blobDataHandle->uuid(), result->elements()[0].m_blobUUID); |
| +} |
| + |
| +TEST_F(BlobBytesConsumerTest, LoaderShouldBeCancelled) |
| +{ |
| + { |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345); |
| + TestThreadableLoader* loader = new TestThreadableLoader(); |
| + BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader); |
| + |
| + char buffer[3]; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::ShouldWait, consumer->read(buffer, sizeof(buffer), &read)); |
| + EXPECT_TRUE(loader->isStarted()); |
| + loader->setShouldBeCancelled(); |
| + } |
| + ThreadState::current()->collectAllGarbage(); |
| +} |
| + |
| +} // namespace |
| + |
| +} // namespace blink |