blob: 5156c3d4a54cad834e89fa3e7d016e606645a10b [file] [log] [blame]
// Copyright 2014 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/BodyStreamBuffer.h"
#include "core/testing/DummyPageHolder.h"
#include "modules/fetch/DataConsumerHandleTestUtil.h"
#include "platform/testing/UnitTestHelpers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/OwnPtr.h"
namespace blink {
namespace {
using ::testing::InSequence;
using ::testing::_;
using ::testing::SaveArg;
using Checkpoint = ::testing::StrictMock<::testing::MockFunction<void(int)>>;
using Command = DataConsumerHandleTestUtil::Command;
using ReplayingHandle = DataConsumerHandleTestUtil::ReplayingHandle;
using MockFetchDataLoaderClient = DataConsumerHandleTestUtil::MockFetchDataLoaderClient;
class BodyStreamBufferTest : public ::testing::Test {
public:
BodyStreamBufferTest()
{
m_page = DummyPageHolder::create(IntSize(1, 1));
}
~BodyStreamBufferTest() override {}
protected:
ScriptState* getScriptState() { return ScriptState::forMainWorld(m_page->document().frame()); }
ExecutionContext* getExecutionContext() { return &m_page->document(); }
OwnPtr<DummyPageHolder> m_page;
};
TEST_F(BodyStreamBufferTest, ReleaseHandle)
{
OwnPtr<FetchDataConsumerHandle> handle = createFetchDataConsumerHandleFromWebHandle(createWaitingDataConsumerHandle());
FetchDataConsumerHandle* rawHandle = handle.get();
BodyStreamBuffer* buffer = new BodyStreamBuffer(handle.release());
EXPECT_FALSE(buffer->hasPendingActivity());
EXPECT_FALSE(buffer->isStreamLocked());
EXPECT_FALSE(buffer->isStreamDisturbed());
EXPECT_TRUE(buffer->isStreamReadable());
OwnPtr<FetchDataConsumerHandle> handle2 = buffer->releaseHandle(getExecutionContext());
ASSERT_EQ(rawHandle, handle2.get());
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_TRUE(buffer->isStreamClosed());
}
TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsArrayBuffer)
{
Checkpoint checkpoint;
MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create();
DOMArrayBuffer* arrayBuffer = nullptr;
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*client, didFetchDataLoadedArrayBufferMock(_)).WillOnce(SaveArg<0>(&arrayBuffer));
EXPECT_CALL(checkpoint, Call(2));
OwnPtr<ReplayingHandle> handle = ReplayingHandle::create();
handle->add(Command(Command::Data, "hello"));
handle->add(Command(Command::Done));
BodyStreamBuffer* buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle.release()));
buffer->startLoading(getExecutionContext(), FetchDataLoader::createLoaderAsArrayBuffer(), client);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_TRUE(buffer->hasPendingActivity());
checkpoint.Call(1);
testing::runPendingTasks();
checkpoint.Call(2);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
ASSERT_TRUE(arrayBuffer);
EXPECT_EQ("hello", String(static_cast<const char*>(arrayBuffer->data()), arrayBuffer->byteLength()));
}
TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsBlob)
{
Checkpoint checkpoint;
MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create();
RefPtr<BlobDataHandle> blobDataHandle;
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*client, didFetchDataLoadedBlobHandleMock(_)).WillOnce(SaveArg<0>(&blobDataHandle));
EXPECT_CALL(checkpoint, Call(2));
OwnPtr<ReplayingHandle> handle = ReplayingHandle::create();
handle->add(Command(Command::Data, "hello"));
handle->add(Command(Command::Done));
BodyStreamBuffer* buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle.release()));
buffer->startLoading(getExecutionContext(), FetchDataLoader::createLoaderAsBlobHandle("text/plain"), client);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_TRUE(buffer->hasPendingActivity());
checkpoint.Call(1);
testing::runPendingTasks();
checkpoint.Call(2);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
EXPECT_EQ(5u, blobDataHandle->size());
}
TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsString)
{
Checkpoint checkpoint;
MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create();
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*client, didFetchDataLoadedString(String("hello")));
EXPECT_CALL(checkpoint, Call(2));
OwnPtr<ReplayingHandle> handle = ReplayingHandle::create();
handle->add(Command(Command::Data, "hello"));
handle->add(Command(Command::Done));
BodyStreamBuffer* buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle.release()));
buffer->startLoading(getExecutionContext(), FetchDataLoader::createLoaderAsString(), client);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_TRUE(buffer->hasPendingActivity());
checkpoint.Call(1);
testing::runPendingTasks();
checkpoint.Call(2);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
}
TEST_F(BodyStreamBufferTest, ReleaseClosedHandle)
{
BodyStreamBuffer* buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle()));
EXPECT_TRUE(buffer->isStreamReadable());
testing::runPendingTasks();
EXPECT_TRUE(buffer->isStreamClosed());
EXPECT_FALSE(buffer->isStreamLocked());
EXPECT_FALSE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
OwnPtr<FetchDataConsumerHandle> handle = buffer->releaseHandle(getExecutionContext());
EXPECT_TRUE(handle);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
}
TEST_F(BodyStreamBufferTest, LoadClosedHandle)
{
Checkpoint checkpoint;
MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create();
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*client, didFetchDataLoadedString(String("")));
EXPECT_CALL(checkpoint, Call(2));
BodyStreamBuffer* buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle()));
EXPECT_TRUE(buffer->isStreamReadable());
testing::runPendingTasks();
EXPECT_TRUE(buffer->isStreamClosed());
EXPECT_FALSE(buffer->isStreamLocked());
EXPECT_FALSE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
buffer->startLoading(getExecutionContext(), FetchDataLoader::createLoaderAsString(), client);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_TRUE(buffer->hasPendingActivity());
checkpoint.Call(1);
testing::runPendingTasks();
checkpoint.Call(2);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
}
TEST_F(BodyStreamBufferTest, ReleaseErroredHandle)
{
BodyStreamBuffer* buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle()));
EXPECT_TRUE(buffer->isStreamReadable());
testing::runPendingTasks();
EXPECT_TRUE(buffer->isStreamErrored());
EXPECT_FALSE(buffer->isStreamLocked());
EXPECT_FALSE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
OwnPtr<FetchDataConsumerHandle> handle = buffer->releaseHandle(getExecutionContext());
EXPECT_TRUE(handle);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
}
TEST_F(BodyStreamBufferTest, LoadErroredHandle)
{
Checkpoint checkpoint;
MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create();
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*client, didFetchDataLoadFailed());
EXPECT_CALL(checkpoint, Call(2));
BodyStreamBuffer* buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle()));
EXPECT_TRUE(buffer->isStreamReadable());
testing::runPendingTasks();
EXPECT_TRUE(buffer->isStreamErrored());
EXPECT_FALSE(buffer->isStreamLocked());
EXPECT_FALSE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
buffer->startLoading(getExecutionContext(), FetchDataLoader::createLoaderAsString(), client);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_TRUE(buffer->hasPendingActivity());
checkpoint.Call(1);
testing::runPendingTasks();
checkpoint.Call(2);
EXPECT_TRUE(buffer->isStreamLocked());
EXPECT_TRUE(buffer->isStreamDisturbed());
EXPECT_FALSE(buffer->hasPendingActivity());
}
TEST_F(BodyStreamBufferTest, LoaderShouldBeKeptAliveByBodyStreamBuffer)
{
Checkpoint checkpoint;
MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create();
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*client, didFetchDataLoadedString(String("hello")));
EXPECT_CALL(checkpoint, Call(2));
OwnPtr<ReplayingHandle> handle = ReplayingHandle::create();
handle->add(Command(Command::Data, "hello"));
handle->add(Command(Command::Done));
Persistent<BodyStreamBuffer> buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle.release()));
buffer->startLoading(getExecutionContext(), FetchDataLoader::createLoaderAsString(), client);
ThreadHeap::collectAllGarbage();
checkpoint.Call(1);
testing::runPendingTasks();
checkpoint.Call(2);
}
// TODO(hiroshige): Merge this class into MockFetchDataConsumerHandle.
class MockFetchDataConsumerHandleWithMockDestructor : public DataConsumerHandleTestUtil::MockFetchDataConsumerHandle {
public:
static PassOwnPtr<::testing::StrictMock<MockFetchDataConsumerHandleWithMockDestructor>> create() { return adoptPtr(new ::testing::StrictMock<MockFetchDataConsumerHandleWithMockDestructor>); }
~MockFetchDataConsumerHandleWithMockDestructor() override
{
destruct();
}
MOCK_METHOD0(destruct, void());
};
TEST_F(BodyStreamBufferTest, SourceHandleAndReaderShouldBeDestructedWhenCanceled)
{
ScriptState::Scope scope(getScriptState());
using MockHandle = MockFetchDataConsumerHandleWithMockDestructor;
using MockReader = DataConsumerHandleTestUtil::MockFetchDataConsumerReader;
OwnPtr<MockHandle> handle = MockHandle::create();
OwnPtr<MockReader> reader = MockReader::create();
Checkpoint checkpoint;
InSequence s;
EXPECT_CALL(*handle, obtainReaderInternal(_)).WillOnce(::testing::Return(reader.get()));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*reader, destruct());
EXPECT_CALL(*handle, destruct());
EXPECT_CALL(checkpoint, Call(2));
// |reader| is adopted by |obtainReader|.
ASSERT_TRUE(reader.leakPtr());
BodyStreamBuffer* buffer = new BodyStreamBuffer(handle.release());
checkpoint.Call(1);
ScriptValue reason(getScriptState(), v8String(getScriptState()->isolate(), "reason"));
buffer->cancelSource(getScriptState(), reason);
checkpoint.Call(2);
}
} // namespace
} // namespace blink