TEST_F(ReadableStreamTest, CloseWhenReadable)
{
    ScriptState::Scope scope(scriptState());
    ExceptionState exceptionState(ExceptionState::ConstructionContext, "property", "interface", scriptState()->context()->Global(), isolate());
    StringStream* stream = construct();

    EXPECT_TRUE(stream->enqueue("hello"));
    EXPECT_TRUE(stream->enqueue("bye"));
    stream->close();
    EXPECT_FALSE(stream->enqueue("should be ignored"));

    EXPECT_EQ(ReadableStream::Readable, stream->stateInternal());
    EXPECT_FALSE(stream->isPulling());
    EXPECT_TRUE(stream->isDraining());

    stream->read(scriptState());

    isolate()->RunMicrotasks();

    EXPECT_EQ(ReadableStream::Readable, stream->stateInternal());
    EXPECT_FALSE(stream->isPulling());
    EXPECT_TRUE(stream->isDraining());

    stream->read(scriptState());

    EXPECT_EQ(ReadableStream::Closed, stream->stateInternal());
    EXPECT_FALSE(stream->isPulling());
    EXPECT_TRUE(stream->isDraining());
}
TEST_F(ReadableStreamTest, CloseWhenErrored)
{
    ScriptState::Scope scope(scriptState());
    ExceptionState exceptionState(ExceptionState::ConstructionContext, "property", "interface", scriptState()->context()->Global(), isolate());
    StringStream* stream = construct();
    EXPECT_EQ(ReadableStream::Readable, stream->stateInternal());

    stream->error(DOMException::create(NotFoundError, "error"));
    stream->close();

    EXPECT_EQ(ReadableStream::Errored, stream->stateInternal());
}
TEST_F(ReadableStreamTest, CloseAndEnqueue)
{
    ScriptState::Scope scope(scriptState());
    ExceptionState exceptionState(ExceptionState::ConstructionContext, "property", "interface", scriptState()->context()->Global(), isolate());
    StringStream* stream = construct();

    stream->close();
    EXPECT_EQ(ReadableStream::Closed, stream->stateInternal());

    bool result = stream->enqueue("hello");
    EXPECT_FALSE(result);
    EXPECT_EQ(ReadableStream::Closed, stream->stateInternal());
}
TEST_F(ReadableStreamTest, GetClosedReader)
{
    ScriptState::Scope scope(scriptState());
    ExceptionState exceptionState(ExceptionState::ConstructionContext, "property", "interface", scriptState()->context()->Global(), isolate());
    StringStream* stream = construct();
    stream->close();
    ReadableStreamReader* reader = stream->getReader(scriptState()->executionContext(), exceptionState);

    ASSERT_TRUE(reader);
    EXPECT_FALSE(exceptionState.hadException());

    String onFulfilled, onRejected;
    reader->closed(scriptState()).then(createCaptor(&onFulfilled), createCaptor(&onRejected));

    EXPECT_FALSE(reader->isActive());
    EXPECT_TRUE(onFulfilled.isNull());
    EXPECT_TRUE(onRejected.isNull());

    isolate()->RunMicrotasks();
    EXPECT_EQ("undefined", onFulfilled);
    EXPECT_TRUE(onRejected.isNull());
}
TEST_F(ReadableStreamTest, CancelWhenClosed)
{
    ScriptState::Scope scope(scriptState());
    ExceptionState exceptionState(ExceptionState::ConstructionContext, "property", "interface", scriptState()->context()->Global(), isolate());
    StringStream* stream = construct();
    String onFulfilled, onRejected;
    stream->close();
    EXPECT_EQ(ReadableStream::Closed, stream->stateInternal());

    EXPECT_FALSE(stream->isDisturbed());
    ScriptPromise promise = stream->cancel(scriptState(), ScriptValue());
    EXPECT_TRUE(stream->isDisturbed());
    EXPECT_EQ(ReadableStream::Closed, stream->stateInternal());

    promise.then(createCaptor(&onFulfilled), createCaptor(&onRejected));
    EXPECT_TRUE(onFulfilled.isNull());
    EXPECT_TRUE(onRejected.isNull());

    isolate()->RunMicrotasks();
    EXPECT_EQ("undefined", onFulfilled);
    EXPECT_TRUE(onRejected.isNull());
}