Chromium Code Reviews| Index: third_party/WebKit/Source/modules/fetch/FormDataBytesConsumerTest.cpp |
| diff --git a/third_party/WebKit/Source/modules/fetch/FormDataBytesConsumerTest.cpp b/third_party/WebKit/Source/modules/fetch/FormDataBytesConsumerTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b44df806cabc41eaec51592a24c04bc8f6231873 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/modules/fetch/FormDataBytesConsumerTest.cpp |
| @@ -0,0 +1,374 @@ |
| +// 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/FormDataBytesConsumer.h" |
| + |
| +#include "core/dom/DOMArrayBuffer.h" |
| +#include "core/dom/DOMTypedArray.h" |
| +#include "core/dom/Document.h" |
| +#include "core/html/FormData.h" |
| +#include "core/testing/DummyPageHolder.h" |
| +#include "modules/fetch/BytesConsumerTestUtil.h" |
| +#include "platform/blob/BlobData.h" |
| +#include "platform/network/EncodedFormData.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "wtf/RefPtr.h" |
| +#include "wtf/Vector.h" |
| +#include "wtf/text/WTFString.h" |
| + |
| +namespace blink { |
| +namespace { |
| + |
| +using Result = BytesConsumer::Result; |
| + |
| +String toString(const Vector<char>& v) |
| +{ |
| + return String(v.data(), v.size()); |
| +} |
| + |
| +PassRefPtr<EncodedFormData> complexFormData() |
| +{ |
| + RefPtr<EncodedFormData> data = EncodedFormData::create(); |
| + |
| + data->appendData("foo", 3); |
| + data->appendFileRange("/foo/bar/baz", 3, 4, 5); |
| + data->appendFileSystemURLRange(KURL(KURL(), "file:///foo/bar/baz"), 6, 7, 8); |
| + std::unique_ptr<BlobData> blobData = BlobData::create(); |
| + blobData->appendText("hello", false); |
| + auto size = blobData->length(); |
| + RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(std::move(blobData), size); |
| + data->appendBlob(blobDataHandle->uuid(), blobDataHandle); |
| + Vector<char> boundary; |
| + boundary.append("\0", 1); |
| + data->setBoundary(boundary); |
| + return data.release(); |
| +} |
| + |
| +class NoopClient final : public GarbageCollectedFinalized<NoopClient>, public BytesConsumer::Client { |
| + USING_GARBAGE_COLLECTED_MIXIN(NoopClient); |
| +public: |
| + void onStateChange() override {} |
| +}; |
| + |
| +class StubBytesConsumer final : public BytesConsumer { |
|
hiroshige
2016/09/15 09:47:33
optional: How about creating a class with gmock an
yhirano
2016/09/16 03:10:32
Done.
|
| +public: |
| + // BytesConsumer implementation |
| + Result beginRead(const char** buffer, size_t* available) override |
| + { |
| + ++m_numBeginReadCalled; |
| + *buffer = nullptr; |
| + *available = 0; |
| + return Result::Ok; |
| + } |
| + Result endRead(size_t readSize) override |
| + { |
| + ++m_numEndReadCalled; |
| + return Result::Ok; |
| + } |
| + void setClient(BytesConsumer::Client* client) override |
| + { |
| + ++m_numSetClientCalled; |
| + } |
| + void clearClient() override |
| + { |
| + ++m_numClearClientCalled; |
| + } |
| + void cancel() override |
| + { |
| + m_isCancelled = true; |
| + } |
| + PublicState getPublicState() const override |
| + { |
| + return PublicState::ReadableOrWaiting; |
| + } |
| + Error getError() const override |
| + { |
| + NOTREACHED(); |
| + return Error(); |
| + } |
| + String debugName() const override |
| + { |
| + return "StubBytesConsumer"; |
| + } |
| + |
| + int numBeginReadCalled() const { return m_numBeginReadCalled; } |
| + int numEndReadCalled() const { return m_numEndReadCalled; } |
| + int numSetClientCalled() const { return m_numSetClientCalled; } |
| + int numClearClientCalled() const { return m_numClearClientCalled; } |
| + bool isCancelled() const { return m_isCancelled; } |
| + |
| +private: |
| + int m_numBeginReadCalled = 0; |
| + int m_numEndReadCalled = 0; |
| + int m_numSetClientCalled = 0; |
| + int m_numClearClientCalled = 0; |
| + bool m_isCancelled = false; |
| +}; |
| + |
| +class FormDataBytesConsumerTest : public ::testing::Test { |
| +public: |
| + FormDataBytesConsumerTest() : m_page(DummyPageHolder::create()) {} |
| + |
| +protected: |
| + Document* getDocument() { return &m_page->document(); } |
| + |
| + std::unique_ptr<DummyPageHolder> m_page; |
| +}; |
| + |
| +TEST_F(FormDataBytesConsumerTest, ReadFromString) |
| +{ |
| + auto result = (new BytesConsumerTestUtil::Reader(new FormDataBytesConsumer("hello, world")))->run(); |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ("hello, world", toString(result.second)); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, TwoPhaseReadFromString) |
| +{ |
| + auto result = (new BytesConsumerTestUtil::TwoPhaseReader(new FormDataBytesConsumer("hello, world")))->run(); |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ("hello, world", toString(result.second)); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, ReadFromStringNonLatin) |
| +{ |
| + constexpr UChar cs[] = {0x3042, 0}; |
| + auto result = (new BytesConsumerTestUtil::Reader(new FormDataBytesConsumer(String(cs))))->run(); |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ("\xe3\x81\x82", toString(result.second)); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, ReadFromArrayBuffer) |
| +{ |
| + constexpr unsigned char data[] = { 0x21, 0xfe, 0x00, 0x00, 0xff, 0xa3, 0x42, 0x30, 0x42, 0x99, 0x88 }; |
| + DOMArrayBuffer* buffer = DOMArrayBuffer::create(data, WTF_ARRAY_LENGTH(data)); |
| + auto result = (new BytesConsumerTestUtil::Reader(new FormDataBytesConsumer(buffer)))->run(); |
| + Vector<char> expected; |
| + expected.append(data, WTF_ARRAY_LENGTH(data)); |
| + |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ(expected, result.second); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, ReadFromArrayBufferView) |
| +{ |
| + constexpr unsigned char data[] = { 0x21, 0xfe, 0x00, 0x00, 0xff, 0xa3, 0x42, 0x30, 0x42, 0x99, 0x88 }; |
| + constexpr size_t offset = 1, size = 4; |
| + DOMArrayBuffer* buffer = DOMArrayBuffer::create(data, WTF_ARRAY_LENGTH(data)); |
| + auto result = (new BytesConsumerTestUtil::Reader(new FormDataBytesConsumer(DOMUint8Array::create(buffer, offset, size))))->run(); |
| + Vector<char> expected; |
| + expected.append(data + offset, size); |
| + |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ(expected, result.second); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, ReadFromSimplFormData) |
|
hiroshige
2016/09/15 09:47:33
nit: s/Simpl/Simple/
yhirano
2016/09/16 03:10:32
Done.
|
| +{ |
| + RefPtr<EncodedFormData> data = EncodedFormData::create(); |
| + data->appendData("foo", 3); |
| + data->appendData("hoge", 4); |
| + |
| + auto result = (new BytesConsumerTestUtil::Reader(new FormDataBytesConsumer(getDocument(), data)))->run(); |
| + EXPECT_EQ(Result::Done, result.first); |
| + EXPECT_EQ("foohoge", toString(result.second)); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, ReadFromComplexFormData) |
| +{ |
| + RefPtr<EncodedFormData> data = complexFormData(); |
| + StubBytesConsumer* underlying = new StubBytesConsumer(); |
| + BytesConsumer* consumer = FormDataBytesConsumer::createForTesting(getDocument(), data, underlying); |
| + |
| + char c; |
| + size_t read = 0; |
| + EXPECT_EQ(Result::Ok, consumer->read(&c, 1, &read)); |
| + EXPECT_EQ(1, underlying->numBeginReadCalled()); |
| + EXPECT_EQ(1, underlying->numEndReadCalled()); |
| + EXPECT_FALSE(underlying->isCancelled()); |
| + EXPECT_EQ(0, underlying->numSetClientCalled()); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, TwoPhaseReadFromComplexFormData) |
| +{ |
| + RefPtr<EncodedFormData> data = complexFormData(); |
| + StubBytesConsumer* underlying = new StubBytesConsumer(); |
| + BytesConsumer* consumer = FormDataBytesConsumer::createForTesting(getDocument(), data, underlying); |
| + |
| + const char* buffer = nullptr; |
| + size_t available = 0; |
| + ASSERT_EQ(Result::Ok, consumer->beginRead(&buffer, &available)); |
| + EXPECT_EQ(1, underlying->numBeginReadCalled()); |
| + EXPECT_EQ(0, underlying->numEndReadCalled()); |
| + |
| + EXPECT_EQ(Result::Ok, consumer->endRead(0)); |
| + EXPECT_EQ(1, underlying->numBeginReadCalled()); |
| + EXPECT_EQ(1, underlying->numEndReadCalled()); |
| + EXPECT_FALSE(underlying->isCancelled()); |
| + EXPECT_EQ(0, underlying->numSetClientCalled()); |
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsBlobDataHandleFromString) |
| +{ |
| + BytesConsumer* consumer = new FormDataBytesConsumer("hello, world"); |
| + RefPtr<BlobDataHandle> blobDataHandle = consumer->drainAsBlobDataHandle(); |
| + ASSERT_TRUE(blobDataHandle); |
| + |
| + EXPECT_EQ(String(), blobDataHandle->type()); |
| + EXPECT_EQ(12u, blobDataHandle->size()); |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
| + char c; |
| + size_t readSize; |
| + EXPECT_EQ(Result::Done, consumer->read(&c, 1, &readSize)); |
|
hiroshige
2016/09/15 09:47:33
Could you also test getPublicState()?
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsBlobDataHandleFromArrayBuffer) |
| +{ |
| + BytesConsumer* consumer = new FormDataBytesConsumer(DOMArrayBuffer::create("foo", 3)); |
| + RefPtr<BlobDataHandle> blobDataHandle = consumer->drainAsBlobDataHandle(); |
| + ASSERT_TRUE(blobDataHandle); |
| + |
| + EXPECT_EQ(String(), blobDataHandle->type()); |
| + EXPECT_EQ(3u, blobDataHandle->size()); |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
| + char c; |
| + size_t readSize; |
| + EXPECT_EQ(Result::Done, consumer->read(&c, 1, &readSize)); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsBlobDataHandleFromSimpleFormData) |
| +{ |
| + FormData* data = FormData::create(UTF8Encoding()); |
| + data->append("name1", "value1"); |
| + data->append("name2", "value2"); |
| + RefPtr<EncodedFormData> inputFormData = data->encodeMultiPartFormData(); |
| + |
| + BytesConsumer* consumer = new FormDataBytesConsumer(getDocument(), inputFormData); |
| + RefPtr<BlobDataHandle> blobDataHandle = consumer->drainAsBlobDataHandle(); |
| + ASSERT_TRUE(blobDataHandle); |
| + |
| + EXPECT_EQ(String(), blobDataHandle->type()); |
| + EXPECT_EQ(inputFormData->flattenToString().utf8().length(), blobDataHandle->size()); |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
| + char c; |
| + size_t readSize; |
| + EXPECT_EQ(Result::Done, consumer->read(&c, 1, &readSize)); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsBlobDataHandleFromComplexFormData) |
| +{ |
| + RefPtr<EncodedFormData> inputFormData = complexFormData(); |
| + |
| + BytesConsumer* consumer = new FormDataBytesConsumer(getDocument(), inputFormData); |
| + RefPtr<BlobDataHandle> blobDataHandle = consumer->drainAsBlobDataHandle(); |
| + ASSERT_TRUE(blobDataHandle); |
| + |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
| + char c; |
| + size_t readSize; |
| + EXPECT_EQ(Result::Done, consumer->read(&c, 1, &readSize)); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsFormDataFromString) |
| +{ |
| + BytesConsumer* consumer = new FormDataBytesConsumer("hello, world"); |
| + RefPtr<EncodedFormData> formData = consumer->drainAsFormData(); |
| + ASSERT_TRUE(formData); |
| + EXPECT_EQ("hello, world", formData->flattenToString()); |
| + |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle()); |
| + const char* buffer = nullptr; |
| + size_t size; |
| + EXPECT_EQ(Result::Done, consumer->read(nullptr, 0, &size)); |
| + EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &size)); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsFormDataFromArrayBuffer) |
| +{ |
| + BytesConsumer* consumer = new FormDataBytesConsumer(DOMArrayBuffer::create("foo", 3)); |
| + RefPtr<EncodedFormData> formData = consumer->drainAsFormData(); |
| + ASSERT_TRUE(formData); |
| + EXPECT_TRUE(formData->isSafeToSendToAnotherThread()); |
| + EXPECT_EQ("foo", formData->flattenToString()); |
| + |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle()); |
| + const char* buffer = nullptr; |
| + size_t size; |
| + EXPECT_EQ(Result::Done, consumer->read(nullptr, 0, &size)); |
| + EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &size)); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsFormDataFromSimpleFormData) |
| +{ |
| + FormData* data = FormData::create(UTF8Encoding()); |
| + data->append("name1", "value1"); |
| + data->append("name2", "value2"); |
| + RefPtr<EncodedFormData> inputFormData = data->encodeMultiPartFormData(); |
| + |
| + BytesConsumer* consumer = new FormDataBytesConsumer(getDocument(), inputFormData); |
| + EXPECT_EQ(inputFormData, consumer->drainAsFormData()); |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle()); |
| + const char* buffer = nullptr; |
| + size_t size; |
| + EXPECT_EQ(Result::Done, consumer->read(nullptr, 0, &size)); |
| + EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &size)); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, DrainAsFormDataFromComplexFormData) |
| +{ |
| + RefPtr<EncodedFormData> inputFormData = complexFormData(); |
| + |
| + BytesConsumer* consumer = new FormDataBytesConsumer(getDocument(), inputFormData); |
| + EXPECT_EQ(inputFormData, consumer->drainAsFormData()); |
| + EXPECT_FALSE(consumer->drainAsBlobDataHandle()); |
| + const char* buffer = nullptr; |
| + size_t size; |
| + EXPECT_EQ(Result::Done, consumer->read(nullptr, 0, &size)); |
| + EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &size)); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, ReadAffectsDraining) |
| +{ |
| + char c; |
| + size_t readSize = 0; |
| + BytesConsumer* consumer = new FormDataBytesConsumer("hello, world"); |
| + EXPECT_EQ(Result::Ok, consumer->read(&c, 0, &readSize)); |
| + EXPECT_EQ(0u, readSize); |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
|
hiroshige
2016/09/15 09:47:33
Could you also test drainAsBlobDataHandle()?
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
| +TEST_F(FormDataBytesConsumerTest, BeginReadAffectsDraining) |
| +{ |
| + const char* buffer = nullptr; |
| + size_t available = 0; |
| + BytesConsumer* consumer = new FormDataBytesConsumer("hello, world"); |
| + ASSERT_EQ(Result::Ok, consumer->beginRead(&buffer, &available)); |
| + EXPECT_EQ("hello, world", String(buffer, available)); |
| + |
| + ASSERT_EQ(Result::Ok, consumer->endRead(0)); |
| + EXPECT_FALSE(consumer->drainAsFormData()); |
|
hiroshige
2016/09/15 09:47:33
ditto.
yhirano
2016/09/16 03:10:32
Done.
|
| +} |
| + |
|
hiroshige
2016/09/15 09:47:33
Could you also test ReadAffectsDraining/BeginReadA
yhirano
2016/09/16 03:10:32
Done.
|
| +TEST_F(FormDataBytesConsumerTest, SetClientWithComplexFormData) |
| +{ |
| + RefPtr<EncodedFormData> inputFormData = complexFormData(); |
| + |
| + StubBytesConsumer* underlying = new StubBytesConsumer(); |
| + BytesConsumer* consumer = FormDataBytesConsumer::createForTesting(getDocument(), inputFormData, underlying); |
| + |
| + EXPECT_EQ(0, underlying->numSetClientCalled()); |
| + EXPECT_EQ(0, underlying->numClearClientCalled()); |
| + |
| + consumer->setClient(new NoopClient()); |
| + |
| + EXPECT_EQ(1, underlying->numSetClientCalled()); |
| + EXPECT_EQ(0, underlying->numClearClientCalled()); |
| + |
| + consumer->clearClient(); |
| + |
| + EXPECT_EQ(1, underlying->numSetClientCalled()); |
| + EXPECT_EQ(1, underlying->numClearClientCalled()); |
| +} |
| + |
| +} // namespace |
| +} // namespace blink |