| // 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(wrapUnique(new 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(wrapUnique(new Vector<char>(v))); |
| } |
| { |
| Vector<char> v; |
| v.append("b\0z", 3); |
| channel()->sendBinaryAsCharVector(wrapUnique(new Vector<char>(v))); |
| } |
| { |
| Vector<char> v; |
| v.append("qu\0", 3); |
| channel()->sendBinaryAsCharVector(wrapUnique(new Vector<char>(v))); |
| } |
| { |
| Vector<char> v; |
| v.append("\0\0\0", 3); |
| channel()->sendBinaryAsCharVector(wrapUnique(new 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(wrapUnique(new 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(wrapUnique(new 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(wrapUnique(new 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 |