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