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

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

Issue 2365853002: Implement ReadableStreamBytesConsumer (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/ReadableStreamBytesConsumerTest.cpp
diff --git a/third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumerTest.cpp b/third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..659531277cced0e3cce96b44e0ee99f3d7ffd39e
--- /dev/null
+++ b/third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumerTest.cpp
@@ -0,0 +1,351 @@
+// 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/ReadableStreamBytesConsumer.h"
+
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/V8BindingMacros.h"
+#include "bindings/core/v8/V8GCController.h"
+#include "core/dom/Document.h"
+#include "core/streams/ReadableStreamOperations.h"
+#include "core/testing/DummyPageHolder.h"
+#include "modules/fetch/BytesConsumerTestUtil.h"
+#include "platform/heap/Handle.h"
+#include "platform/testing/UnitTestHelpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include <memory>
+#include <v8.h>
+
+namespace blink {
+
+namespace {
+
+using ::testing::InSequence;
+using ::testing::StrictMock;
+using Checkpoint = StrictMock<::testing::MockFunction<void(int)>>;
+using Result = BytesConsumer::Result;
+using PublicState = BytesConsumer::PublicState;
+
+class MockClient : public GarbageCollectedFinalized<MockClient>, public BytesConsumer::Client {
hiroshige 2016/09/30 06:35:14 BytesConsumerForDataConsumerHandleTest.cpp also ha
yhirano 2016/09/30 09:01:02 Acknowledged.
+ USING_GARBAGE_COLLECTED_MIXIN(MockClient);
+public:
+ static MockClient* create() { return new StrictMock<MockClient>(); }
+ MOCK_METHOD0(onStateChange, void());
+
+ DEFINE_INLINE_TRACE() {}
+
+protected:
+ MockClient() = default;
+};
+
+class ReadableStreamBytesConsumerTest : public ::testing::Test {
+public:
+ ReadableStreamBytesConsumerTest()
+ : m_page(DummyPageHolder::create())
+ {
+ }
+
+ ScriptState* getScriptState() { return ScriptState::forMainWorld(m_page->document().frame()); }
+ v8::Isolate* isolate() { return getScriptState()->isolate(); }
+
+ v8::MaybeLocal<v8::Value> eval(const char* s)
+ {
+ v8::Local<v8::String> source;
+ v8::Local<v8::Script> script;
+ v8::MicrotasksScope microtasks(isolate(), v8::MicrotasksScope::kDoNotRunMicrotasks);
+ if (!v8Call(v8::String::NewFromUtf8(isolate(), s, v8::NewStringType::kNormal), source)) {
+ ADD_FAILURE();
+ return v8::MaybeLocal<v8::Value>();
+ }
+ if (!v8Call(v8::Script::Compile(getScriptState()->context(), source), script)) {
+ ADD_FAILURE() << "Compilation fails";
+ return v8::MaybeLocal<v8::Value>();
+ }
+ return script->Run(getScriptState()->context());
+ }
+ v8::MaybeLocal<v8::Value> evalWithPrintingError(const char* s)
+ {
+ v8::TryCatch block(isolate());
+ v8::MaybeLocal<v8::Value> r = eval(s);
+ if (block.HasCaught()) {
+ ADD_FAILURE() << toCoreString(block.Exception()->ToString(isolate())).utf8().data();
+ block.ReThrow();
+ }
+ return r;
+ }
+
+ ReadableStreamBytesConsumer* createConsumer(ScriptValue stream)
+ {
+ NonThrowableExceptionState es;
+ ScriptValue reader = ReadableStreamOperations::getReader(getScriptState(), stream, es);
+ DCHECK(!reader.isEmpty());
+ DCHECK(reader.v8Value()->IsObject());
+ return new ReadableStreamBytesConsumer(getScriptState(), reader);
+ }
+
+ void gc() { V8GCController::collectAllGarbageForTesting(isolate()); }
+
+private:
+ std::unique_ptr<DummyPageHolder> m_page;
+};
+
+TEST_F(ReadableStreamBytesConsumerTest, Create)
+{
+ ScriptState::Scope scope(getScriptState());
+ ScriptValue stream(getScriptState(), evalWithPrintingError("new ReadableStream"));
+ ASSERT_FALSE(stream.isEmpty());
+ Persistent<BytesConsumer> consumer = createConsumer(stream);
+
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+}
+
+TEST_F(ReadableStreamBytesConsumerTest, EmptyStream)
+{
+ ScriptState::Scope scope(getScriptState());
+ ScriptValue stream(getScriptState(), evalWithPrintingError(
+ "new ReadableStream({start: c => c.close()})"));
+ ASSERT_FALSE(stream.isEmpty());
+ Persistent<BytesConsumer> consumer = createConsumer(stream);
+ Persistent<MockClient> client = MockClient::create();
+ consumer->setClient(client);
+
+ Checkpoint checkpoint;
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(3));
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ checkpoint.Call(1);
+ testing::runPendingTasks();
+ checkpoint.Call(2);
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:15 Could you add checkpoint.Call() before runPendingT
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(3);
+ EXPECT_EQ(PublicState::Closed, consumer->getPublicState());
+ EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &available));
+}
+
+TEST_F(ReadableStreamBytesConsumerTest, ErroredStream)
+{
+ ScriptState::Scope scope(getScriptState());
+ ScriptValue stream(getScriptState(), evalWithPrintingError(
+ "new ReadableStream({start: c => c.error()})"));
+ ASSERT_FALSE(stream.isEmpty());
+ Persistent<BytesConsumer> consumer = createConsumer(stream);
+ Persistent<MockClient> client = MockClient::create();
+ consumer->setClient(client);
+ Checkpoint checkpoint;
+
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(3));
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ checkpoint.Call(1);
+ testing::runPendingTasks();
+ checkpoint.Call(2);
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:14 ditto.
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(3);
+ EXPECT_EQ(PublicState::Errored, consumer->getPublicState());
+ EXPECT_EQ(Result::Error, consumer->beginRead(&buffer, &available));
+}
+
+TEST_F(ReadableStreamBytesConsumerTest, TwoPhaseRead)
+{
+ ScriptState::Scope scope(getScriptState());
+ ScriptValue stream(getScriptState(), evalWithPrintingError(
+ "var controller;"
+ "var stream = new ReadableStream({start: c => controller = c});"
+ "controller.enqueue(new Uint8Array());"
+ "controller.enqueue(new Uint8Array([0x43, 0x44, 0x45, 0x46]));"
+ "controller.enqueue(new Uint8Array([0x47, 0x48, 0x49, 0x4a]));"
+ "controller.close();"
+ "stream"));
+ ASSERT_FALSE(stream.isEmpty());
+ Persistent<BytesConsumer> consumer = createConsumer(stream);
+ Persistent<MockClient> client = MockClient::create();
+ consumer->setClient(client);
+ Checkpoint checkpoint;
+
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(3));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(4));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(5));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(6));
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ checkpoint.Call(1);
+ testing::runPendingTasks();
+ checkpoint.Call(2);
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
+ checkpoint.Call(3);
+ EXPECT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ ASSERT_EQ(0u, available);
+ EXPECT_EQ(Result::Ok, consumer->endRead(0));
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:14 ditto.
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(4);
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ ASSERT_EQ(4u, available);
+ EXPECT_EQ(0x43, buffer[0]);
+ EXPECT_EQ(0x44, buffer[1]);
+ EXPECT_EQ(0x45, buffer[2]);
+ EXPECT_EQ(0x46, buffer[3]);
+ EXPECT_EQ(Result::Ok, consumer->endRead(0));
+ EXPECT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ ASSERT_EQ(4u, available);
+ EXPECT_EQ(0x43, buffer[0]);
+ EXPECT_EQ(0x44, buffer[1]);
+ EXPECT_EQ(0x45, buffer[2]);
+ EXPECT_EQ(0x46, buffer[3]);
+ EXPECT_EQ(Result::Ok, consumer->endRead(1));
+ EXPECT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ ASSERT_EQ(3u, available);
+ EXPECT_EQ(0x44, buffer[0]);
+ EXPECT_EQ(0x45, buffer[1]);
+ EXPECT_EQ(0x46, buffer[2]);
+ EXPECT_EQ(Result::Ok, consumer->endRead(3));
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:15 ditto.
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(5);
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::Ok, consumer->beginRead(&buffer, &available));
+ ASSERT_EQ(4u, available);
+ EXPECT_EQ(0x47, buffer[0]);
+ EXPECT_EQ(0x48, buffer[1]);
+ EXPECT_EQ(0x49, buffer[2]);
+ EXPECT_EQ(0x4a, buffer[3]);
+ EXPECT_EQ(Result::Ok, consumer->endRead(4));
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:14 ditto.
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(6);
+ EXPECT_EQ(PublicState::Closed, consumer->getPublicState());
+ EXPECT_EQ(Result::Done, consumer->beginRead(&buffer, &available));
+}
+
+TEST_F(ReadableStreamBytesConsumerTest, EnqueueUndefined)
+{
+ ScriptState::Scope scope(getScriptState());
+ ScriptValue stream(getScriptState(), evalWithPrintingError(
+ "var controller;"
+ "var stream = new ReadableStream({start: c => controller = c});"
+ "controller.enqueue(undefined);"
+ "controller.close();"
+ "stream"));
+ ASSERT_FALSE(stream.isEmpty());
+ Persistent<BytesConsumer> consumer = createConsumer(stream);
+ Persistent<MockClient> client = MockClient::create();
+ consumer->setClient(client);
+ Checkpoint checkpoint;
+
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(3));
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ checkpoint.Call(1);
+ testing::runPendingTasks();
+ checkpoint.Call(2);
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:14 ditto.
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(3);
+ EXPECT_EQ(PublicState::Errored, consumer->getPublicState());
+ EXPECT_EQ(Result::Error, consumer->beginRead(&buffer, &available));
+}
+
+TEST_F(ReadableStreamBytesConsumerTest, EnqueueNull)
+{
+ ScriptState::Scope scope(getScriptState());
+ ScriptValue stream(getScriptState(), evalWithPrintingError(
+ "var controller;"
+ "var stream = new ReadableStream({start: c => controller = c});"
+ "controller.enqueue(null);"
+ "controller.close();"
+ "stream"));
+
+ ASSERT_FALSE(stream.isEmpty());
+ Persistent<BytesConsumer> consumer = createConsumer(stream);
+ Persistent<MockClient> client = MockClient::create();
+ consumer->setClient(client);
+ Checkpoint checkpoint;
+
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(3));
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ checkpoint.Call(1);
+ testing::runPendingTasks();
+ checkpoint.Call(2);
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:15 ditto.
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(3);
+ EXPECT_EQ(PublicState::Errored, consumer->getPublicState());
+ EXPECT_EQ(Result::Error, consumer->beginRead(&buffer, &available));
+}
+
+TEST_F(ReadableStreamBytesConsumerTest, EnqueueString)
+{
+ ScriptState::Scope scope(getScriptState());
+ ScriptValue stream(getScriptState(), evalWithPrintingError(
+ "var controller;"
+ "var stream = new ReadableStream({start: c => controller = c});"
+ "controller.enqueue('hello');"
+ "controller.close();"
+ "stream"));
+ ASSERT_FALSE(stream.isEmpty());
+ Persistent<BytesConsumer> consumer = createConsumer(stream);
+ Persistent<MockClient> client = MockClient::create();
+ consumer->setClient(client);
+ Checkpoint checkpoint;
+
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*client, onStateChange());
+ EXPECT_CALL(checkpoint, Call(3));
+
+ const char* buffer = nullptr;
+ size_t available = 0;
+ checkpoint.Call(1);
+ testing::runPendingTasks();
+ checkpoint.Call(2);
+ EXPECT_EQ(PublicState::ReadableOrWaiting, consumer->getPublicState());
+ EXPECT_EQ(Result::ShouldWait, consumer->beginRead(&buffer, &available));
+ testing::runPendingTasks();
hiroshige 2016/09/30 06:35:14 ditto.
yhirano 2016/09/30 09:01:02 Done.
+ checkpoint.Call(3);
+ EXPECT_EQ(PublicState::Errored, consumer->getPublicState());
+ EXPECT_EQ(Result::Error, consumer->beginRead(&buffer, &available));
+}
+
hiroshige 2016/09/30 06:35:14 StreamReaderShouldBeWeak and StreamReaderShouldBeW
yhirano 2016/09/30 09:01:02 Because ReadableStreamBytesConsumer expects that s
hiroshige 2016/09/30 11:46:25 Acknowledged.
+} // namespace
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698