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: 39 static PassRefPtrWillBeRawPtr<MockWebSocketChannel> create() 40 { 41 return adoptRefWillBeRefCountedGarbageCollected(new testing::StrictMock<MockWebSocketChannel>()); 42 } 43 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 60 MockWebSocketChannel() 61 { 62 } 63 }; 64 65 class WebSocketWithMockChannel FINAL : public WebSocket { 66 public: 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 74 MockWebSocketChannel* channel() { return m_channel.get(); } 75 76 virtual PassRefPtrWillBeRawPtr<WebSocketChannel> createChannel(ExecutionContext*, WebSocketChannelClient*) OVERRIDE 77 { 78 ASSERT(!m_hasCreatedChannel); 79 m_hasCreatedChannel = true; 80 return m_channel.get(); 81 } 82 83 virtual void trace(Visitor* visitor) OVERRIDE 84 { 85 visitor->trace(m_channel); 86 WebSocket::trace(visitor); 87 } 88 89 private: 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: 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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