Chromium Code Reviews| Index: Source/modules/websockets/WebSocketTest.cpp |
| diff --git a/Source/modules/websockets/WebSocketTest.cpp b/Source/modules/websockets/WebSocketTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..652a21d424b699da4326e2d4b1084214ab2d8513 |
| --- /dev/null |
| +++ b/Source/modules/websockets/WebSocketTest.cpp |
| @@ -0,0 +1,796 @@ |
| +// 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 "config.h" |
| + |
| +#include "modules/websockets/WebSocket.h" |
| + |
| +#include "bindings/v8/ExceptionState.h" |
| +#include "bindings/v8/V8Binding.h" |
| +#include "core/dom/ExceptionCode.h" |
| +#include "core/fileapi/Blob.h" |
| +#include "core/frame/ConsoleTypes.h" |
| +#include "core/testing/DummyPageHolder.h" |
| +#include "wtf/ArrayBuffer.h" |
| +#include "wtf/OwnPtr.h" |
| +#include "wtf/Uint8Array.h" |
| +#include "wtf/Vector.h" |
| +#include "wtf/testing/WTFTestHelpers.h" |
| + |
| +#include <gmock/gmock.h> |
| +#include <gtest/gtest.h> |
| + |
| +using testing::_; |
| +using testing::InSequence; |
| +using testing::Ref; |
| +using testing::Return; |
| + |
| +namespace WebCore { |
| + |
| +namespace { |
| + |
| +typedef testing::StrictMock<testing::MockFunction<void(int)> > Checkpoint; // NOLINT |
|
tyoshino (SeeGerritForStatus)
2014/05/26 08:17:51
blank line
yhirano
2014/05/26 11:37:51
Done.
|
| +class MockWebSocketChannel : public WebSocketChannel { |
| +public: |
| + static PassRefPtrWillBeRawPtr<MockWebSocketChannel> create() |
| + { |
| + return adoptRefWillBeRefCountedGarbageCollected(new testing::StrictMock<MockWebSocketChannel>()); |
| + } |
| + |
| + virtual ~MockWebSocketChannel() |
| + { |
| + } |
| + |
| + MOCK_METHOD2(connect, bool(const KURL&, const String&)); |
| + MOCK_METHOD0(subprotocol, String()); |
| + MOCK_METHOD0(extensions, String()); |
| + MOCK_METHOD1(send, SendResult(const String&)); |
| + MOCK_METHOD3(send, SendResult(const ArrayBuffer&, unsigned, unsigned)); |
| + MOCK_METHOD1(send, SendResult(PassRefPtr<BlobDataHandle>)); |
| + MOCK_METHOD1(send, SendResult(PassOwnPtr<Vector<char> >)); |
| + MOCK_CONST_METHOD0(bufferedAmount, unsigned long()); |
| + MOCK_METHOD2(close, void(int, const String&)); |
| + MOCK_METHOD4(fail, void(const String&, MessageLevel, const String&, unsigned)); |
| + MOCK_METHOD0(disconnect, void()); |
| + MOCK_METHOD0(suspend, void()); |
| + MOCK_METHOD0(resume, void()); |
| + MOCK_METHOD0(stop, void()); |
| + |
| + MockWebSocketChannel() |
| + { |
| + } |
| +}; |
| + |
| +class WebSocketWithMockChannel : public WebSocket { |
| +public: |
| + static PassRefPtrWillBeRawPtr<WebSocketWithMockChannel> create(ExecutionContext* context) |
| + { |
| + RefPtrWillBeRawPtr<WebSocketWithMockChannel> websocket = adoptRefWillBeRefCountedGarbageCollected(new WebSocketWithMockChannel(context)); |
| + websocket->suspendIfNeeded(); |
| + return websocket; |
| + } |
| + |
| + MockWebSocketChannel* channel() { return m_channel.get(); } |
| + |
| + virtual PassRefPtrWillBeRawPtr<WebSocketChannel> createChannel(ExecutionContext*, WebSocketChannelClient*) OVERRIDE |
| + { |
| + ASSERT(!m_hasCreated); |
| + m_hasCreated = true; |
| + return m_channel; |
| + } |
| + |
| +private: |
| + WebSocketWithMockChannel(ExecutionContext* context) |
| + : WebSocket(context), m_channel(MockWebSocketChannel::create()), m_hasCreated(false) { } |
| + |
| + RefPtrWillBeRawPtr<MockWebSocketChannel> m_channel; |
| + bool m_hasCreated; |
| +}; |
| + |
| +class WebSocketTestBase { |
| +public: |
| + WebSocketTestBase() |
| + : m_pageHolder(DummyPageHolder::create()) |
| + , m_websocket(WebSocketWithMockChannel::create(&m_pageHolder->document())) |
| + , m_executionScope(V8ExecutionScope::create(v8::Isolate::GetCurrent())) |
| + , m_constructionExceptionState(ExceptionState::ConstructionContext, "property", "interface", m_executionScope->scriptState()->context()->Global(), m_executionScope->isolate()) |
| + { |
| + } |
| + |
| + virtual ~WebSocketTestBase() |
| + { |
| + } |
| + |
| + OwnPtr<DummyPageHolder> m_pageHolder; |
| + RefPtrWillBeRawPtr<WebSocketWithMockChannel> m_websocket; |
| + OwnPtr<V8ExecutionScope> m_executionScope; |
| + ExceptionState m_constructionExceptionState; |
| +}; |
| + |
| +class WebSocketTest : public WebSocketTestBase, public ::testing::Test { |
| +public: |
| +}; |
| + |
| +class WebSocketValidClosingCodeTest : public WebSocketTestBase, public ::testing::TestWithParam<unsigned short> { |
| +public: |
| +}; |
| + |
| +class WebSocketInvalidClosingCodeTest : public WebSocketTestBase, public ::testing::TestWithParam<unsigned short> { |
| +public: |
| +}; |
|
tyoshino (SeeGerritForStatus)
2014/05/26 08:17:51
plase see if placing class declaration, the test t
yhirano
2014/05/26 11:37:51
I don't have a strong preference here. Done.
|
| + |
| +TEST_F(WebSocketTest, connectToBadURL) |
| +{ |
| + m_websocket->connect("xxx", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SyntaxError, exceptionState.code()); |
| + EXPECT_EQ("The URL 'xxx' is invalid.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, connectToNonWsURL) |
| +{ |
| + m_websocket->connect("http://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SyntaxError, exceptionState.code()); |
| + EXPECT_EQ("The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, connectToURLHavingFragmentIdentifier) |
| +{ |
| + m_websocket->connect("ws://example.com/#fragment", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SyntaxError, exceptionState.code()); |
| + EXPECT_EQ("The URL contains a fragment identifier ('fragment'). Fragment identifiers are not allowed in WebSocket URLs.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, invalidPort) |
| +{ |
| + m_websocket->connect("ws://example.com:7", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SecurityError, exceptionState.code()); |
| + EXPECT_EQ("The port 7 is not allowed.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +// FIXME: Add a test for Content Security Policy. |
| + |
| +TEST_F(WebSocketTest, invalidSubprotocols) |
| +{ |
| + Vector<String> subprotocols; |
| + subprotocols.append("@subprotocol-|'\"x\x01\x02\x03x"); |
| + |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), disconnect()); |
|
tyoshino (SeeGerritForStatus)
2014/05/26 08:17:51
add an accessor to WebSocketTestBase to get m_webs
yhirano
2014/05/26 11:37:51
Done.
|
| + } |
| + |
| + m_websocket->connect("ws://example.com/", subprotocols, m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SyntaxError, exceptionState.code()); |
| + EXPECT_EQ("The subprotocol '@subprotocol-|'\"x\\u0001\\u0002\\u0003x' is invalid.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, channelConnectSuccess) |
| +{ |
| + Vector<String> subprotocols; |
| + subprotocols.append("aa"); |
| + subprotocols.append("bb"); |
| + |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/hoge"), String("aa, bb"))).WillOnce(Return(true)); |
| + } |
| + |
| + m_websocket->connect("ws://example.com/hoge", Vector<String>(subprotocols), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + EXPECT_EQ(KURL(KURL(), "ws://example.com/hoge"), m_websocket->url()); |
| +} |
| + |
| +TEST_F(WebSocketTest, channelConnectFail) |
| +{ |
| + Vector<String> subprotocols; |
| + subprotocols.append("aa"); |
| + subprotocols.append("bb"); |
| + |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(false)); |
| + EXPECT_CALL(*m_websocket->channel(), disconnect()); |
| + } |
| + |
| + m_websocket->connect("ws://example.com/", Vector<String>(subprotocols), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SecurityError, exceptionState.code()); |
| + EXPECT_EQ("An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, isValidSubprotocolString) |
| +{ |
| + EXPECT_TRUE(WebSocket::isValidSubprotocolString("Helloworld!!")); |
| + EXPECT_FALSE(WebSocket::isValidSubprotocolString("Hello, world!!")); |
| + EXPECT_FALSE(WebSocket::isValidSubprotocolString(String())); |
| + EXPECT_FALSE(WebSocket::isValidSubprotocolString("")); |
| + |
| + const char validCharacters[] = "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~"; |
| + size_t length = strlen(validCharacters); |
| + for (size_t i = 0; i < length; ++i) { |
| + String s; |
| + s.append(static_cast<UChar>(validCharacters[i])); |
| + EXPECT_TRUE(WebSocket::isValidSubprotocolString(s)); |
| + } |
| + for (size_t i = 0; i < 256; ++i) { |
| + if (std::find(validCharacters, validCharacters + length, static_cast<char>(i)) != validCharacters + length) { |
| + continue; |
| + } |
| + String s; |
| + s.append(static_cast<UChar>(i)); |
| + EXPECT_FALSE(WebSocket::isValidSubprotocolString(s)); |
| + } |
| +} |
| + |
| +TEST_F(WebSocketTest, connectSuccess) |
| +{ |
| + Vector<String> subprotocols; |
| + subprotocols.append("aa"); |
| + subprotocols.append("bb"); |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String("bb"))); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String("cc"))); |
| + } |
| + m_websocket->connect("ws://example.com/", subprotocols, m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->didConnect(); |
| + |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| + EXPECT_EQ("bb", m_websocket->protocol()); |
| + EXPECT_EQ("cc", m_websocket->extensions()); |
| +} |
| + |
| +TEST_F(WebSocketTest, didClose) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), disconnect()); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->didClose(0, WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, ""); |
| + |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_P(WebSocketValidClosingCodeTest, test) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), fail(_, _, _, _)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->close(GetParam(), "bye", m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_P(WebSocketInvalidClosingCodeTest, test) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->close(GetParam(), "bye", m_constructionExceptionState); |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(InvalidAccessError, exceptionState.code()); |
| + EXPECT_EQ(String::format("The code must be either 1000, or between 3000 and 4999. %d is neither.", GetParam()), exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| +} |
| + |
| +INSTANTIATE_TEST_CASE_P(WebSocketValidClosingCode, WebSocketValidClosingCodeTest, ::testing::Values(1000, 3000, 3001, 4998, 4999)); |
| +INSTANTIATE_TEST_CASE_P(WebSocketInvalidClosingCode, WebSocketInvalidClosingCodeTest, ::testing::Values(0, 1, 998, 999, 1001, 2999, 5000, 9999, 65535)); |
| + |
| +TEST_F(WebSocketTest, maximumReasonSize) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), fail(_, _, _, _)); |
| + } |
| + String reason; |
| + for (size_t i = 0; i < 123; ++i) |
| + reason.append("a"); |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->close(1000, reason, m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, reasonSizeExceeding) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + } |
| + String reason; |
| + for (size_t i = 0; i < 124; ++i) |
| + reason.append("a"); |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->close(1000, reason, m_constructionExceptionState); |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SyntaxError, exceptionState.code()); |
| + EXPECT_EQ("The message must not be greater than 123 bytes.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, closeWhenConnecting) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), fail(String("WebSocket is closed before the connection is established."), WarningMessageLevel, String(), 0)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->close(1000, "bye", m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, close) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), close(3005, String("bye"))); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->didConnect(); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| + m_websocket->close(3005, "bye", m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, closeWithoutReason) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), close(3005, String())); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->didConnect(); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| + m_websocket->close(3005, m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, closeWithoutCodeAndReason) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), close(-1, String())); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->didConnect(); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| + m_websocket->close(m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, closeWhenClosing) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), close(-1, String())); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->didConnect(); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| + m_websocket->close(m_constructionExceptionState); |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| + |
| + m_websocket->close(m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, closeWhenClosed) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), close(-1, String())); |
| + EXPECT_CALL(*m_websocket->channel(), disconnect()); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| + |
| + m_websocket->didConnect(); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| + m_websocket->close(m_constructionExceptionState); |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| + |
| + m_websocket->didClose(0, WebSocketChannelClient::ClosingHandshakeComplete, 1000, String()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| + m_websocket->close(m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendStringWhenConnecting) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->send("hello", m_constructionExceptionState); |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(InvalidStateError, exceptionState.code()); |
| + EXPECT_EQ("Still in CONNECTING state.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendStringWhenClosing) |
| +{ |
| + Checkpoint checkpoint; |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), fail(_, _, _, _)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->close(m_constructionExceptionState); |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->send("hello", m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendStringWhenClosed) |
| +{ |
| + Checkpoint checkpoint; |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), disconnect()); |
| + EXPECT_CALL(checkpoint, Call(1)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didClose(0, WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, ""); |
| + checkpoint.Call(1); |
| + |
| + m_websocket->send("hello", m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendStringSuccess) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::SendSuccess)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didConnect(); |
| + m_websocket->send("hello", m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendStringFail) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::SendFail)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didConnect(); |
| + m_websocket->send("hello", m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendStringInvalidMessage) |
| +{ |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::InvalidMessage)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didConnect(); |
| + m_websocket->send("hello", m_constructionExceptionState); |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SyntaxError, exceptionState.code()); |
| + EXPECT_EQ("The message contains invalid characters.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendArrayBufferWhenConnecting) |
| +{ |
| + RefPtr<ArrayBufferView> view = Uint8Array::create(8); |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->send(view->buffer().get(), m_constructionExceptionState); |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(InvalidStateError, exceptionState.code()); |
| + EXPECT_EQ("Still in CONNECTING state.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendArrayBufferWhenClosing) |
| +{ |
| + RefPtr<ArrayBufferView> view = Uint8Array::create(8); |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), fail(_, _, _, _)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->close(m_constructionExceptionState); |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->send(view->buffer().get(), m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendArrayBufferWhenClosed) |
| +{ |
| + Checkpoint checkpoint; |
| + RefPtr<ArrayBufferView> view = Uint8Array::create(8); |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), disconnect()); |
| + EXPECT_CALL(checkpoint, Call(1)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didClose(0, WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, ""); |
| + checkpoint.Call(1); |
| + |
| + m_websocket->send(view->buffer().get(), m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendArrayBufferSuccess) |
| +{ |
| + RefPtr<ArrayBufferView> view = Uint8Array::create(8); |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::SendSuccess)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didConnect(); |
| + m_websocket->send(view->buffer().get(), m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendArrayBufferFail) |
| +{ |
| + RefPtr<ArrayBufferView> view = Uint8Array::create(8); |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::SendFail)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didConnect(); |
| + m_websocket->send(view->buffer().get(), m_constructionExceptionState); |
| + |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| +} |
| + |
| +TEST_F(WebSocketTest, sendArrayBufferInvalidMessage) |
| +{ |
| + RefPtr<ArrayBufferView> view = Uint8Array::create(8); |
| + { |
| + InSequence s; |
| + EXPECT_CALL(*m_websocket->channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); |
| + EXPECT_CALL(*m_websocket->channel(), subprotocol()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), extensions()).WillOnce(Return(String())); |
| + EXPECT_CALL(*m_websocket->channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::InvalidMessage)); |
| + } |
| + m_websocket->connect("ws://example.com/", Vector<String>(), m_constructionExceptionState); |
| + const ExceptionState& exceptionState = m_constructionExceptionState; |
| + EXPECT_FALSE(exceptionState.hadException()); |
| + |
| + m_websocket->didConnect(); |
| + m_websocket->send(view->buffer().get(), m_constructionExceptionState); |
| + |
| + EXPECT_TRUE(exceptionState.hadException()); |
| + EXPECT_EQ(SyntaxError, exceptionState.code()); |
| + EXPECT_EQ("The message contains invalid characters.", exceptionState.message()); |
| + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); |
| +} |
| + |
| +// FIXME: We should have Blob tests here. |
| +// We can't create a Blob because the blob registration cannot be mocked yet. |
| + |
| +// FIXME: We should add tests for bufferedAmount. |
| + |
| +// FIXME: We should add tests for data receiving. |
| + |
| +TEST_F(WebSocketTest, binaryType) |
| +{ |
| + EXPECT_EQ("blob", m_websocket->binaryType()); |
| + |
| + m_websocket->setBinaryType("hoge"); |
| + |
| + EXPECT_EQ("blob", m_websocket->binaryType()); |
| + |
| + m_websocket->setBinaryType("arraybuffer"); |
| + |
| + EXPECT_EQ("arraybuffer", m_websocket->binaryType()); |
| + |
| + m_websocket->setBinaryType("fuga"); |
| + |
| + EXPECT_EQ("arraybuffer", m_websocket->binaryType()); |
| + |
| + m_websocket->setBinaryType("blob"); |
| + |
| + EXPECT_EQ("blob", m_websocket->binaryType()); |
| +} |
| + |
| +// FIXME: We should add tests for suspend / resume. |
| + |
| +} // namespace |
| + |
| +} // namespace WebCore |