1 // Copyright 2013 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 // Tests for WebSocketBasicStream. Note that we do not attempt to verify that 6 // frame parsing itself functions correctly, as that is covered by the 7 // WebSocketFrameParser tests. 8 9 #include "net/websockets/websocket_basic_stream.h" 10 11 #include <string.h> // for memcpy() and memset(). 12 13 #include <string> 14 15 #include "base/basictypes.h" 16 #include "base/port.h" 17 #include "net/base/big_endian.h" 18 #include "net/base/capturing_net_log.h" 19 #include "net/base/test_completion_callback.h" 20 #include "net/socket/socket_test_util.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 namespace net { 24 namespace { 25 26 #define WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(name, value) \ 27 const char k##name[] = value; \ 28 const size_t k##name##Size = arraysize(k##name) - 1; 29 30 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(SampleFrame, "\x81\x06Sample"); 31 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT( 32 PartialLargeFrame, 33 "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF" 34 "chromiunum ad pasco per loca insanis pullum manducat frumenti"); 35 const size_t kLargeFrameHeaderSize = 10; 36 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MultipleFrames, 37 "\x81\x01X\x81\x01Y\x81\x01Z"); 38 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFirstFrame, "\x01\x00"); 39 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyMiddleFrame, "\x00\x00"); 40 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalTextFrame, "\x81\x00"); 41 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalContinuationFrame, 42 "\x80\x00"); 43 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(ValidPong, "\x8A\x00"); 44 // This frame encodes a payload length of 7 in two bytes, which is always 45 // invalid. 46 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(InvalidFrame, 47 "\x81\x7E\x00\x07Invalid"); 48 // Control frames must have the FIN bit set. This one does not. 49 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(PingFrameWithoutFin, "\x09\x00"); 50 // Control frames must have a payload of 125 bytes or less. This one has 51 // a payload of 126 bytes. 52 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT( 53 126BytePong, 54 "\x8a\x7e\x00\x7eZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" 55 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); 56 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(CloseFrame, 57 "\x88\x09\x03\xe8occludo"); 58 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(WriteFrame, 59 "\x81\x85\x00\x00\x00\x00Write"); 60 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}}; 61 const WebSocketMaskingKey kNonNulMaskingKey = { 62 {'\x0d', '\x1b', '\x06', '\x17'}}; 63 64 // A masking key generator function which generates the identity mask, 65 // ie. "\0\0\0\0". 66 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; } 67 68 // A masking key generation function which generates a fixed masking key with no 69 // nul characters. 70 WebSocketMaskingKey GenerateNonNulMaskingKey() { return kNonNulMaskingKey; } 71 72 // Base class for WebSocketBasicStream test fixtures. 73 class WebSocketBasicStreamTest : public ::testing::Test { 74 protected: 75 scoped_ptr<WebSocketBasicStream> stream_; 76 CapturingNetLog net_log_; 77 }; 78 79 // A subclass of StaticSocketDataProvider modified to require that all data 80 // expected to be read or written actually is. 81 class StrictStaticSocketDataProvider : public StaticSocketDataProvider { 82 public: 83 StrictStaticSocketDataProvider(MockRead* reads, 84 size_t reads_count, 85 MockWrite* writes, 86 size_t writes_count, 87 bool strict_mode) 88 : StaticSocketDataProvider(reads, reads_count, writes, writes_count), 89 strict_mode_(strict_mode) {} 90 91 virtual ~StrictStaticSocketDataProvider() { 92 if (strict_mode_) { 93 EXPECT_EQ(read_count(), read_index()); 94 EXPECT_EQ(write_count(), write_index()); 95 } 96 } 97 98 private: 99 const bool strict_mode_; 100 }; 101 102 // A fixture for tests which only perform normal socket operations. 103 class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest { 104 protected: 105 WebSocketBasicStreamSocketTest() 106 : histograms_("a"), 107 pool_(1, 1, &histograms_, &factory_), 108 generator_(&GenerateNulMaskingKey), 109 expect_all_io_to_complete_(true) {} 110 111 virtual ~WebSocketBasicStreamSocketTest() { 112 // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so 113 // should be destroyed first. 114 stream_.reset(); 115 } 116 117 scoped_ptr<ClientSocketHandle> MakeTransportSocket(MockRead reads[], 118 size_t reads_count, 119 MockWrite writes[], 120 size_t writes_count) { 121 socket_data_.reset(new StrictStaticSocketDataProvider( 122 reads, reads_count, writes, writes_count, expect_all_io_to_complete_)); 123 socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 124 factory_.AddSocketDataProvider(socket_data_.get()); 125 126 scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle); 127 scoped_refptr<MockTransportSocketParams> params; 128 transport_socket->Init("a", 129 params, 130 MEDIUM, 131 CompletionCallback(), 132 &pool_, 133 bound_net_log_.bound()); 134 return transport_socket.Pass(); 135 } 136 137 void SetHttpReadBuffer(const char* data, size_t size) { 138 http_read_buffer_ = new GrowableIOBuffer; 139 http_read_buffer_->SetCapacity(size); 140 memcpy(http_read_buffer_->data(), data, size); 141 http_read_buffer_->set_offset(size); 142 } 143 144 void CreateStream(MockRead reads[], 145 size_t reads_count, 146 MockWrite writes[], 147 size_t writes_count) { 148 stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting( 149 MakeTransportSocket(reads, reads_count, writes, writes_count), 150 http_read_buffer_, 151 sub_protocol_, 152 extensions_, 153 generator_); 154 } 155 156 template <size_t N> 157 void CreateReadOnly(MockRead (&reads)[N]) { 158 CreateStream(reads, N, NULL, 0); 159 } 160 161 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); } 162 163 scoped_ptr<SocketDataProvider> socket_data_; 164 MockClientSocketFactory factory_; 165 ClientSocketPoolHistograms histograms_; 166 MockTransportClientSocketPool pool_; 167 CapturingBoundNetLog(bound_net_log_); 168 ScopedVector<WebSocketFrame> frames_; 169 TestCompletionCallback cb_; 170 scoped_refptr<GrowableIOBuffer> http_read_buffer_; 171 std::string sub_protocol_; 172 std::string extensions_; 173 WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_; 174 bool expect_all_io_to_complete_; 175 }; 176 177 // A test fixture for the common case of tests that only perform a single read. 178 class WebSocketBasicStreamSocketSingleReadTest 179 : public WebSocketBasicStreamSocketTest { 180 protected: 181 void CreateRead(const MockRead& read) { 182 reads_[0] = read; 183 CreateStream(reads_, 1U, NULL, 0); 184 } 185 186 MockRead reads_[1]; 187 }; 188 189 // A test fixture for tests that perform chunked reads. 190 class WebSocketBasicStreamSocketChunkedReadTest 191 : public WebSocketBasicStreamSocketTest { 192 protected: 193 // Specify the behaviour if there aren't enough chunks to use all the data. If 194 // LAST_FRAME_BIG is specified, then the rest of the data will be 195 // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last 196 // frame will be no bigger than the rest of the frames (but it can be smaller, 197 // if not enough data remains). 198 enum LastFrameBehaviour { 199 LAST_FRAME_BIG, 200 LAST_FRAME_NOT_BIG 201 }; 202 203 // Prepares a read from |data| of |data_size|, split into |number_of_chunks|, 204 // each of |chunk_size| (except that the last chunk may be larger or 205 // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture), 206 // and errors cannot be simulated. Once data is exhausted, further reads will 207 // return 0 (ie. connection closed). 208 void CreateChunkedRead(IoMode mode, 209 const char data[], 210 size_t data_size, 211 int chunk_size, 212 int number_of_chunks, 213 LastFrameBehaviour last_frame_behaviour) { 214 reads_.reset(new MockRead[number_of_chunks]); 215 const char* start = data; 216 for (int i = 0; i < number_of_chunks; ++i) { 217 int len = chunk_size; 218 const bool is_last_chunk = (i == number_of_chunks - 1); 219 if ((last_frame_behaviour == LAST_FRAME_BIG && is_last_chunk) || 220 static_cast<int>(data + data_size - start) < len) { 221 len = static_cast<int>(data + data_size - start); 222 } 223 reads_[i] = MockRead(mode, start, len); 224 start += len; 225 } 226 CreateStream(reads_.get(), number_of_chunks, NULL, 0); 227 } 228 229 scoped_ptr<MockRead[]> reads_; 230 }; 231 232 // Test fixture for write tests. 233 class WebSocketBasicStreamSocketWriteTest 234 : public WebSocketBasicStreamSocketTest { 235 protected: 236 // All write tests use the same frame, so it is easiest to create it during 237 // test creation. 238 virtual void SetUp() OVERRIDE { PrepareWriteFrame(); } 239 240 // Creates a WebSocketFrame with a wire format matching kWriteFrame and adds 241 // it to |frames_|. 242 void PrepareWriteFrame() { 243 scoped_ptr<WebSocketFrame> frame( 244 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText)); 245 const size_t payload_size = 246 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize + 247 WebSocketFrameHeader::kMaskingKeyLength); 248 frame->data = new IOBuffer(payload_size); 249 memcpy(frame->data->data(), 250 kWriteFrame + kWriteFrameSize - payload_size, 251 payload_size); 252 WebSocketFrameHeader& header = frame->header; 253 header.final = true; 254 header.masked = true; 255 header.payload_length = payload_size; 256 frames_.push_back(frame.release()); 257 } 258 259 // Creates a stream that expects the listed writes. 260 template <size_t N> 261 void CreateWriteOnly(MockWrite (&writes)[N]) { 262 CreateStream(NULL, 0, writes, N); 263 } 264 }; 265 266 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) { 267 CreateNullStream(); 268 } 269 270 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) { 271 CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize)); 272 int result = stream_->ReadFrames(&frames_, cb_.callback()); 273 EXPECT_EQ(OK, result); 274 ASSERT_EQ(1U, frames_.size()); 275 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length); 276 EXPECT_TRUE(frames_[0]->header.final); 277 } 278 279 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) { 280 CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize)); 281 int result = stream_->ReadFrames(&frames_, cb_.callback()); 282 ASSERT_EQ(ERR_IO_PENDING, result); 283 EXPECT_EQ(OK, cb_.WaitForResult()); 284 ASSERT_EQ(1U, frames_.size()); 285 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length); 286 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the 287 // frame was really read. 288 } 289 290 // ReadFrames will not return a frame whose header has not been wholly received. 291 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) { 292 CreateChunkedRead( 293 SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG); 294 int result = stream_->ReadFrames(&frames_, cb_.callback()); 295 EXPECT_EQ(OK, result); 296 ASSERT_EQ(1U, frames_.size()); 297 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length); 298 } 299 300 // The same behaviour applies to asynchronous reads. 301 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) { 302 CreateChunkedRead( 303 ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG); 304 int result = stream_->ReadFrames(&frames_, cb_.callback()); 305 ASSERT_EQ(ERR_IO_PENDING, result); 306 EXPECT_EQ(OK, cb_.WaitForResult()); 307 ASSERT_EQ(1U, frames_.size()); 308 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length); 309 } 310 311 // If it receives an incomplete header in a synchronous call, then has to wait 312 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING. 313 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) { 314 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1), 315 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; 316 CreateReadOnly(reads); 317 int result = stream_->ReadFrames(&frames_, cb_.callback()); 318 ASSERT_EQ(ERR_IO_PENDING, result); 319 EXPECT_EQ(OK, cb_.WaitForResult()); 320 ASSERT_EQ(1U, frames_.size()); 321 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length); 322 } 323 324 // An extended header should also return ERR_IO_PENDING if it is not completely 325 // received. 326 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) { 327 MockRead reads[] = { 328 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1), 329 MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; 330 CreateReadOnly(reads); 331 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 332 } 333 334 // A frame that does not arrive in a single read should be broken into separate 335 // frames. 336 TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) { 337 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize)); 338 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 339 ASSERT_EQ(1U, frames_.size()); 340 EXPECT_FALSE(frames_[0]->header.final); 341 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize, 342 static_cast<size_t>(frames_[0]->header.payload_length)); 343 } 344 345 // If only the header of a data frame arrives, we should receive a frame with a 346 // zero-size payload. 347 TEST_F(WebSocketBasicStreamSocketSingleReadTest, HeaderOnlyChunk) { 348 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize)); 349 350 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 351 ASSERT_EQ(1U, frames_.size()); 352 EXPECT_EQ(NULL, frames_[0]->data.get()); 353 EXPECT_EQ(0U, frames_[0]->header.payload_length); 354 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode); 355 } 356 357 // If the header and the body of a data frame arrive seperately, we should see 358 // them as separate frames. 359 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) { 360 MockRead reads[] = { 361 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize), 362 MockRead(ASYNC, 363 kPartialLargeFrame + kLargeFrameHeaderSize, 364 kPartialLargeFrameSize - kLargeFrameHeaderSize)}; 365 CreateReadOnly(reads); 366 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 367 ASSERT_EQ(1U, frames_.size()); 368 EXPECT_EQ(NULL, frames_[0]->data.get()); 369 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode); 370 frames_.clear(); 371 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 372 EXPECT_EQ(OK, cb_.WaitForResult()); 373 ASSERT_EQ(1U, frames_.size()); 374 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize, 375 frames_[0]->header.payload_length); 376 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 377 frames_[0]->header.opcode); 378 } 379 380 // Every frame has a header with a correct payload_length field. 381 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) { 382 const size_t kChunkSize = 16; 383 CreateChunkedRead(ASYNC, 384 kPartialLargeFrame, 385 kPartialLargeFrameSize, 386 kChunkSize, 387 2, 388 LAST_FRAME_NOT_BIG); 389 TestCompletionCallback cb[2]; 390 391 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback())); 392 EXPECT_EQ(OK, cb[0].WaitForResult()); 393 ASSERT_EQ(1U, frames_.size()); 394 EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize, 395 frames_[0]->header.payload_length); 396 397 frames_.clear(); 398 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback())); 399 EXPECT_EQ(OK, cb[1].WaitForResult()); 400 ASSERT_EQ(1U, frames_.size()); 401 EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length); 402 } 403 404 // Only the final frame of a fragmented message has |final| bit set. 405 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) { 406 static const size_t kFirstChunkSize = 4; 407 CreateChunkedRead(ASYNC, 408 kSampleFrame, 409 kSampleFrameSize, 410 kFirstChunkSize, 411 2, 412 LAST_FRAME_BIG); 413 TestCompletionCallback cb[2]; 414 415 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback())); 416 EXPECT_EQ(OK, cb[0].WaitForResult()); 417 ASSERT_EQ(1U, frames_.size()); 418 ASSERT_FALSE(frames_[0]->header.final); 419 420 frames_.clear(); 421 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback())); 422 EXPECT_EQ(OK, cb[1].WaitForResult()); 423 ASSERT_EQ(1U, frames_.size()); 424 ASSERT_TRUE(frames_[0]->header.final); 425 } 426 427 // All frames after the first have their opcode changed to Continuation. 428 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ContinuationOpCodeUsed) { 429 const size_t kFirstChunkSize = 3; 430 const int kChunkCount = 3; 431 // The input data is one frame with opcode Text, which arrives in three 432 // separate chunks. 433 CreateChunkedRead(ASYNC, 434 kSampleFrame, 435 kSampleFrameSize, 436 kFirstChunkSize, 437 kChunkCount, 438 LAST_FRAME_BIG); 439 TestCompletionCallback cb[kChunkCount]; 440 441 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback())); 442 EXPECT_EQ(OK, cb[0].WaitForResult()); 443 ASSERT_EQ(1U, frames_.size()); 444 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode); 445 446 // This test uses a loop to verify that the opcode for every frames generated 447 // after the first is converted to Continuation. 448 for (int i = 1; i < kChunkCount; ++i) { 449 frames_.clear(); 450 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[i].callback())); 451 EXPECT_EQ(OK, cb[i].WaitForResult()); 452 ASSERT_EQ(1U, frames_.size()); 453 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 454 frames_[0]->header.opcode); 455 } 456 } 457 458 // Multiple frames that arrive together should be parsed correctly. 459 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) { 460 CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize)); 461 462 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 463 ASSERT_EQ(3U, frames_.size()); 464 EXPECT_TRUE(frames_[0]->header.final); 465 EXPECT_TRUE(frames_[1]->header.final); 466 EXPECT_TRUE(frames_[2]->header.final); 467 } 468 469 // ERR_CONNECTION_CLOSED must be returned on close. 470 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) { 471 CreateRead(MockRead(SYNCHRONOUS, "", 0)); 472 473 EXPECT_EQ(ERR_CONNECTION_CLOSED, 474 stream_->ReadFrames(&frames_, cb_.callback())); 475 } 476 477 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) { 478 CreateRead(MockRead(ASYNC, "", 0)); 479 480 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 481 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 482 } 483 484 // The result should be the same if the socket returns 485 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established 486 // connection; a Read of size 0 is the expected behaviour. The key point of this 487 // test is to confirm that ReadFrames() behaviour is identical in both cases. 488 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) { 489 CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)); 490 491 EXPECT_EQ(ERR_CONNECTION_CLOSED, 492 stream_->ReadFrames(&frames_, cb_.callback())); 493 } 494 495 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) { 496 CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED)); 497 498 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 499 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 500 } 501 502 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) { 503 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that 504 // WebSocketBasicStream gives no special handling to. 505 CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES)); 506 507 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, 508 stream_->ReadFrames(&frames_, cb_.callback())); 509 } 510 511 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) { 512 CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES)); 513 514 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 515 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult()); 516 } 517 518 // If we get a frame followed by a close, we should receive them separately. 519 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) { 520 // The chunk size equals the data size, so the second chunk is 0 size, closing 521 // the connection. 522 CreateChunkedRead(SYNCHRONOUS, 523 kSampleFrame, 524 kSampleFrameSize, 525 kSampleFrameSize, 526 2, 527 LAST_FRAME_NOT_BIG); 528 529 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 530 EXPECT_EQ(1U, frames_.size()); 531 frames_.clear(); 532 EXPECT_EQ(ERR_CONNECTION_CLOSED, 533 stream_->ReadFrames(&frames_, cb_.callback())); 534 } 535 536 // Synchronous close after an async frame header is handled by a different code 537 // path. 538 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) { 539 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), 540 MockRead(SYNCHRONOUS, "", 0)}; 541 CreateReadOnly(reads); 542 543 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 544 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 545 } 546 547 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a 548 // slightly different code path. 549 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) { 550 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), 551 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)}; 552 CreateReadOnly(reads); 553 554 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 555 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 556 } 557 558 // An empty first frame is not ignored. 559 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) { 560 CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize)); 561 562 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 563 ASSERT_EQ(1U, frames_.size()); 564 EXPECT_EQ(NULL, frames_[0]->data.get()); 565 EXPECT_EQ(0U, frames_[0]->header.payload_length); 566 } 567 568 // An empty frame in the middle of a message is ignored. 569 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrame) { 570 MockRead reads[] = { 571 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize), 572 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize), 573 MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; 574 CreateReadOnly(reads); 575 576 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 577 EXPECT_EQ(1U, frames_.size()); 578 frames_.clear(); 579 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 580 } 581 582 // An empty frame in the middle of a message that arrives separately is still 583 // ignored. 584 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrameAsync) { 585 MockRead reads[] = { 586 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize), 587 MockRead(ASYNC, kEmptyMiddleFrame, kEmptyMiddleFrameSize), 588 // We include a pong message to verify the middle frame was actually 589 // processed. 590 MockRead(ASYNC, kValidPong, kValidPongSize)}; 591 CreateReadOnly(reads); 592 593 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 594 EXPECT_EQ(1U, frames_.size()); 595 frames_.clear(); 596 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 597 EXPECT_EQ(OK, cb_.WaitForResult()); 598 ASSERT_EQ(1U, frames_.size()); 599 EXPECT_EQ(WebSocketFrameHeader::kOpCodePong, frames_[0]->header.opcode); 600 } 601 602 // An empty final frame is not ignored. 603 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) { 604 CreateRead( 605 MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize)); 606 607 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 608 ASSERT_EQ(1U, frames_.size()); 609 EXPECT_EQ(NULL, frames_[0]->data.get()); 610 EXPECT_EQ(0U, frames_[0]->header.payload_length); 611 } 612 613 // An empty middle frame is ignored with a final frame present. 614 TEST_F(WebSocketBasicStreamSocketTest, ThreeFrameEmptyMessage) { 615 MockRead reads[] = { 616 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize), 617 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize), 618 MockRead(SYNCHRONOUS, 619 kEmptyFinalContinuationFrame, 620 kEmptyFinalContinuationFrameSize)}; 621 CreateReadOnly(reads); 622 623 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 624 ASSERT_EQ(1U, frames_.size()); 625 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode); 626 frames_.clear(); 627 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 628 ASSERT_EQ(1U, frames_.size()); 629 EXPECT_TRUE(frames_[0]->header.final); 630 } 631 632 // If there was a frame read at the same time as the response headers (and the 633 // handshake succeeded), then we should parse it. 634 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) { 635 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize); 636 CreateNullStream(); 637 638 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 639 ASSERT_EQ(1U, frames_.size()); 640 ASSERT_TRUE(frames_[0]->data); 641 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length); 642 } 643 644 // Check that a frame whose header partially arrived at the end of the response 645 // headers works correctly. 646 TEST_F(WebSocketBasicStreamSocketSingleReadTest, 647 PartialFrameHeaderInHttpResponse) { 648 SetHttpReadBuffer(kSampleFrame, 1); 649 CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)); 650 651 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 652 EXPECT_EQ(OK, cb_.WaitForResult()); 653 ASSERT_EQ(1U, frames_.size()); 654 ASSERT_TRUE(frames_[0]->data); 655 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length); 656 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode); 657 } 658 659 // Check that a control frame which partially arrives at the end of the response 660 // headers works correctly. 661 TEST_F(WebSocketBasicStreamSocketSingleReadTest, 662 PartialControlFrameInHttpResponse) { 663 const size_t kPartialFrameBytes = 3; 664 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes); 665 CreateRead(MockRead(ASYNC, 666 kCloseFrame + kPartialFrameBytes, 667 kCloseFrameSize - kPartialFrameBytes)); 668 669 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 670 EXPECT_EQ(OK, cb_.WaitForResult()); 671 ASSERT_EQ(1U, frames_.size()); 672 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode); 673 EXPECT_EQ(kCloseFrameSize - 2, frames_[0]->header.payload_length); 674 EXPECT_EQ( 675 0, 676 memcmp(frames_[0]->data->data(), kCloseFrame + 2, kCloseFrameSize - 2)); 677 } 678 679 // Check that a control frame which partially arrives at the end of the response 680 // headers works correctly. Synchronous version (unlikely in practice). 681 TEST_F(WebSocketBasicStreamSocketSingleReadTest, 682 PartialControlFrameInHttpResponseSync) { 683 const size_t kPartialFrameBytes = 3; 684 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes); 685 CreateRead(MockRead(SYNCHRONOUS, 686 kCloseFrame + kPartialFrameBytes, 687 kCloseFrameSize - kPartialFrameBytes)); 688 689 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 690 ASSERT_EQ(1U, frames_.size()); 691 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode); 692 } 693 694 // Check that an invalid frame results in an error. 695 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) { 696 CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)); 697 698 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, 699 stream_->ReadFrames(&frames_, cb_.callback())); 700 } 701 702 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) { 703 CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)); 704 705 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 706 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult()); 707 } 708 709 // A control frame without a FIN flag is invalid and should not be passed 710 // through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be 711 // fragmented." 712 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) { 713 CreateRead( 714 MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize)); 715 716 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, 717 stream_->ReadFrames(&frames_, cb_.callback())); 718 EXPECT_TRUE(frames_.empty()); 719 } 720 721 // A control frame over 125 characters is invalid. RFC6455 5.5 "All control 722 // frames MUST have a payload length of 125 bytes or less". Since we use a 723 // 125-byte buffer to assemble fragmented control frames, we need to detect this 724 // error before attempting to assemble the fragments. 725 TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) { 726 CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize)); 727 728 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, 729 stream_->ReadFrames(&frames_, cb_.callback())); 730 EXPECT_TRUE(frames_.empty()); 731 } 732 733 // A control frame over 125 characters should still be rejected if it is split 734 // into multiple chunks. 735 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) { 736 const size_t kFirstChunkSize = 16; 737 expect_all_io_to_complete_ = false; 738 CreateChunkedRead(SYNCHRONOUS, 739 k126BytePong, 740 k126BytePongSize, 741 kFirstChunkSize, 742 2, 743 LAST_FRAME_BIG); 744 745 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, 746 stream_->ReadFrames(&frames_, cb_.callback())); 747 EXPECT_TRUE(frames_.empty()); 748 } 749 750 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, 751 AsyncSplitOverlongControlFrame) { 752 const size_t kFirstChunkSize = 16; 753 expect_all_io_to_complete_ = false; 754 CreateChunkedRead(ASYNC, 755 k126BytePong, 756 k126BytePongSize, 757 kFirstChunkSize, 758 2, 759 LAST_FRAME_BIG); 760 761 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 762 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult()); 763 // The caller should not call ReadFrames() again after receiving an error 764 // other than ERR_IO_PENDING. 765 EXPECT_TRUE(frames_.empty()); 766 } 767 768 // In the synchronous case, ReadFrames assembles the whole control frame before 769 // returning. 770 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) { 771 const size_t kChunkSize = 3; 772 CreateChunkedRead( 773 SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG); 774 775 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback())); 776 ASSERT_EQ(1U, frames_.size()); 777 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode); 778 } 779 780 // In the asynchronous case, the callback is not called until the control frame 781 // has been completely assembled. 782 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) { 783 const size_t kChunkSize = 3; 784 CreateChunkedRead( 785 ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG); 786 787 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 788 EXPECT_EQ(OK, cb_.WaitForResult()); 789 ASSERT_EQ(1U, frames_.size()); 790 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode); 791 } 792 793 // A frame with a 1MB payload that has to be read in chunks. 794 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OneMegFrame) { 795 // This should be equal to the definition of kReadBufferSize in 796 // websocket_basic_stream.cc. 797 const int kReadBufferSize = 32 * 1024; 798 const uint64 kPayloadSize = 1 << 20; 799 const size_t kWireSize = kPayloadSize + kLargeFrameHeaderSize; 800 const size_t kExpectedFrameCount = 801 (kWireSize + kReadBufferSize - 1) / kReadBufferSize; 802 scoped_ptr<char[]> big_frame(new char[kWireSize]); 803 memcpy(big_frame.get(), "\x81\x7F", 2); 804 WriteBigEndian(big_frame.get() + 2, kPayloadSize); 805 memset(big_frame.get() + kLargeFrameHeaderSize, 'A', kPayloadSize); 806 807 CreateChunkedRead(ASYNC, 808 big_frame.get(), 809 kWireSize, 810 kReadBufferSize, 811 kExpectedFrameCount, 812 LAST_FRAME_BIG); 813 814 for (size_t frame = 0; frame < kExpectedFrameCount; ++frame) { 815 frames_.clear(); 816 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback())); 817 EXPECT_EQ(OK, cb_.WaitForResult()); 818 ASSERT_EQ(1U, frames_.size()); 819 size_t expected_payload_size = kReadBufferSize; 820 if (frame == 0) { 821 expected_payload_size = kReadBufferSize - kLargeFrameHeaderSize; 822 } else if (frame == kExpectedFrameCount - 1) { 823 expected_payload_size = kLargeFrameHeaderSize; 824 } 825 EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length); 826 } 827 } 828 829 // Check that writing a frame all at once works. 830 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) { 831 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)}; 832 CreateWriteOnly(writes); 833 834 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback())); 835 } 836 837 // Check that completely async writing works. 838 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) { 839 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)}; 840 CreateWriteOnly(writes); 841 842 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback())); 843 EXPECT_EQ(OK, cb_.WaitForResult()); 844 } 845 846 // Check that writing a frame to an extremely full kernel buffer (so that it 847 // ends up being sent in bits) works. The WriteFrames() callback should not be 848 // called until all parts have been written. 849 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) { 850 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4), 851 MockWrite(ASYNC, kWriteFrame + 4, 4), 852 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)}; 853 CreateWriteOnly(writes); 854 855 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback())); 856 EXPECT_EQ(OK, cb_.WaitForResult()); 857 } 858 859 // Check that writing with a non-NULL mask works correctly. 860 TEST_F(WebSocketBasicStreamSocketTest, WriteNonNulMask) { 861 std::string masked_frame = std::string("\x81\x88"); 862 masked_frame += std::string(kNonNulMaskingKey.key, 4); 863 masked_frame += "jiggered"; 864 MockWrite writes[] = { 865 MockWrite(SYNCHRONOUS, masked_frame.data(), masked_frame.size())}; 866 generator_ = &GenerateNonNulMaskingKey; 867 CreateStream(NULL, 0, writes, arraysize(writes)); 868 869 scoped_ptr<WebSocketFrame> frame( 870 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText)); 871 const std::string unmasked_payload = "graphics"; 872 const size_t payload_size = unmasked_payload.size(); 873 frame->data = new IOBuffer(payload_size); 874 memcpy(frame->data->data(), unmasked_payload.data(), payload_size); 875 WebSocketFrameHeader& header = frame->header; 876 header.final = true; 877 header.masked = true; 878 header.payload_length = payload_size; 879 frames_.push_back(frame.release()); 880 881 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback())); 882 } 883 884 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) { 885 extensions_ = "inflate-uuencode"; 886 CreateNullStream(); 887 888 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions()); 889 } 890 891 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) { 892 sub_protocol_ = "cyberchat"; 893 CreateNullStream(); 894 895 EXPECT_EQ("cyberchat", stream_->GetSubProtocol()); 896 } 897 898 } // namespace 899 } // namespace net 900