• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
create()39     static PassRefPtrWillBeRawPtr<MockWebSocketChannel> create()
40     {
41         return adoptRefWillBeRefCountedGarbageCollected(new testing::StrictMock<MockWebSocketChannel>());
42     }
43 
~MockWebSocketChannel()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 
MockWebSocketChannel()60     MockWebSocketChannel()
61     {
62     }
63 };
64 
65 class WebSocketWithMockChannel FINAL : public WebSocket {
66 public:
create(ExecutionContext * context)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 
channel()74     MockWebSocketChannel* channel() { return m_channel.get(); }
75 
createChannel(ExecutionContext *,WebSocketChannelClient *)76     virtual PassRefPtrWillBeRawPtr<WebSocketChannel> createChannel(ExecutionContext*, WebSocketChannelClient*) OVERRIDE
77     {
78         ASSERT(!m_hasCreatedChannel);
79         m_hasCreatedChannel = true;
80         return m_channel.get();
81     }
82 
trace(Visitor * visitor)83     virtual void trace(Visitor* visitor) OVERRIDE
84     {
85         visitor->trace(m_channel);
86         WebSocket::trace(visitor);
87     }
88 
89 private:
WebSocketWithMockChannel(ExecutionContext * context)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:
WebSocketTestBase()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 
~WebSocketTestBase()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 
channel()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 
TEST_F(WebSocketTest,connectToBadURL)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 
TEST_F(WebSocketTest,connectToNonWsURL)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 
TEST_F(WebSocketTest,connectToURLHavingFragmentIdentifier)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 
TEST_F(WebSocketTest,invalidPort)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 
TEST_F(WebSocketTest,invalidSubprotocols)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 
TEST_F(WebSocketTest,channelConnectSuccess)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 
TEST_F(WebSocketTest,channelConnectFail)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 
TEST_F(WebSocketTest,isValidSubprotocolString)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 
TEST_F(WebSocketTest,connectSuccess)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 
TEST_F(WebSocketTest,didClose)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 
TEST_F(WebSocketTest,maximumReasonSize)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 
TEST_F(WebSocketTest,reasonSizeExceeding)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 
TEST_F(WebSocketTest,closeWhenConnecting)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 
TEST_F(WebSocketTest,close)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 
TEST_F(WebSocketTest,closeWithoutReason)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 
TEST_F(WebSocketTest,closeWithoutCodeAndReason)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 
TEST_F(WebSocketTest,closeWhenClosing)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 
TEST_F(WebSocketTest,closeWhenClosed)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 
TEST_F(WebSocketTest,sendStringWhenConnecting)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 
TEST_F(WebSocketTest,sendStringWhenClosing)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 
TEST_F(WebSocketTest,sendStringWhenClosed)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 
TEST_F(WebSocketTest,sendStringSuccess)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 
TEST_F(WebSocketTest,sendStringFail)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 
TEST_F(WebSocketTest,sendStringInvalidMessage)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 
TEST_F(WebSocketTest,sendArrayBufferWhenConnecting)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 
TEST_F(WebSocketTest,sendArrayBufferWhenClosing)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 
TEST_F(WebSocketTest,sendArrayBufferWhenClosed)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 
TEST_F(WebSocketTest,sendArrayBufferSuccess)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 
TEST_F(WebSocketTest,sendArrayBufferFail)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 
TEST_F(WebSocketTest,sendArrayBufferInvalidMessage)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 
TEST_F(WebSocketTest,binaryType)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 
TEST_P(WebSocketValidClosingCodeTest,test)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 
TEST_P(WebSocketInvalidClosingCodeTest,test)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