Home | History | Annotate | Download | only in websockets
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "config.h"
      6 
      7 #include "modules/websockets/WebSocket.h"
      8 
      9 #include "bindings/v8/ExceptionState.h"
     10 #include "bindings/v8/V8Binding.h"
     11 #include "core/dom/ExceptionCode.h"
     12 #include "core/fileapi/Blob.h"
     13 #include "core/frame/ConsoleTypes.h"
     14 #include "core/testing/DummyPageHolder.h"
     15 #include "wtf/ArrayBuffer.h"
     16 #include "wtf/OwnPtr.h"
     17 #include "wtf/Uint8Array.h"
     18 #include "wtf/Vector.h"
     19 #include "wtf/testing/WTFTestHelpers.h"
     20 #include "wtf/text/WTFString.h"
     21 #include <gmock/gmock.h>
     22 #include <gtest/gtest.h>
     23 #include <v8.h>
     24 
     25 using testing::_;
     26 using testing::AnyNumber;
     27 using testing::InSequence;
     28 using testing::Ref;
     29 using testing::Return;
     30 
     31 namespace WebCore {
     32 
     33 namespace {
     34 
     35 typedef testing::StrictMock<testing::MockFunction<void(int)> > Checkpoint;  // NOLINT
     36 
     37 class MockWebSocketChannel : public WebSocketChannel {
     38 public:
     39     static PassRefPtrWillBeRawPtr<MockWebSocketChannel> create()
     40     {
     41         return adoptRefWillBeRefCountedGarbageCollected(new testing::StrictMock<MockWebSocketChannel>());
     42     }
     43 
     44     virtual ~MockWebSocketChannel()
     45     {
     46     }
     47 
     48     MOCK_METHOD2(connect, bool(const KURL&, const String&));
     49     MOCK_METHOD1(send, SendResult(const String&));
     50     MOCK_METHOD3(send, SendResult(const ArrayBuffer&, unsigned, unsigned));
     51     MOCK_METHOD1(send, SendResult(PassRefPtr<BlobDataHandle>));
     52     MOCK_METHOD1(send, SendResult(PassOwnPtr<Vector<char> >));
     53     MOCK_CONST_METHOD0(bufferedAmount, unsigned long());
     54     MOCK_METHOD2(close, void(int, const String&));
     55     MOCK_METHOD4(fail, void(const String&, MessageLevel, const String&, unsigned));
     56     MOCK_METHOD0(disconnect, void());
     57     MOCK_METHOD0(suspend, void());
     58     MOCK_METHOD0(resume, void());
     59 
     60     MockWebSocketChannel()
     61     {
     62     }
     63 };
     64 
     65 class WebSocketWithMockChannel FINAL : public WebSocket {
     66 public:
     67     static PassRefPtrWillBeRawPtr<WebSocketWithMockChannel> create(ExecutionContext* context)
     68     {
     69         RefPtrWillBeRawPtr<WebSocketWithMockChannel> websocket = adoptRefWillBeRefCountedGarbageCollected(new WebSocketWithMockChannel(context));
     70         websocket->suspendIfNeeded();
     71         return websocket.release();
     72     }
     73 
     74     MockWebSocketChannel* channel() { return m_channel.get(); }
     75 
     76     virtual PassRefPtrWillBeRawPtr<WebSocketChannel> createChannel(ExecutionContext*, WebSocketChannelClient*) OVERRIDE
     77     {
     78         ASSERT(!m_hasCreatedChannel);
     79         m_hasCreatedChannel = true;
     80         return m_channel.get();
     81     }
     82 
     83     virtual void trace(Visitor* visitor) OVERRIDE
     84     {
     85         visitor->trace(m_channel);
     86         WebSocket::trace(visitor);
     87     }
     88 
     89 private:
     90     WebSocketWithMockChannel(ExecutionContext* context)
     91         : WebSocket(context)
     92         , m_channel(MockWebSocketChannel::create())
     93         , m_hasCreatedChannel(false) { }
     94 
     95     RefPtrWillBeMember<MockWebSocketChannel> m_channel;
     96     bool m_hasCreatedChannel;
     97 };
     98 
     99 class WebSocketTestBase {
    100 public:
    101     WebSocketTestBase()
    102         : m_pageHolder(DummyPageHolder::create())
    103         , m_websocket(WebSocketWithMockChannel::create(&m_pageHolder->document()))
    104         , m_executionScope(v8::Isolate::GetCurrent())
    105         , m_exceptionState(ExceptionState::ConstructionContext, "property", "interface", m_executionScope.scriptState()->context()->Global(), m_executionScope.isolate())
    106     {
    107     }
    108 
    109     virtual ~WebSocketTestBase()
    110     {
    111         if (!m_websocket)
    112             return;
    113         // These statements are needed to clear WebSocket::m_channel to
    114         // avoid ASSERTION failure on ~WebSocket.
    115         ASSERT(m_websocket->channel());
    116         ::testing::Mock::VerifyAndClear(m_websocket->channel());
    117         EXPECT_CALL(channel(), disconnect()).Times(AnyNumber());
    118 
    119         m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    120         m_websocket.clear();
    121         Heap::collectAllGarbage();
    122     }
    123 
    124     MockWebSocketChannel& channel() { return *m_websocket->channel(); }
    125 
    126     OwnPtr<DummyPageHolder> m_pageHolder;
    127     RefPtrWillBePersistent<WebSocketWithMockChannel> m_websocket;
    128     V8TestingScope m_executionScope;
    129     ExceptionState m_exceptionState;
    130 };
    131 
    132 class WebSocketTest : public WebSocketTestBase, public ::testing::Test {
    133 public:
    134 };
    135 
    136 TEST_F(WebSocketTest, connectToBadURL)
    137 {
    138     m_websocket->connect("xxx", Vector<String>(), m_exceptionState);
    139 
    140 
    141     EXPECT_TRUE(m_exceptionState.hadException());
    142     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    143     EXPECT_EQ("The URL 'xxx' is invalid.", m_exceptionState.message());
    144     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    145 }
    146 
    147 TEST_F(WebSocketTest, connectToNonWsURL)
    148 {
    149     m_websocket->connect("http://example.com/", Vector<String>(), m_exceptionState);
    150 
    151 
    152     EXPECT_TRUE(m_exceptionState.hadException());
    153     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    154     EXPECT_EQ("The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.", m_exceptionState.message());
    155     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    156 }
    157 
    158 TEST_F(WebSocketTest, connectToURLHavingFragmentIdentifier)
    159 {
    160     m_websocket->connect("ws://example.com/#fragment", Vector<String>(), m_exceptionState);
    161 
    162 
    163     EXPECT_TRUE(m_exceptionState.hadException());
    164     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    165     EXPECT_EQ("The URL contains a fragment identifier ('fragment'). Fragment identifiers are not allowed in WebSocket URLs.", m_exceptionState.message());
    166     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    167 }
    168 
    169 TEST_F(WebSocketTest, invalidPort)
    170 {
    171     m_websocket->connect("ws://example.com:7", Vector<String>(), m_exceptionState);
    172 
    173 
    174     EXPECT_TRUE(m_exceptionState.hadException());
    175     EXPECT_EQ(SecurityError, m_exceptionState.code());
    176     EXPECT_EQ("The port 7 is not allowed.", m_exceptionState.message());
    177     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    178 }
    179 
    180 // FIXME: Add a test for Content Security Policy.
    181 
    182 TEST_F(WebSocketTest, invalidSubprotocols)
    183 {
    184     Vector<String> subprotocols;
    185     subprotocols.append("@subprotocol-|'\"x\x01\x02\x03x");
    186 
    187     {
    188         InSequence s;
    189         EXPECT_CALL(channel(), disconnect());
    190     }
    191 
    192     m_websocket->connect("ws://example.com/", subprotocols, m_exceptionState);
    193 
    194     EXPECT_TRUE(m_exceptionState.hadException());
    195     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    196     EXPECT_EQ("The subprotocol '@subprotocol-|'\"x\\u0001\\u0002\\u0003x' is invalid.", m_exceptionState.message());
    197     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    198 }
    199 
    200 TEST_F(WebSocketTest, channelConnectSuccess)
    201 {
    202     Vector<String> subprotocols;
    203     subprotocols.append("aa");
    204     subprotocols.append("bb");
    205 
    206     {
    207         InSequence s;
    208         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/hoge"), String("aa, bb"))).WillOnce(Return(true));
    209     }
    210 
    211     m_websocket->connect("ws://example.com/hoge", Vector<String>(subprotocols), m_exceptionState);
    212 
    213 
    214     EXPECT_FALSE(m_exceptionState.hadException());
    215     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    216     EXPECT_EQ(KURL(KURL(), "ws://example.com/hoge"), m_websocket->url());
    217 }
    218 
    219 TEST_F(WebSocketTest, channelConnectFail)
    220 {
    221     Vector<String> subprotocols;
    222     subprotocols.append("aa");
    223     subprotocols.append("bb");
    224 
    225     {
    226         InSequence s;
    227         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(false));
    228         EXPECT_CALL(channel(), disconnect());
    229     }
    230 
    231     m_websocket->connect("ws://example.com/", Vector<String>(subprotocols), m_exceptionState);
    232 
    233 
    234     EXPECT_TRUE(m_exceptionState.hadException());
    235     EXPECT_EQ(SecurityError, m_exceptionState.code());
    236     EXPECT_EQ("An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.", m_exceptionState.message());
    237     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    238 }
    239 
    240 TEST_F(WebSocketTest, isValidSubprotocolString)
    241 {
    242     EXPECT_TRUE(WebSocket::isValidSubprotocolString("Helloworld!!"));
    243     EXPECT_FALSE(WebSocket::isValidSubprotocolString("Hello, world!!"));
    244     EXPECT_FALSE(WebSocket::isValidSubprotocolString(String()));
    245     EXPECT_FALSE(WebSocket::isValidSubprotocolString(""));
    246 
    247     const char validCharacters[] = "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~";
    248     size_t length = strlen(validCharacters);
    249     for (size_t i = 0; i < length; ++i) {
    250         String s;
    251         s.append(static_cast<UChar>(validCharacters[i]));
    252         EXPECT_TRUE(WebSocket::isValidSubprotocolString(s));
    253     }
    254     for (size_t i = 0; i < 256; ++i) {
    255         if (std::find(validCharacters, validCharacters + length, static_cast<char>(i)) != validCharacters + length) {
    256             continue;
    257         }
    258         String s;
    259         s.append(static_cast<UChar>(i));
    260         EXPECT_FALSE(WebSocket::isValidSubprotocolString(s));
    261     }
    262 }
    263 
    264 TEST_F(WebSocketTest, connectSuccess)
    265 {
    266     Vector<String> subprotocols;
    267     subprotocols.append("aa");
    268     subprotocols.append("bb");
    269     {
    270         InSequence s;
    271         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(true));
    272     }
    273     m_websocket->connect("ws://example.com/", subprotocols, m_exceptionState);
    274 
    275     EXPECT_FALSE(m_exceptionState.hadException());
    276     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    277 
    278     m_websocket->didConnect("bb", "cc");
    279 
    280     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    281     EXPECT_EQ("bb", m_websocket->protocol());
    282     EXPECT_EQ("cc", m_websocket->extensions());
    283 }
    284 
    285 TEST_F(WebSocketTest, didClose)
    286 {
    287     {
    288         InSequence s;
    289         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    290         EXPECT_CALL(channel(), disconnect());
    291     }
    292     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    293 
    294     EXPECT_FALSE(m_exceptionState.hadException());
    295     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    296 
    297     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    298 
    299     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    300 }
    301 
    302 TEST_F(WebSocketTest, maximumReasonSize)
    303 {
    304     {
    305         InSequence s;
    306         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    307         EXPECT_CALL(channel(), fail(_, _, _, _));
    308     }
    309     String reason;
    310     for (size_t i = 0; i < 123; ++i)
    311         reason.append("a");
    312     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    313 
    314     EXPECT_FALSE(m_exceptionState.hadException());
    315     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    316 
    317     m_websocket->close(1000, reason, m_exceptionState);
    318 
    319     EXPECT_FALSE(m_exceptionState.hadException());
    320     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    321 }
    322 
    323 TEST_F(WebSocketTest, reasonSizeExceeding)
    324 {
    325     {
    326         InSequence s;
    327         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    328     }
    329     String reason;
    330     for (size_t i = 0; i < 124; ++i)
    331         reason.append("a");
    332     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    333 
    334     EXPECT_FALSE(m_exceptionState.hadException());
    335     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    336 
    337     m_websocket->close(1000, reason, m_exceptionState);
    338 
    339     EXPECT_TRUE(m_exceptionState.hadException());
    340     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    341     EXPECT_EQ("The message must not be greater than 123 bytes.", m_exceptionState.message());
    342     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    343 }
    344 
    345 TEST_F(WebSocketTest, closeWhenConnecting)
    346 {
    347     {
    348         InSequence s;
    349         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    350         EXPECT_CALL(channel(), fail(String("WebSocket is closed before the connection is established."), WarningMessageLevel, String(), 0));
    351     }
    352     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    353 
    354     EXPECT_FALSE(m_exceptionState.hadException());
    355     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    356 
    357     m_websocket->close(1000, "bye", m_exceptionState);
    358 
    359     EXPECT_FALSE(m_exceptionState.hadException());
    360     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    361 }
    362 
    363 TEST_F(WebSocketTest, close)
    364 {
    365     {
    366         InSequence s;
    367         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    368         EXPECT_CALL(channel(), close(3005, String("bye")));
    369     }
    370     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    371 
    372     EXPECT_FALSE(m_exceptionState.hadException());
    373     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    374 
    375     m_websocket->didConnect("", "");
    376     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    377     m_websocket->close(3005, "bye", m_exceptionState);
    378 
    379     EXPECT_FALSE(m_exceptionState.hadException());
    380     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    381 }
    382 
    383 TEST_F(WebSocketTest, closeWithoutReason)
    384 {
    385     {
    386         InSequence s;
    387         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    388         EXPECT_CALL(channel(), close(3005, String()));
    389     }
    390     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    391 
    392     EXPECT_FALSE(m_exceptionState.hadException());
    393     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    394 
    395     m_websocket->didConnect("", "");
    396     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    397     m_websocket->close(3005, m_exceptionState);
    398 
    399     EXPECT_FALSE(m_exceptionState.hadException());
    400     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    401 }
    402 
    403 TEST_F(WebSocketTest, closeWithoutCodeAndReason)
    404 {
    405     {
    406         InSequence s;
    407         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    408         EXPECT_CALL(channel(), close(-1, String()));
    409     }
    410     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    411 
    412     EXPECT_FALSE(m_exceptionState.hadException());
    413     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    414 
    415     m_websocket->didConnect("", "");
    416     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    417     m_websocket->close(m_exceptionState);
    418 
    419     EXPECT_FALSE(m_exceptionState.hadException());
    420     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    421 }
    422 
    423 TEST_F(WebSocketTest, closeWhenClosing)
    424 {
    425     {
    426         InSequence s;
    427         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    428         EXPECT_CALL(channel(), close(-1, String()));
    429     }
    430     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    431 
    432     EXPECT_FALSE(m_exceptionState.hadException());
    433     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    434 
    435     m_websocket->didConnect("", "");
    436     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    437     m_websocket->close(m_exceptionState);
    438     EXPECT_FALSE(m_exceptionState.hadException());
    439     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    440 
    441     m_websocket->close(m_exceptionState);
    442 
    443     EXPECT_FALSE(m_exceptionState.hadException());
    444     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    445 }
    446 
    447 TEST_F(WebSocketTest, closeWhenClosed)
    448 {
    449     {
    450         InSequence s;
    451         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    452         EXPECT_CALL(channel(), close(-1, String()));
    453         EXPECT_CALL(channel(), disconnect());
    454     }
    455     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    456 
    457     EXPECT_FALSE(m_exceptionState.hadException());
    458     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    459 
    460     m_websocket->didConnect("", "");
    461     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    462     m_websocket->close(m_exceptionState);
    463     EXPECT_FALSE(m_exceptionState.hadException());
    464     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    465 
    466     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeComplete, 1000, String());
    467     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    468     m_websocket->close(m_exceptionState);
    469 
    470     EXPECT_FALSE(m_exceptionState.hadException());
    471     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    472 }
    473 
    474 TEST_F(WebSocketTest, sendStringWhenConnecting)
    475 {
    476     {
    477         InSequence s;
    478         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    479     }
    480     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    481 
    482     EXPECT_FALSE(m_exceptionState.hadException());
    483 
    484     m_websocket->send("hello", m_exceptionState);
    485 
    486     EXPECT_TRUE(m_exceptionState.hadException());
    487     EXPECT_EQ(InvalidStateError, m_exceptionState.code());
    488     EXPECT_EQ("Still in CONNECTING state.", m_exceptionState.message());
    489     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    490 }
    491 
    492 TEST_F(WebSocketTest, sendStringWhenClosing)
    493 {
    494     Checkpoint checkpoint;
    495     {
    496         InSequence s;
    497         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    498         EXPECT_CALL(channel(), fail(_, _, _, _));
    499     }
    500     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    501 
    502     EXPECT_FALSE(m_exceptionState.hadException());
    503 
    504     m_websocket->close(m_exceptionState);
    505     EXPECT_FALSE(m_exceptionState.hadException());
    506 
    507     m_websocket->send("hello", m_exceptionState);
    508 
    509     EXPECT_FALSE(m_exceptionState.hadException());
    510     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    511 }
    512 
    513 TEST_F(WebSocketTest, sendStringWhenClosed)
    514 {
    515     Checkpoint checkpoint;
    516     {
    517         InSequence s;
    518         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    519         EXPECT_CALL(channel(), disconnect());
    520         EXPECT_CALL(checkpoint, Call(1));
    521     }
    522     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    523 
    524     EXPECT_FALSE(m_exceptionState.hadException());
    525 
    526     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    527     checkpoint.Call(1);
    528 
    529     m_websocket->send("hello", m_exceptionState);
    530 
    531     EXPECT_FALSE(m_exceptionState.hadException());
    532     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    533 }
    534 
    535 TEST_F(WebSocketTest, sendStringSuccess)
    536 {
    537     {
    538         InSequence s;
    539         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    540         EXPECT_CALL(channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::SendSuccess));
    541     }
    542     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    543 
    544     EXPECT_FALSE(m_exceptionState.hadException());
    545 
    546     m_websocket->didConnect("", "");
    547     m_websocket->send("hello", m_exceptionState);
    548 
    549     EXPECT_FALSE(m_exceptionState.hadException());
    550     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    551 }
    552 
    553 TEST_F(WebSocketTest, sendStringFail)
    554 {
    555     {
    556         InSequence s;
    557         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    558         EXPECT_CALL(channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::SendFail));
    559     }
    560     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    561 
    562     EXPECT_FALSE(m_exceptionState.hadException());
    563 
    564     m_websocket->didConnect("", "");
    565     m_websocket->send("hello", m_exceptionState);
    566 
    567     EXPECT_FALSE(m_exceptionState.hadException());
    568     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    569 }
    570 
    571 TEST_F(WebSocketTest, sendStringInvalidMessage)
    572 {
    573     {
    574         InSequence s;
    575         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    576         EXPECT_CALL(channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::InvalidMessage));
    577     }
    578     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    579 
    580     EXPECT_FALSE(m_exceptionState.hadException());
    581 
    582     m_websocket->didConnect("", "");
    583     m_websocket->send("hello", m_exceptionState);
    584 
    585     EXPECT_TRUE(m_exceptionState.hadException());
    586     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    587     EXPECT_EQ("The message contains invalid characters.", m_exceptionState.message());
    588     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    589 }
    590 
    591 TEST_F(WebSocketTest, sendArrayBufferWhenConnecting)
    592 {
    593     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    594     {
    595         InSequence s;
    596         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    597     }
    598     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    599 
    600     EXPECT_FALSE(m_exceptionState.hadException());
    601 
    602     m_websocket->send(view->buffer().get(), m_exceptionState);
    603 
    604     EXPECT_TRUE(m_exceptionState.hadException());
    605     EXPECT_EQ(InvalidStateError, m_exceptionState.code());
    606     EXPECT_EQ("Still in CONNECTING state.", m_exceptionState.message());
    607     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    608 }
    609 
    610 TEST_F(WebSocketTest, sendArrayBufferWhenClosing)
    611 {
    612     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    613     {
    614         InSequence s;
    615         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    616         EXPECT_CALL(channel(), fail(_, _, _, _));
    617     }
    618     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    619 
    620     EXPECT_FALSE(m_exceptionState.hadException());
    621 
    622     m_websocket->close(m_exceptionState);
    623     EXPECT_FALSE(m_exceptionState.hadException());
    624 
    625     m_websocket->send(view->buffer().get(), m_exceptionState);
    626 
    627     EXPECT_FALSE(m_exceptionState.hadException());
    628     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    629 }
    630 
    631 TEST_F(WebSocketTest, sendArrayBufferWhenClosed)
    632 {
    633     Checkpoint checkpoint;
    634     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    635     {
    636         InSequence s;
    637         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    638         EXPECT_CALL(channel(), disconnect());
    639         EXPECT_CALL(checkpoint, Call(1));
    640     }
    641     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    642 
    643     EXPECT_FALSE(m_exceptionState.hadException());
    644 
    645     m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, "");
    646     checkpoint.Call(1);
    647 
    648     m_websocket->send(view->buffer().get(), m_exceptionState);
    649 
    650     EXPECT_FALSE(m_exceptionState.hadException());
    651     EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState());
    652 }
    653 
    654 TEST_F(WebSocketTest, sendArrayBufferSuccess)
    655 {
    656     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    657     {
    658         InSequence s;
    659         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    660         EXPECT_CALL(channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::SendSuccess));
    661     }
    662     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    663 
    664     EXPECT_FALSE(m_exceptionState.hadException());
    665 
    666     m_websocket->didConnect("", "");
    667     m_websocket->send(view->buffer().get(), m_exceptionState);
    668 
    669     EXPECT_FALSE(m_exceptionState.hadException());
    670     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    671 }
    672 
    673 TEST_F(WebSocketTest, sendArrayBufferFail)
    674 {
    675     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    676     {
    677         InSequence s;
    678         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    679         EXPECT_CALL(channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::SendFail));
    680     }
    681     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    682 
    683     EXPECT_FALSE(m_exceptionState.hadException());
    684 
    685     m_websocket->didConnect("", "");
    686     m_websocket->send(view->buffer().get(), m_exceptionState);
    687 
    688     EXPECT_FALSE(m_exceptionState.hadException());
    689     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    690 }
    691 
    692 TEST_F(WebSocketTest, sendArrayBufferInvalidMessage)
    693 {
    694     RefPtr<ArrayBufferView> view = Uint8Array::create(8);
    695     {
    696         InSequence s;
    697         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    698         EXPECT_CALL(channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::InvalidMessage));
    699     }
    700     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    701 
    702     EXPECT_FALSE(m_exceptionState.hadException());
    703 
    704     m_websocket->didConnect("", "");
    705     m_websocket->send(view->buffer().get(), m_exceptionState);
    706 
    707     EXPECT_TRUE(m_exceptionState.hadException());
    708     EXPECT_EQ(SyntaxError, m_exceptionState.code());
    709     EXPECT_EQ("The message contains invalid characters.", m_exceptionState.message());
    710     EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState());
    711 }
    712 
    713 // FIXME: We should have Blob tests here.
    714 // We can't create a Blob because the blob registration cannot be mocked yet.
    715 
    716 // FIXME: We should add tests for bufferedAmount.
    717 
    718 // FIXME: We should add tests for data receiving.
    719 
    720 TEST_F(WebSocketTest, binaryType)
    721 {
    722     EXPECT_EQ("blob", m_websocket->binaryType());
    723 
    724     m_websocket->setBinaryType("hoge");
    725 
    726     EXPECT_EQ("blob", m_websocket->binaryType());
    727 
    728     m_websocket->setBinaryType("arraybuffer");
    729 
    730     EXPECT_EQ("arraybuffer", m_websocket->binaryType());
    731 
    732     m_websocket->setBinaryType("fuga");
    733 
    734     EXPECT_EQ("arraybuffer", m_websocket->binaryType());
    735 
    736     m_websocket->setBinaryType("blob");
    737 
    738     EXPECT_EQ("blob", m_websocket->binaryType());
    739 }
    740 
    741 // FIXME: We should add tests for suspend / resume.
    742 
    743 class WebSocketValidClosingCodeTest : public WebSocketTestBase, public ::testing::TestWithParam<unsigned short> {
    744 public:
    745 };
    746 
    747 TEST_P(WebSocketValidClosingCodeTest, test)
    748 {
    749     {
    750         InSequence s;
    751         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    752         EXPECT_CALL(channel(), fail(_, _, _, _));
    753     }
    754     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    755 
    756     EXPECT_FALSE(m_exceptionState.hadException());
    757     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    758 
    759     m_websocket->close(GetParam(), "bye", m_exceptionState);
    760 
    761     EXPECT_FALSE(m_exceptionState.hadException());
    762     EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState());
    763 }
    764 
    765 INSTANTIATE_TEST_CASE_P(WebSocketValidClosingCode, WebSocketValidClosingCodeTest, ::testing::Values(1000, 3000, 3001, 4998, 4999));
    766 
    767 class WebSocketInvalidClosingCodeTest : public WebSocketTestBase, public ::testing::TestWithParam<unsigned short> {
    768 public:
    769 };
    770 
    771 TEST_P(WebSocketInvalidClosingCodeTest, test)
    772 {
    773     {
    774         InSequence s;
    775         EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
    776     }
    777     m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState);
    778 
    779     EXPECT_FALSE(m_exceptionState.hadException());
    780     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    781 
    782     m_websocket->close(GetParam(), "bye", m_exceptionState);
    783 
    784     EXPECT_TRUE(m_exceptionState.hadException());
    785     EXPECT_EQ(InvalidAccessError, m_exceptionState.code());
    786     EXPECT_EQ(String::format("The code must be either 1000, or between 3000 and 4999. %d is neither.", GetParam()), m_exceptionState.message());
    787     EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState());
    788 }
    789 
    790 INSTANTIATE_TEST_CASE_P(WebSocketInvalidClosingCode, WebSocketInvalidClosingCodeTest, ::testing::Values(0, 1, 998, 999, 1001, 2999, 5000, 9999, 65535));
    791 
    792 } // namespace
    793 
    794 } // namespace WebCore
    795