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