blob: 1e9178091feb52335a233df66302de1b43208b23 [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/websockets/WebSocketChannel.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/Document.h"
#include "core/fileapi/Blob.h"
#include "core/testing/DummyPageHolder.h"
#include "modules/websockets/DocumentWebSocketChannel.h"
#include "modules/websockets/WebSocketChannelClient.h"
#include "modules/websockets/WebSocketHandle.h"
#include "modules/websockets/WebSocketHandleClient.h"
#include "platform/heap/Handle.h"
#include "platform/weborigin/KURL.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/PtrUtil.h"
#include "wtf/Vector.h"
#include "wtf/text/WTFString.h"
#include <memory>
#include <stdint.h>
using testing::_;
using testing::InSequence;
using testing::PrintToString;
using testing::AnyNumber;
using testing::SaveArg;
namespace blink {
namespace {
typedef testing::StrictMock<testing::MockFunction<void(int)>> Checkpoint;
class MockWebSocketChannelClient
: public GarbageCollectedFinalized<MockWebSocketChannelClient>,
public WebSocketChannelClient {
USING_GARBAGE_COLLECTED_MIXIN(MockWebSocketChannelClient);
public:
static MockWebSocketChannelClient* create() {
return new testing::StrictMock<MockWebSocketChannelClient>();
}
MockWebSocketChannelClient() {}
~MockWebSocketChannelClient() override {}
MOCK_METHOD2(didConnect, void(const String&, const String&));
MOCK_METHOD1(didReceiveTextMessage, void(const String&));
void didReceiveBinaryMessage(std::unique_ptr<Vector<char>> payload) override {
didReceiveBinaryMessageMock(*payload);
}
MOCK_METHOD1(didReceiveBinaryMessageMock, void(const Vector<char>&));
MOCK_METHOD0(didError, void());
MOCK_METHOD1(didConsumeBufferedAmount, void(uint64_t));
MOCK_METHOD0(didStartClosingHandshake, void());
MOCK_METHOD3(didClose,
void(ClosingHandshakeCompletionStatus,
unsigned short,
const String&));
DEFINE_INLINE_VIRTUAL_TRACE() { WebSocketChannelClient::trace(visitor); }
};
class MockWebSocketHandle : public WebSocketHandle {
public:
static MockWebSocketHandle* create() {
return new testing::StrictMock<MockWebSocketHandle>();
}
MockWebSocketHandle() {}
~MockWebSocketHandle() override {}
MOCK_METHOD1(initialize, void(InterfaceProvider*));
MOCK_METHOD6(connect,
void(const KURL&,
const Vector<String>&,
SecurityOrigin*,
const KURL&,
const String&,
WebSocketHandleClient*));
MOCK_METHOD4(send,
void(bool, WebSocketHandle::MessageType, const char*, size_t));
MOCK_METHOD1(flowControl, void(int64_t));
MOCK_METHOD2(close, void(unsigned short, const String&));
};
class DocumentWebSocketChannelTest : public ::testing::Test {
public:
DocumentWebSocketChannelTest()
: m_pageHolder(DummyPageHolder::create()),
m_channelClient(MockWebSocketChannelClient::create()),
m_handle(MockWebSocketHandle::create()),
m_channel(DocumentWebSocketChannel::create(&m_pageHolder->document(),
m_channelClient.get(),
SourceLocation::capture(),
handle())),
m_sumOfConsumedBufferedAmount(0) {
ON_CALL(*channelClient(), didConsumeBufferedAmount(_))
.WillByDefault(Invoke(
this, &DocumentWebSocketChannelTest::didConsumeBufferedAmount));
}
~DocumentWebSocketChannelTest() { channel()->disconnect(); }
MockWebSocketChannelClient* channelClient() { return m_channelClient.get(); }
WebSocketChannel* channel() {
return static_cast<WebSocketChannel*>(m_channel.get());
}
WebSocketHandleClient* handleClient() {
return static_cast<WebSocketHandleClient*>(m_channel.get());
}
MockWebSocketHandle* handle() { return m_handle; }
void didConsumeBufferedAmount(unsigned long a) {
m_sumOfConsumedBufferedAmount += a;
}
void connect() {
{
InSequence s;
EXPECT_CALL(*handle(), initialize(_));
EXPECT_CALL(*handle(), connect(KURL(KURL(), "ws://localhost/"), _, _, _,
_, handleClient()));
EXPECT_CALL(*handle(), flowControl(65536));
EXPECT_CALL(*channelClient(), didConnect(String("a"), String("b")));
}
EXPECT_TRUE(channel()->connect(KURL(KURL(), "ws://localhost/"), "x"));
handleClient()->didConnect(handle(), String("a"), String("b"));
::testing::Mock::VerifyAndClearExpectations(this);
}
std::unique_ptr<DummyPageHolder> m_pageHolder;
Persistent<MockWebSocketChannelClient> m_channelClient;
MockWebSocketHandle* m_handle;
Persistent<DocumentWebSocketChannel> m_channel;
unsigned long m_sumOfConsumedBufferedAmount;
};
MATCHER_P2(MemEq,
p,
len,
std::string("pointing to memory") + (negation ? " not" : "") +
" equal to \"" +
std::string(p, len) +
"\" (length=" +
PrintToString(len) +
")") {
return memcmp(arg, p, len) == 0;
}
MATCHER_P(KURLEq,
urlString,
std::string(negation ? "doesn't equal" : "equals") + " to \"" +
urlString +
"\"") {
KURL url(KURL(), urlString);
*result_listener << "where the url is \"" << arg.getString().utf8().data()
<< "\"";
return arg == url;
}
TEST_F(DocumentWebSocketChannelTest, connectSuccess) {
Vector<String> protocols;
RefPtr<SecurityOrigin> origin;
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*handle(), initialize(_));
EXPECT_CALL(*handle(),
connect(KURLEq("ws://localhost/"), _, _,
KURLEq("http://example.com/"), _, handleClient()))
.WillOnce(DoAll(SaveArg<1>(&protocols), SaveArg<2>(&origin)));
EXPECT_CALL(*handle(), flowControl(65536));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*channelClient(), didConnect(String("a"), String("b")));
}
KURL pageUrl(KURL(), "http://example.com/");
m_pageHolder->frame().securityContext()->setSecurityOrigin(
SecurityOrigin::create(pageUrl));
Document& document = m_pageHolder->document();
document.setURL(pageUrl);
// Make sure that firstPartyForCookies() is set to the given value.
EXPECT_STREQ("http://example.com/",
document.firstPartyForCookies().getString().utf8().data());
EXPECT_TRUE(channel()->connect(KURL(KURL(), "ws://localhost/"), "x"));
EXPECT_EQ(1U, protocols.size());
EXPECT_STREQ("x", protocols[0].utf8().data());
EXPECT_STREQ("http://example.com", origin->toString().utf8().data());
checkpoint.Call(1);
handleClient()->didConnect(handle(), String("a"), String("b"));
}
TEST_F(DocumentWebSocketChannelTest, sendText) {
connect();
{
InSequence s;
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeText,
MemEq("foo", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeText,
MemEq("bar", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeText,
MemEq("baz", 3), 3));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
channel()->send("foo");
channel()->send("bar");
channel()->send("baz");
EXPECT_EQ(9ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendTextContinuation) {
connect();
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*handle(), send(false, WebSocketHandle::MessageTypeText,
MemEq("0123456789abcdef", 16), 16));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeContinuation,
MemEq("g", 1), 1));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeText,
MemEq("hijk", 4), 4));
EXPECT_CALL(*handle(), send(false, WebSocketHandle::MessageTypeText,
MemEq("lmnopqrstuv", 11), 11));
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(*handle(), send(false, WebSocketHandle::MessageTypeContinuation,
MemEq("wxyzABCDEFGHIJKL", 16), 16));
EXPECT_CALL(checkpoint, Call(3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeContinuation,
MemEq("MNOPQRSTUVWXYZ", 14), 14));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
channel()->send("0123456789abcdefg");
channel()->send("hijk");
channel()->send("lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
checkpoint.Call(1);
handleClient()->didReceiveFlowControl(handle(), 16);
checkpoint.Call(2);
handleClient()->didReceiveFlowControl(handle(), 16);
checkpoint.Call(3);
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_EQ(62ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInVector) {
connect();
{
InSequence s;
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("foo", 3), 3));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
Vector<char> fooVector;
fooVector.append("foo", 3);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(fooVector));
EXPECT_EQ(3ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInVectorWithNullBytes) {
connect();
{
InSequence s;
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\0ar", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("b\0z", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("qu\0", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\0\0\0", 3), 3));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
{
Vector<char> v;
v.append("\0ar", 3);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(v));
}
{
Vector<char> v;
v.append("b\0z", 3);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(v));
}
{
Vector<char> v;
v.append("qu\0", 3);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(v));
}
{
Vector<char> v;
v.append("\0\0\0", 3);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(v));
}
EXPECT_EQ(12ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInVectorNonLatin1UTF8) {
connect();
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\xe7\x8b\x90", 3), 3));
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
Vector<char> v;
v.append("\xe7\x8b\x90", 3);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(v));
EXPECT_EQ(3ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInVectorNonUTF8) {
connect();
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\x80\xff\xe7", 3), 3));
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
Vector<char> v;
v.append("\x80\xff\xe7", 3);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(v));
EXPECT_EQ(3ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest,
sendBinaryInVectorNonLatin1UTF8Continuation) {
connect();
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*handle(), send(false, WebSocketHandle::MessageTypeBinary,
MemEq("\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7"
"\x8b\x90\xe7\x8b\x90\xe7",
16),
16));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeContinuation,
MemEq("\x8b\x90", 2), 2));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
Vector<char> v;
v.append(
"\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b"
"\x90",
18);
channel()->sendBinaryAsCharVector(makeUnique<Vector<char>>(v));
checkpoint.Call(1);
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_EQ(18ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInArrayBuffer) {
connect();
{
InSequence s;
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("foo", 3), 3));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
DOMArrayBuffer* fooBuffer = DOMArrayBuffer::create("foo", 3);
channel()->send(*fooBuffer, 0, 3);
EXPECT_EQ(3ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInArrayBufferPartial) {
connect();
{
InSequence s;
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("foo", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("bar", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("baz", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("a", 1), 1));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
DOMArrayBuffer* foobarBuffer = DOMArrayBuffer::create("foobar", 6);
DOMArrayBuffer* qbazuxBuffer = DOMArrayBuffer::create("qbazux", 6);
channel()->send(*foobarBuffer, 0, 3);
channel()->send(*foobarBuffer, 3, 3);
channel()->send(*qbazuxBuffer, 1, 3);
channel()->send(*qbazuxBuffer, 2, 1);
EXPECT_EQ(10ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInArrayBufferWithNullBytes) {
connect();
{
InSequence s;
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\0ar", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("b\0z", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("qu\0", 3), 3));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\0\0\0", 3), 3));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
{
DOMArrayBuffer* b = DOMArrayBuffer::create("\0ar", 3);
channel()->send(*b, 0, 3);
}
{
DOMArrayBuffer* b = DOMArrayBuffer::create("b\0z", 3);
channel()->send(*b, 0, 3);
}
{
DOMArrayBuffer* b = DOMArrayBuffer::create("qu\0", 3);
channel()->send(*b, 0, 3);
}
{
DOMArrayBuffer* b = DOMArrayBuffer::create("\0\0\0", 3);
channel()->send(*b, 0, 3);
}
EXPECT_EQ(12ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInArrayBufferNonLatin1UTF8) {
connect();
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\xe7\x8b\x90", 3), 3));
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
DOMArrayBuffer* b = DOMArrayBuffer::create("\xe7\x8b\x90", 3);
channel()->send(*b, 0, 3);
EXPECT_EQ(3ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest, sendBinaryInArrayBufferNonUTF8) {
connect();
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeBinary,
MemEq("\x80\xff\xe7", 3), 3));
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
DOMArrayBuffer* b = DOMArrayBuffer::create("\x80\xff\xe7", 3);
channel()->send(*b, 0, 3);
EXPECT_EQ(3ul, m_sumOfConsumedBufferedAmount);
}
TEST_F(DocumentWebSocketChannelTest,
sendBinaryInArrayBufferNonLatin1UTF8Continuation) {
connect();
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*handle(), send(false, WebSocketHandle::MessageTypeBinary,
MemEq("\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7"
"\x8b\x90\xe7\x8b\x90\xe7",
16),
16));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*handle(), send(true, WebSocketHandle::MessageTypeContinuation,
MemEq("\x8b\x90", 2), 2));
}
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_CALL(*channelClient(), didConsumeBufferedAmount(_)).Times(AnyNumber());
DOMArrayBuffer* b = DOMArrayBuffer::create(
"\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b\x90\xe7\x8b"
"\x90",
18);
channel()->send(*b, 0, 18);
checkpoint.Call(1);
handleClient()->didReceiveFlowControl(handle(), 16);
EXPECT_EQ(18ul, m_sumOfConsumedBufferedAmount);
}
// FIXME: Add tests for WebSocketChannel::send(PassRefPtr<BlobDataHandle>)
TEST_F(DocumentWebSocketChannelTest, receiveText) {
connect();
{
InSequence s;
EXPECT_CALL(*channelClient(), didReceiveTextMessage(String("FOO")));
EXPECT_CALL(*channelClient(), didReceiveTextMessage(String("BAR")));
}
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeText, "FOOX", 3);
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeText, "BARX", 3);
}
TEST_F(DocumentWebSocketChannelTest, receiveTextContinuation) {
connect();
EXPECT_CALL(*channelClient(), didReceiveTextMessage(String("BAZ")));
handleClient()->didReceiveData(handle(), false,
WebSocketHandle::MessageTypeText, "BX", 1);
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeContinuation, "AX", 1);
handleClient()->didReceiveData(
handle(), true, WebSocketHandle::MessageTypeContinuation, "ZX", 1);
}
TEST_F(DocumentWebSocketChannelTest, receiveTextNonLatin1) {
connect();
UChar nonLatin1String[] = {0x72d0, 0x0914, 0x0000};
EXPECT_CALL(*channelClient(), didReceiveTextMessage(String(nonLatin1String)));
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeText,
"\xe7\x8b\x90\xe0\xa4\x94", 6);
}
TEST_F(DocumentWebSocketChannelTest, receiveTextNonLatin1Continuation) {
connect();
UChar nonLatin1String[] = {0x72d0, 0x0914, 0x0000};
EXPECT_CALL(*channelClient(), didReceiveTextMessage(String(nonLatin1String)));
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeText, "\xe7\x8b", 2);
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeContinuation, "\x90\xe0", 2);
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeContinuation, "\xa4", 1);
handleClient()->didReceiveData(
handle(), true, WebSocketHandle::MessageTypeContinuation, "\x94", 1);
}
TEST_F(DocumentWebSocketChannelTest, receiveBinary) {
connect();
Vector<char> fooVector;
fooVector.append("FOO", 3);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(fooVector));
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeBinary, "FOOx", 3);
}
TEST_F(DocumentWebSocketChannelTest, receiveBinaryContinuation) {
connect();
Vector<char> bazVector;
bazVector.append("BAZ", 3);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(bazVector));
handleClient()->didReceiveData(handle(), false,
WebSocketHandle::MessageTypeBinary, "Bx", 1);
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeContinuation, "Ax", 1);
handleClient()->didReceiveData(
handle(), true, WebSocketHandle::MessageTypeContinuation, "Zx", 1);
}
TEST_F(DocumentWebSocketChannelTest, receiveBinaryWithNullBytes) {
connect();
{
InSequence s;
{
Vector<char> v;
v.append("\0AR", 3);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(v));
}
{
Vector<char> v;
v.append("B\0Z", 3);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(v));
}
{
Vector<char> v;
v.append("QU\0", 3);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(v));
}
{
Vector<char> v;
v.append("\0\0\0", 3);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(v));
}
}
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeBinary, "\0AR", 3);
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeBinary, "B\0Z", 3);
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeBinary, "QU\0", 3);
handleClient()->didReceiveData(
handle(), true, WebSocketHandle::MessageTypeBinary, "\0\0\0", 3);
}
TEST_F(DocumentWebSocketChannelTest, receiveBinaryNonLatin1UTF8) {
connect();
Vector<char> v;
v.append("\xe7\x8b\x90\xe0\xa4\x94", 6);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(v));
handleClient()->didReceiveData(handle(), true,
WebSocketHandle::MessageTypeBinary,
"\xe7\x8b\x90\xe0\xa4\x94", 6);
}
TEST_F(DocumentWebSocketChannelTest, receiveBinaryNonLatin1UTF8Continuation) {
connect();
Vector<char> v;
v.append("\xe7\x8b\x90\xe0\xa4\x94", 6);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(v));
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeBinary, "\xe7\x8b", 2);
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeContinuation, "\x90\xe0", 2);
handleClient()->didReceiveData(
handle(), false, WebSocketHandle::MessageTypeContinuation, "\xa4", 1);
handleClient()->didReceiveData(
handle(), true, WebSocketHandle::MessageTypeContinuation, "\x94", 1);
}
TEST_F(DocumentWebSocketChannelTest, receiveBinaryNonUTF8) {
connect();
Vector<char> v;
v.append("\x80\xff", 2);
EXPECT_CALL(*channelClient(), didReceiveBinaryMessageMock(v));
handleClient()->didReceiveData(
handle(), true, WebSocketHandle::MessageTypeBinary, "\x80\xff", 2);
}
TEST_F(DocumentWebSocketChannelTest, closeFromBrowser) {
connect();
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*channelClient(), didStartClosingHandshake());
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*handle(), close(WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason")));
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(*channelClient(),
didClose(WebSocketChannelClient::ClosingHandshakeComplete,
WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason")));
EXPECT_CALL(checkpoint, Call(3));
}
handleClient()->didStartClosingHandshake(handle());
checkpoint.Call(1);
channel()->close(WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason"));
checkpoint.Call(2);
handleClient()->didClose(handle(), true,
WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason"));
checkpoint.Call(3);
channel()->disconnect();
}
TEST_F(DocumentWebSocketChannelTest, closeFromWebSocket) {
connect();
Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*handle(), close(WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason")));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*channelClient(),
didClose(WebSocketChannelClient::ClosingHandshakeComplete,
WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason")));
EXPECT_CALL(checkpoint, Call(2));
}
channel()->close(WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason"));
checkpoint.Call(1);
handleClient()->didClose(handle(), true,
WebSocketChannel::CloseEventCodeNormalClosure,
String("close reason"));
checkpoint.Call(2);
channel()->disconnect();
}
TEST_F(DocumentWebSocketChannelTest, failFromBrowser) {
connect();
{
InSequence s;
EXPECT_CALL(*channelClient(), didError());
EXPECT_CALL(
*channelClient(),
didClose(WebSocketChannelClient::ClosingHandshakeIncomplete,
WebSocketChannel::CloseEventCodeAbnormalClosure, String()));
}
handleClient()->didFail(handle(), "fail message");
}
TEST_F(DocumentWebSocketChannelTest, failFromWebSocket) {
connect();
{
InSequence s;
EXPECT_CALL(*channelClient(), didError());
EXPECT_CALL(
*channelClient(),
didClose(WebSocketChannelClient::ClosingHandshakeIncomplete,
WebSocketChannel::CloseEventCodeAbnormalClosure, String()));
}
channel()->fail("fail message from WebSocket", ErrorMessageLevel,
SourceLocation::create(String(), 0, 0, nullptr));
}
} // namespace
} // namespace blink