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

Unified Diff: third_party/WebKit/Source/modules/fetch/BlobBytesConsumerTest.cpp

Issue 2287323002: Implement BlobBytesConsumer (Closed)
Patch Set: fix Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
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..f6950fe7e013c9c0bed6215aa3e78dac88d325cf
--- /dev/null
+++ b/third_party/WebKit/Source/modules/fetch/BlobBytesConsumerTest.cpp
@@ -0,0 +1,532 @@
+// 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 SyncLoadingTestThreadableLoader : public ThreadableLoader {
+public:
+ ~SyncLoadingTestThreadableLoader() override
+ {
+ DCHECK(!m_handle);
+ }
+
+ void start(const ResourceRequest& request) override
+ {
+ m_isStarted = true;
+ m_client->didReceiveResponse(0, ResourceResponse(), std::move(m_handle));
+ m_client->didFinishLoading(0, 0);
+ }
+
+ 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 setClient(ThreadableLoaderClient* client)
+ {
+ m_client = client;
+ }
+
+ void setHandle(std::unique_ptr<WebDataConsumerHandle> handle)
+ {
+ m_handle = std::move(handle);
+ }
+
+private:
+ bool m_isStarted = false;
+ bool m_isCancelled = false;
+ ThreadableLoaderClient* m_client = nullptr;
+ std::unique_ptr<WebDataConsumerHandle> m_handle;
+};
+
+class SyncErrorTestThreadableLoader : public ThreadableLoader {
+public:
+ ~SyncErrorTestThreadableLoader() override {}
+
+ void start(const ResourceRequest& request) override
+ {
+ m_isStarted = true;
+ m_client->didFail(ResourceError());
+ }
+
+ 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 setClient(ThreadableLoaderClient* client)
+ {
+ m_client = client;
+ }
+
+private:
+ bool m_isStarted = false;
+ bool m_isCancelled = false;
+ ThreadableLoaderClient* m_client = nullptr;
+};
+
+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, 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());
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ 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);
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ 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->beginRead(&buffer, &available));
+}
+
+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);
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ 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->beginRead(&buffer, &available));
+ 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->beginRead(&buffer, &available));
+}
+
+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);
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ 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->beginRead(&buffer, &available));
+}
+
+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());
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &available));
+ EXPECT_EQ(PublicState::Closed, consumer->getPublicState());
+ 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);
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ 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->beginRead(&buffer, &available));
+ 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());
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ 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());
+ ASSERT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ ASSERT_EQ(5u, available);
+ EXPECT_EQ("hello", String(buffer, available));
+ ASSERT_EQ(Result::Ok, consumer->endRead(available));
+
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ ASSERT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+
+ consumer->didFinishLoading(0, 0);
+ EXPECT_EQ(3, client->numOnStateChangeCalled());
+ EXPECT_EQ(PublicState::Closed, consumer->getPublicState());
+ ASSERT_EQ(Result::Done, consumer->beginRead(&buffer, &available));
+}
+
+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());
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ 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());
+ ASSERT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ ASSERT_EQ(5u, available);
+ EXPECT_EQ("hello", String(buffer, available));
+ ASSERT_EQ(Result::Ok, consumer->endRead(available));
+
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &available));
+ 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());
+ EXPECT_EQ(PublicState::Closed, consumer->getPublicState());
+ EXPECT_FALSE(loader->isStarted());
+}
+
+
+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());
+ EXPECT_EQ(PublicState::Closed, consumer->getPublicState());
+ EXPECT_FALSE(loader->isStarted());
+}
+
+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));
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_FALSE(loader->isStarted());
+}
+
+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);
+ EXPECT_EQ(PublicState::Closed, consumer->getPublicState());
+ EXPECT_FALSE(loader->isStarted());
+}
+
+TEST_F(BlobBytesConsumerTest, LoaderShouldBeCancelled)
+{
+ {
+ RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345);
+ TestThreadableLoader* loader = new TestThreadableLoader();
+ BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader);
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ EXPECT_TRUE(loader->isStarted());
+ loader->setShouldBeCancelled();
+ }
+ ThreadState::current()->collectAllGarbage();
+}
+
+TEST_F(BlobBytesConsumerTest, SyncErrorDispatch)
+{
+ RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345);
+ SyncErrorTestThreadableLoader* loader = new SyncErrorTestThreadableLoader();
+ BlobBytesConsumer* consumer = BlobBytesConsumer::createForTesting(&document(), blobDataHandle, loader);
+ loader->setClient(consumer);
+ TestClient* client = new TestClient();
+ consumer->setClient(client);
+
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(Result::Error, consumer->beginRead(&buffer, &available));
+ EXPECT_TRUE(loader->isStarted());
+
+ EXPECT_EQ(0, client->numOnStateChangeCalled());
+ EXPECT_EQ(BytesConsumer::PublicState::Errored, consumer->getPublicState());
+}
+
+TEST_F(BlobBytesConsumerTest, SyncLoading)
+{
+ RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(BlobData::create(), 12345);
+ SyncLoadingTestThreadableLoader* loader = new SyncLoadingTestThreadableLoader();
+ 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));
+ loader->setClient(consumer);
+ loader->setHandle(std::move(src));
+ TestClient* client = new TestClient();
+ consumer->setClient(client);
+
+ const char* buffer = nullptr;
+ size_t available;
+ ASSERT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ EXPECT_TRUE(loader->isStarted());
+ ASSERT_EQ(7u, available);
+ EXPECT_EQ("hello, ", String(buffer, available));
+
+ EXPECT_EQ(0, client->numOnStateChangeCalled());
+ EXPECT_EQ(BytesConsumer::PublicState::ReadableOrWaiting, consumer->getPublicState());
+}
+
+TEST_F(BlobBytesConsumerTest, ConstructedFromNullHandle)
+{
+ BlobBytesConsumer* consumer = new BlobBytesConsumer(&document(), nullptr);
+ const char* buffer = nullptr;
+ size_t available;
+ EXPECT_EQ(BytesConsumer::PublicState::Closed, consumer->getPublicState());
+ EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &available));
+}
+
+} // namespace
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698