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