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