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

Unified Diff: Source/core/streams/ExclusiveStreamReaderTest.cpp

Issue 837673002: Introduce ExclusiveStreamReader. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « Source/core/streams/ExclusiveStreamReader.idl ('k') | Source/core/streams/ReadableStream.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/streams/ExclusiveStreamReaderTest.cpp
diff --git a/Source/core/streams/ExclusiveStreamReaderTest.cpp b/Source/core/streams/ExclusiveStreamReaderTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..491baf8e99bcc30130bd2a949a483e8cd6a87513
--- /dev/null
+++ b/Source/core/streams/ExclusiveStreamReaderTest.cpp
@@ -0,0 +1,434 @@
+// Copyright 2015 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 "config.h"
+#include "core/streams/ExclusiveStreamReader.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/ToV8.h"
+#include "bindings/core/v8/V8ThrowException.h"
+#include "core/dom/DOMException.h"
+#include "core/dom/Document.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/streams/ReadableStream.h"
+#include "core/streams/ReadableStreamImpl.h"
+#include "core/streams/UnderlyingSource.h"
+#include "core/testing/DummyPageHolder.h"
+#include <gtest/gtest.h>
+
+namespace blink {
+
+using StringStream = ReadableStreamImpl<ReadableStreamChunkTypeTraits<String>>;
+
+namespace {
+
+class StringCapturingFunction final : public ScriptFunction {
+public:
+ static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, String* value)
+ {
+ StringCapturingFunction* self = new StringCapturingFunction(scriptState, value);
+ return self->bindToV8Function();
+ }
+
+private:
+ StringCapturingFunction(ScriptState* scriptState, String* value)
+ : ScriptFunction(scriptState)
+ , m_value(value)
+ {
+ }
+
+ ScriptValue call(ScriptValue value) override
+ {
+ ASSERT(!value.isEmpty());
+ *m_value = toCoreString(value.v8Value()->ToString(scriptState()->isolate()));
+ return value;
+ }
+
+ String* m_value;
+};
+
+class NoopUnderlyingSource final : public GarbageCollectedFinalized<NoopUnderlyingSource>, public UnderlyingSource {
+ USING_GARBAGE_COLLECTED_MIXIN(NoopUnderlyingSource);
+public:
+ ~NoopUnderlyingSource() override { }
+
+ void pullSource() override { }
+ ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) { return ScriptPromise::cast(scriptState, reason); }
+ void trace(Visitor* visitor) override { UnderlyingSource::trace(visitor); }
+};
+
+class PermissiveStrategy final : public StringStream::Strategy {
+public:
+ bool shouldApplyBackpressure(size_t, ReadableStream*) override { return false; }
+};
+
+class ExclusiveStreamReaderTest : public ::testing::Test {
+public:
+ ExclusiveStreamReaderTest()
+ : m_page(DummyPageHolder::create(IntSize(1, 1)))
+ , m_scope(scriptState())
+ , m_exceptionState(ExceptionState::ConstructionContext, "property", "interface", scriptState()->context()->Global(), isolate())
+ , m_stream(new StringStream(scriptState()->executionContext(), new NoopUnderlyingSource, new PermissiveStrategy))
+ {
+ m_stream->didSourceStart();
+ }
+
+ ~ExclusiveStreamReaderTest()
+ {
+ // We need to call |error| in order to make
+ // ActiveDOMObject::hasPendingActivity return false.
+ m_stream->error(DOMException::create(AbortError, "done"));
+ }
+
+ ScriptState* scriptState() { return ScriptState::forMainWorld(m_page->document().frame()); }
+ v8::Isolate* isolate() { return scriptState()->isolate(); }
+
+ v8::Handle<v8::Function> createCaptor(String* value)
+ {
+ return StringCapturingFunction::createFunction(scriptState(), value);
+ }
+
+ OwnPtr<DummyPageHolder> m_page;
+ ScriptState::Scope m_scope;
+ ExceptionState m_exceptionState;
+ Persistent<StringStream> m_stream;
+};
+
+TEST_F(ExclusiveStreamReaderTest, Construct)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+}
+
+TEST_F(ExclusiveStreamReaderTest, Release)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+ reader->releaseLock();
+ EXPECT_FALSE(reader->isActive());
+
+ ExclusiveStreamReader* another = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(another->isActive());
+ EXPECT_FALSE(reader->isActive());
+ reader->releaseLock();
+ EXPECT_TRUE(another->isActive());
+ EXPECT_FALSE(reader->isActive());
+}
+
+TEST_F(ExclusiveStreamReaderTest, MaskState)
+{
+ m_stream->enqueue("hello");
+ EXPECT_EQ("readable", m_stream->stateString());
+
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_EQ("waiting", m_stream->stateString());
+ EXPECT_EQ("readable", reader->state());
+
+ reader->releaseLock();
+ EXPECT_EQ("readable", m_stream->stateString());
+ EXPECT_EQ("closed", reader->state());
+
+ ExclusiveStreamReader* another = new ExclusiveStreamReader(m_stream);
+ EXPECT_EQ("waiting", m_stream->stateString());
+ EXPECT_EQ("closed", reader->state());
+ EXPECT_EQ("readable", another->state());
+}
+
+TEST_F(ExclusiveStreamReaderTest, MaskReady)
+{
+ m_stream->enqueue("hello");
+ isolate()->RunMicrotasks();
+
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ {
+ String s1, s2;
+ reader->ready(scriptState()).then(createCaptor(&s1));
+ m_stream->ready(scriptState()).then(createCaptor(&s2));
+ isolate()->RunMicrotasks();
+ EXPECT_EQ("undefined", s1);
+ EXPECT_TRUE(s2.isNull());
+
+ reader->releaseLock();
+ isolate()->RunMicrotasks();
+ EXPECT_EQ("undefined", s2);
+ }
+
+ {
+ String s1, s2;
+ reader->ready(scriptState()).then(createCaptor(&s1));
+ m_stream->ready(scriptState()).then(createCaptor(&s2));
+ isolate()->RunMicrotasks();
+ EXPECT_EQ("undefined", s1);
+ EXPECT_EQ("undefined", s2);
+ }
+
+ ExclusiveStreamReader* another = new ExclusiveStreamReader(m_stream);
+ {
+ String s1, s2, s3;
+ reader->ready(scriptState()).then(createCaptor(&s1));
+ m_stream->ready(scriptState()).then(createCaptor(&s2));
+ another->ready(scriptState()).then(createCaptor(&s3));
+ isolate()->RunMicrotasks();
+ EXPECT_EQ("undefined", s1);
+ EXPECT_TRUE(s2.isNull());
+ EXPECT_EQ("undefined", s3);
+
+ // We need to call here to ensure all promises having captors are
+ // resolved or rejected.
+ m_stream->error(DOMException::create(AbortError, "done"));
+ isolate()->RunMicrotasks();
+ }
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReaderRead)
+{
+ m_stream->enqueue("hello");
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+
+ EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal());
+ ScriptValue value = reader->read(scriptState(), m_exceptionState);
+
+ EXPECT_FALSE(m_exceptionState.hadException());
+ String stringValue;
+ EXPECT_TRUE(value.toString(stringValue));
+ EXPECT_EQ("hello", stringValue);
+}
+
+TEST_F(ExclusiveStreamReaderTest, StreamReadShouldFailWhenLocked)
+{
+ m_stream->enqueue("hello");
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+
+ EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal());
+ m_stream->read(scriptState(), m_exceptionState);
+
+ EXPECT_TRUE(m_exceptionState.hadException());
+ EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal());
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReaderReadShouldFailWhenNotLocked)
+{
+ m_stream->enqueue("hello");
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ reader->releaseLock();
+ EXPECT_FALSE(reader->isActive());
+
+ EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal());
+ reader->read(scriptState(), m_exceptionState);
+
+ EXPECT_TRUE(m_exceptionState.hadException());
+ EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal());
+}
+
+TEST_F(ExclusiveStreamReaderTest, ClosedReader)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+
+ m_stream->close();
+
+ EXPECT_EQ("closed", m_stream->stateString());
+ EXPECT_EQ("closed", reader->state());
+ EXPECT_FALSE(reader->isActive());
+
+ String onClosedFulfilled, onClosedRejected;
+ String onReadyFulfilled, onReadyRejected;
+ isolate()->RunMicrotasks();
+ reader->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createCaptor(&onClosedRejected));
+ reader->ready(scriptState()).then(createCaptor(&onReadyFulfilled), createCaptor(&onReadyRejected));
+ EXPECT_TRUE(onClosedFulfilled.isNull());
+ EXPECT_TRUE(onClosedRejected.isNull());
+ EXPECT_TRUE(onReadyFulfilled.isNull());
+ EXPECT_TRUE(onReadyRejected.isNull());
+
+ isolate()->RunMicrotasks();
+ EXPECT_EQ("undefined", onClosedFulfilled);
+ EXPECT_TRUE(onClosedRejected.isNull());
+ EXPECT_EQ("undefined", onReadyFulfilled);
+ EXPECT_TRUE(onReadyRejected.isNull());
+}
+
+TEST_F(ExclusiveStreamReaderTest, ErroredReader)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+
+ m_stream->error(DOMException::create(SyntaxError, "some error"));
+
+ EXPECT_EQ("errored", m_stream->stateString());
+ EXPECT_EQ("errored", reader->state());
+ EXPECT_FALSE(reader->isActive());
+
+ String onClosedFulfilled, onClosedRejected;
+ String onReadyFulfilled, onReadyRejected;
+ reader->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createCaptor(&onClosedRejected));
+ reader->ready(scriptState()).then(createCaptor(&onReadyFulfilled), createCaptor(&onReadyRejected));
+ EXPECT_TRUE(onClosedFulfilled.isNull());
+ EXPECT_TRUE(onClosedRejected.isNull());
+ EXPECT_TRUE(onReadyFulfilled.isNull());
+ EXPECT_TRUE(onReadyRejected.isNull());
+
+ isolate()->RunMicrotasks();
+ EXPECT_TRUE(onClosedFulfilled.isNull());
+ EXPECT_EQ("SyntaxError: some error", onClosedRejected);
+ EXPECT_EQ("undefined", onReadyFulfilled);
+ EXPECT_TRUE(onReadyRejected.isNull());
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReadyPromiseShouldNotBeResolvedWhenLocked)
+{
+ String s;
+ ScriptPromise ready = m_stream->ready(scriptState());
+ ready.then(createCaptor(&s));
+ isolate()->RunMicrotasks();
+ EXPECT_TRUE(s.isNull());
+
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+ EXPECT_NE(ready, m_stream->ready(scriptState()));
+
+ isolate()->RunMicrotasks();
+ EXPECT_TRUE(s.isNull());
+
+ // We need to call here to ensure all promises having captors are resolved
+ // or rejected.
+ m_stream->error(DOMException::create(AbortError, "done"));
+ isolate()->RunMicrotasks();
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReaderShouldBeReleasedWhenClosed)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+ m_stream->close();
+ EXPECT_FALSE(reader->isActive());
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReaderShouldBeReleasedWhenCanceled)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+ reader->cancel(scriptState(), ScriptValue(scriptState(), v8::Undefined(isolate())));
+ EXPECT_FALSE(reader->isActive());
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReaderShouldBeReleasedWhenErrored)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+ m_stream->error(DOMException::create(SyntaxError, "some error"));
+ EXPECT_FALSE(reader->isActive());
+}
+
+TEST_F(ExclusiveStreamReaderTest, StreamCancelShouldFailWhenLocked)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ EXPECT_TRUE(reader->isActive());
+ ScriptPromise p = m_stream->cancel(scriptState(), ScriptValue(scriptState(), v8::Undefined(isolate())));
+ EXPECT_EQ(ReadableStream::Waiting, m_stream->stateInternal());
+ String onFulfilled, onRejected;
+ p.then(createCaptor(&onFulfilled), createCaptor(&onRejected));
+
+ EXPECT_TRUE(onFulfilled.isNull());
+ EXPECT_TRUE(onRejected.isNull());
+ isolate()->RunMicrotasks();
+ EXPECT_TRUE(onFulfilled.isNull());
+ EXPECT_EQ("TypeError: this stream is locked to an ExclusiveStreamReader", onRejected);
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReaderCancelShouldNotWorkWhenNotActive)
+{
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+ reader->releaseLock();
+ EXPECT_FALSE(reader->isActive());
+
+ ScriptPromise p = reader->cancel(scriptState(), ScriptValue(scriptState(), v8::Undefined(isolate())));
+ EXPECT_EQ(ReadableStream::Waiting, m_stream->stateInternal());
+ String onFulfilled, onRejected;
+ p.then(createCaptor(&onFulfilled), createCaptor(&onRejected));
+
+ EXPECT_TRUE(onFulfilled.isNull());
+ EXPECT_TRUE(onRejected.isNull());
+ isolate()->RunMicrotasks();
+ EXPECT_EQ("undefined", onFulfilled);
+ EXPECT_TRUE(onRejected.isNull());
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReadyShouldNotBeResolvedWhileLocked)
+{
+ String onFulfilled;
+ m_stream->ready(scriptState()).then(createCaptor(&onFulfilled));
+
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+
+ m_stream->enqueue("hello");
+ m_stream->enqueue("world");
+
+ ASSERT_EQ("readable", reader->state());
+ reader->read(scriptState(), m_exceptionState);
+ ASSERT_EQ("readable", reader->state());
+ reader->read(scriptState(), m_exceptionState);
+ ASSERT_EQ("waiting", reader->state());
+
+ isolate()->RunMicrotasks();
+ EXPECT_TRUE(onFulfilled.isNull());
+
+ // We need to call here to ensure all promises having captors are resolved
+ // or rejected.
+ m_stream->error(DOMException::create(AbortError, "done"));
+ isolate()->RunMicrotasks();
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReadyShouldNotBeResolvedWhenReleasedIfNotReady)
+{
+ String onFulfilled;
+ m_stream->ready(scriptState()).then(createCaptor(&onFulfilled));
+
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+
+ m_stream->enqueue("hello");
+ m_stream->enqueue("world");
+
+ ASSERT_EQ("readable", reader->state());
+ reader->read(scriptState(), m_exceptionState);
+ ASSERT_EQ("readable", reader->state());
+ reader->read(scriptState(), m_exceptionState);
+ ASSERT_EQ("waiting", reader->state());
+
+ reader->releaseLock();
+
+ isolate()->RunMicrotasks();
+ EXPECT_TRUE(onFulfilled.isNull());
+
+ // We need to call here to ensure all promises having captors are resolved
+ // or rejected.
+ m_stream->error(DOMException::create(AbortError, "done"));
+ isolate()->RunMicrotasks();
+}
+
+TEST_F(ExclusiveStreamReaderTest, ReadyShouldBeResolvedWhenReleasedIfReady)
+{
+ String onFulfilled;
+ m_stream->ready(scriptState()).then(createCaptor(&onFulfilled));
+
+ ExclusiveStreamReader* reader = new ExclusiveStreamReader(m_stream);
+
+ m_stream->enqueue("hello");
+ m_stream->enqueue("world");
+
+ ASSERT_EQ("readable", reader->state());
+ reader->read(scriptState(), m_exceptionState);
+ ASSERT_EQ("readable", reader->state());
+
+ isolate()->RunMicrotasks();
+ reader->releaseLock();
+ EXPECT_TRUE(onFulfilled.isNull());
+
+ isolate()->RunMicrotasks();
+ EXPECT_EQ("undefined", onFulfilled);
+}
+
+} // namespace
+
+} // namespace blink
« no previous file with comments | « Source/core/streams/ExclusiveStreamReader.idl ('k') | Source/core/streams/ReadableStream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698