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