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 #include "net/websockets/websocket_deflate_stream.h" 6 7 #include <stdint.h> 8 #include <deque> 9 #include <string> 10 11 #include "base/basictypes.h" 12 #include "base/bind.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_vector.h" 16 #include "net/base/completion_callback.h" 17 #include "net/base/io_buffer.h" 18 #include "net/base/net_errors.h" 19 #include "net/websockets/websocket_deflate_predictor.h" 20 #include "net/websockets/websocket_deflater.h" 21 #include "net/websockets/websocket_frame.h" 22 #include "net/websockets/websocket_inflater.h" 23 #include "net/websockets/websocket_stream.h" 24 #include "net/websockets/websocket_test_util.h" 25 #include "testing/gmock/include/gmock/gmock.h" 26 #include "testing/gtest/include/gtest/gtest.h" 27 28 namespace net { 29 namespace { 30 31 typedef ::testing::MockFunction<void(int)> MockCallback; // NOLINT 32 using ::testing::_; 33 using ::testing::InSequence; 34 using ::testing::Invoke; 35 using ::testing::Return; 36 37 typedef uint32_t FrameFlag; 38 const FrameFlag kNoFlag = 0; 39 const FrameFlag kFinal = 1; 40 const FrameFlag kReserved1 = 2; 41 // We don't define values for other flags because we don't need them. 42 43 // The value must equal to the value of the corresponding 44 // constant in websocket_deflate_stream.cc 45 const size_t kChunkSize = 4 * 1024; 46 const int kWindowBits = 15; 47 48 scoped_refptr<IOBuffer> ToIOBuffer(const std::string& s) { 49 scoped_refptr<IOBuffer> buffer = new IOBuffer(s.size()); 50 memcpy(buffer->data(), s.data(), s.size()); 51 return buffer; 52 } 53 54 std::string ToString(IOBufferWithSize* buffer) { 55 return std::string(buffer->data(), buffer->size()); 56 } 57 58 std::string ToString(const scoped_refptr<IOBufferWithSize>& buffer) { 59 return ToString(buffer.get()); 60 } 61 62 std::string ToString(IOBuffer* buffer, size_t size) { 63 return std::string(buffer->data(), size); 64 } 65 66 std::string ToString(const scoped_refptr<IOBuffer>& buffer, size_t size) { 67 return ToString(buffer.get(), size); 68 } 69 70 std::string ToString(const WebSocketFrame* frame) { 71 return frame->data.get() ? ToString(frame->data, frame->header.payload_length) 72 : ""; 73 } 74 75 void AppendTo(ScopedVector<WebSocketFrame>* frames, 76 WebSocketFrameHeader::OpCode opcode, 77 FrameFlag flag, 78 const std::string& data) { 79 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode)); 80 frame->header.final = (flag & kFinal); 81 frame->header.reserved1 = (flag & kReserved1); 82 frame->data = ToIOBuffer(data); 83 frame->header.payload_length = data.size(); 84 frames->push_back(frame.release()); 85 } 86 87 void AppendTo(ScopedVector<WebSocketFrame>* frames, 88 WebSocketFrameHeader::OpCode opcode, 89 FrameFlag flag) { 90 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode)); 91 frame->header.final = (flag & kFinal); 92 frame->header.reserved1 = (flag & kReserved1); 93 frames->push_back(frame.release()); 94 } 95 96 class MockWebSocketStream : public WebSocketStream { 97 public: 98 MOCK_METHOD2(ReadFrames, int(ScopedVector<WebSocketFrame>*, 99 const CompletionCallback&)); 100 MOCK_METHOD2(WriteFrames, int(ScopedVector<WebSocketFrame>*, 101 const CompletionCallback&)); 102 MOCK_METHOD0(Close, void()); 103 MOCK_CONST_METHOD0(GetSubProtocol, std::string()); 104 MOCK_CONST_METHOD0(GetExtensions, std::string()); 105 }; 106 107 // This mock class relies on some assumptions. 108 // - RecordInputDataFrame is called after the corresponding WriteFrames 109 // call. 110 // - RecordWrittenDataFrame is called before writing the frame. 111 class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor { 112 public: 113 WebSocketDeflatePredictorMock() : result_(DEFLATE) {} 114 virtual ~WebSocketDeflatePredictorMock() { 115 // Verify whether all expectaions are consumed. 116 if (!frames_to_be_input_.empty()) { 117 ADD_FAILURE() << "There are missing frames to be input."; 118 return; 119 } 120 if (!frames_written_.empty()) { 121 ADD_FAILURE() << "There are extra written frames."; 122 return; 123 } 124 } 125 126 // WebSocketDeflatePredictor functions. 127 virtual Result Predict(const ScopedVector<WebSocketFrame>& frames, 128 size_t frame_index) OVERRIDE { 129 return result_; 130 } 131 virtual void RecordInputDataFrame(const WebSocketFrame* frame) OVERRIDE { 132 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) { 133 ADD_FAILURE() << "Control frames should not be recorded."; 134 return; 135 } 136 if (frame->header.reserved1) { 137 ADD_FAILURE() << "Input frame may not be compressed."; 138 return; 139 } 140 if (frames_to_be_input_.empty()) { 141 ADD_FAILURE() << "Unexpected input data frame"; 142 return; 143 } 144 if (frame != frames_to_be_input_.front()) { 145 ADD_FAILURE() << "Input data frame does not match the expectation."; 146 return; 147 } 148 frames_to_be_input_.pop_front(); 149 } 150 virtual void RecordWrittenDataFrame(const WebSocketFrame* frame) OVERRIDE { 151 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) { 152 ADD_FAILURE() << "Control frames should not be recorded."; 153 return; 154 } 155 frames_written_.push_back(frame); 156 } 157 158 // Sets |result_| for the |Predict| return value. 159 void set_result(Result result) { result_ = result; } 160 161 // Adds |frame| as an expectation of future |RecordInputDataFrame| call. 162 void AddFrameToBeInput(const WebSocketFrame* frame) { 163 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) 164 return; 165 frames_to_be_input_.push_back(frame); 166 } 167 // Verifies that |frame| is recorded in order. 168 void VerifySentFrame(const WebSocketFrame* frame) { 169 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) 170 return; 171 if (frames_written_.empty()) { 172 ADD_FAILURE() << "There are missing frames to be written."; 173 return; 174 } 175 if (frame != frames_written_.front()) { 176 ADD_FAILURE() << "Written data frame does not match the expectation."; 177 return; 178 } 179 frames_written_.pop_front(); 180 } 181 void AddFramesToBeInput(const ScopedVector<WebSocketFrame>& frames) { 182 for (size_t i = 0; i < frames.size(); ++i) 183 AddFrameToBeInput(frames[i]); 184 } 185 void VerifySentFrames(const ScopedVector<WebSocketFrame>& frames) { 186 for (size_t i = 0; i < frames.size(); ++i) 187 VerifySentFrame(frames[i]); 188 } 189 // Call this method in order to disable checks in the destructor when 190 // WriteFrames fails. 191 void Clear() { 192 frames_to_be_input_.clear(); 193 frames_written_.clear(); 194 } 195 196 private: 197 Result result_; 198 // Data frames which will be recorded by |RecordInputFrames|. 199 // Pushed by |AddFrameToBeInput| and popped and verified by 200 // |RecordInputFrames|. 201 std::deque<const WebSocketFrame*> frames_to_be_input_; 202 // Data frames recorded by |RecordWrittenFrames|. 203 // Pushed by |RecordWrittenFrames| and popped and verified by 204 // |VerifySentFrame|. 205 std::deque<const WebSocketFrame*> frames_written_; 206 207 DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock); 208 }; 209 210 class WebSocketDeflateStreamTest : public ::testing::Test { 211 public: 212 WebSocketDeflateStreamTest() 213 : mock_stream_(NULL), 214 predictor_(NULL) {} 215 virtual ~WebSocketDeflateStreamTest() {} 216 217 virtual void SetUp() { 218 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, kWindowBits); 219 } 220 221 protected: 222 // Initialize deflate_stream_ with the given parameters. 223 void Initialize(WebSocketDeflater::ContextTakeOverMode mode, 224 int window_bits) { 225 mock_stream_ = new testing::StrictMock<MockWebSocketStream>; 226 predictor_ = new WebSocketDeflatePredictorMock; 227 deflate_stream_.reset(new WebSocketDeflateStream( 228 scoped_ptr<WebSocketStream>(mock_stream_), 229 mode, 230 window_bits, 231 scoped_ptr<WebSocketDeflatePredictor>(predictor_))); 232 } 233 234 scoped_ptr<WebSocketDeflateStream> deflate_stream_; 235 // Owned by |deflate_stream_|. 236 MockWebSocketStream* mock_stream_; 237 // Owned by |deflate_stream_|. 238 WebSocketDeflatePredictorMock* predictor_; 239 }; 240 241 // Since WebSocketDeflater with DoNotTakeOverContext is well tested at 242 // websocket_deflater_test.cc, we have only a few tests for this configuration 243 // here. 244 class WebSocketDeflateStreamWithDoNotTakeOverContextTest 245 : public WebSocketDeflateStreamTest { 246 public: 247 WebSocketDeflateStreamWithDoNotTakeOverContextTest() {} 248 virtual ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() {} 249 250 virtual void SetUp() { 251 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT, kWindowBits); 252 } 253 }; 254 255 class WebSocketDeflateStreamWithClientWindowBitsTest 256 : public WebSocketDeflateStreamTest { 257 public: 258 WebSocketDeflateStreamWithClientWindowBitsTest() {} 259 virtual ~WebSocketDeflateStreamWithClientWindowBitsTest() {} 260 261 // Overridden to postpone the call to Initialize(). 262 virtual void SetUp() {} 263 264 // This needs to be called explicitly from the tests. 265 void SetUpWithWindowBits(int window_bits) { 266 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, window_bits); 267 } 268 269 // Add a frame which will be compressed to a smaller size if the window 270 // size is large enough. 271 void AddCompressibleFrameString() { 272 const std::string word = "Chromium"; 273 const std::string payload = word + std::string(256, 'a') + word; 274 AppendTo(&frames_, WebSocketFrameHeader::kOpCodeText, kFinal, payload); 275 predictor_->AddFramesToBeInput(frames_); 276 } 277 278 protected: 279 ScopedVector<WebSocketFrame> frames_; 280 }; 281 282 // ReadFrameStub is a stub for WebSocketStream::ReadFrames. 283 // It returns |result_| and |frames_to_output_| to the caller and 284 // saves parameters to |frames_passed_| and |callback_|. 285 class ReadFramesStub { 286 public: 287 explicit ReadFramesStub(int result) : result_(result) {} 288 289 ReadFramesStub(int result, ScopedVector<WebSocketFrame>* frames_to_output) 290 : result_(result) { 291 frames_to_output_.swap(*frames_to_output); 292 } 293 294 int Call(ScopedVector<WebSocketFrame>* frames, 295 const CompletionCallback& callback) { 296 DCHECK(frames->empty()); 297 frames_passed_ = frames; 298 callback_ = callback; 299 frames->swap(frames_to_output_); 300 return result_; 301 } 302 303 int result() const { return result_; } 304 const CompletionCallback callback() const { return callback_; } 305 ScopedVector<WebSocketFrame>* frames_passed() { 306 return frames_passed_; 307 } 308 309 private: 310 int result_; 311 CompletionCallback callback_; 312 ScopedVector<WebSocketFrame> frames_to_output_; 313 ScopedVector<WebSocketFrame>* frames_passed_; 314 }; 315 316 // WriteFramesStub is a stub for WebSocketStream::WriteFrames. 317 // It returns |result_| and |frames_| to the caller and 318 // saves |callback| parameter to |callback_|. 319 class WriteFramesStub { 320 public: 321 explicit WriteFramesStub(WebSocketDeflatePredictorMock* predictor, 322 int result) 323 : result_(result), predictor_(predictor) {} 324 325 int Call(ScopedVector<WebSocketFrame>* frames, 326 const CompletionCallback& callback) { 327 frames_.insert(frames_.end(), frames->begin(), frames->end()); 328 frames->weak_clear(); 329 callback_ = callback; 330 predictor_->VerifySentFrames(frames_); 331 return result_; 332 } 333 334 int result() const { return result_; } 335 const CompletionCallback callback() const { return callback_; } 336 ScopedVector<WebSocketFrame>* frames() { return &frames_; } 337 338 private: 339 int result_; 340 CompletionCallback callback_; 341 ScopedVector<WebSocketFrame> frames_; 342 WebSocketDeflatePredictorMock* predictor_; 343 }; 344 345 TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) { 346 ScopedVector<WebSocketFrame> frames; 347 CompletionCallback callback; 348 { 349 InSequence s; 350 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 351 .WillOnce(Return(ERR_FAILED)); 352 } 353 EXPECT_EQ(ERR_FAILED, deflate_stream_->ReadFrames(&frames, callback)); 354 } 355 356 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameImmediately) { 357 ScopedVector<WebSocketFrame> frames_to_output; 358 AppendTo(&frames_to_output, 359 WebSocketFrameHeader::kOpCodeText, 360 kFinal, 361 "hello"); 362 ReadFramesStub stub(OK, &frames_to_output); 363 ScopedVector<WebSocketFrame> frames; 364 365 { 366 InSequence s; 367 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 368 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 369 } 370 CompletionCallback callback; 371 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 372 ASSERT_EQ(1u, frames.size()); 373 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 374 EXPECT_TRUE(frames[0]->header.final); 375 EXPECT_FALSE(frames[0]->header.reserved1); 376 EXPECT_EQ("hello", ToString(frames[0])); 377 } 378 379 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) { 380 ReadFramesStub stub(ERR_IO_PENDING); 381 ScopedVector<WebSocketFrame> frames; 382 MockCallback mock_callback, checkpoint; 383 CompletionCallback callback = 384 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); 385 386 { 387 InSequence s; 388 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 389 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 390 EXPECT_CALL(checkpoint, Call(0)); 391 EXPECT_CALL(mock_callback, Call(OK)); 392 } 393 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); 394 ASSERT_EQ(0u, frames.size()); 395 396 checkpoint.Call(0); 397 398 AppendTo(stub.frames_passed(), 399 WebSocketFrameHeader::kOpCodeText, 400 kFinal, 401 "hello"); 402 stub.callback().Run(OK); 403 ASSERT_EQ(1u, frames.size()); 404 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 405 EXPECT_TRUE(frames[0]->header.final); 406 EXPECT_FALSE(frames[0]->header.reserved1); 407 EXPECT_EQ("hello", ToString(frames[0])); 408 } 409 410 TEST_F(WebSocketDeflateStreamTest, ReadFailedAsync) { 411 ReadFramesStub stub(ERR_IO_PENDING); 412 ScopedVector<WebSocketFrame> frames; 413 MockCallback mock_callback, checkpoint; 414 CompletionCallback callback = 415 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); 416 417 { 418 InSequence s; 419 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 420 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 421 EXPECT_CALL(checkpoint, Call(0)); 422 EXPECT_CALL(mock_callback, Call(ERR_FAILED)); 423 } 424 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); 425 ASSERT_EQ(0u, frames.size()); 426 427 checkpoint.Call(0); 428 429 AppendTo(stub.frames_passed(), 430 WebSocketFrameHeader::kOpCodeText, 431 kFinal, 432 "hello"); 433 stub.callback().Run(ERR_FAILED); 434 ASSERT_EQ(0u, frames.size()); 435 } 436 437 TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameImmediately) { 438 ScopedVector<WebSocketFrame> frames_to_output; 439 AppendTo(&frames_to_output, 440 WebSocketFrameHeader::kOpCodeText, 441 kFinal | kReserved1, 442 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 443 ReadFramesStub stub(OK, &frames_to_output); 444 CompletionCallback callback; 445 ScopedVector<WebSocketFrame> frames; 446 { 447 InSequence s; 448 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 449 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 450 } 451 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 452 ASSERT_EQ(1u, frames.size()); 453 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 454 EXPECT_TRUE(frames[0]->header.final); 455 EXPECT_FALSE(frames[0]->header.reserved1); 456 EXPECT_EQ("Hello", ToString(frames[0])); 457 } 458 459 TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameAsync) { 460 ReadFramesStub stub(ERR_IO_PENDING); 461 MockCallback mock_callback, checkpoint; 462 CompletionCallback callback = 463 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); 464 ScopedVector<WebSocketFrame> frames; 465 { 466 InSequence s; 467 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 468 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 469 EXPECT_CALL(checkpoint, Call(0)); 470 EXPECT_CALL(mock_callback, Call(OK)); 471 } 472 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); 473 474 checkpoint.Call(0); 475 476 AppendTo(stub.frames_passed(), 477 WebSocketFrameHeader::kOpCodeText, 478 kFinal | kReserved1, 479 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 480 stub.callback().Run(OK); 481 482 ASSERT_EQ(1u, frames.size()); 483 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 484 EXPECT_TRUE(frames[0]->header.final); 485 EXPECT_FALSE(frames[0]->header.reserved1); 486 EXPECT_EQ("Hello", ToString(frames[0])); 487 } 488 489 TEST_F(WebSocketDeflateStreamTest, 490 ReadCompressedFrameFragmentImmediatelyButInflaterReturnsPending) { 491 ScopedVector<WebSocketFrame> frames_to_output; 492 const std::string data1("\xf2", 1); 493 const std::string data2("\x48\xcd\xc9\xc9\x07\x00", 6); 494 AppendTo(&frames_to_output, 495 WebSocketFrameHeader::kOpCodeText, 496 kReserved1, 497 data1); 498 ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING); 499 MockCallback mock_callback, checkpoint; 500 CompletionCallback callback = 501 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); 502 ScopedVector<WebSocketFrame> frames; 503 504 { 505 InSequence s; 506 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 507 .WillOnce(Invoke(&stub1, &ReadFramesStub::Call)) 508 .WillOnce(Invoke(&stub2, &ReadFramesStub::Call)); 509 EXPECT_CALL(checkpoint, Call(0)); 510 EXPECT_CALL(mock_callback, Call(OK)); 511 } 512 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); 513 ASSERT_EQ(0u, frames.size()); 514 515 AppendTo(stub2.frames_passed(), 516 WebSocketFrameHeader::kOpCodeText, 517 kFinal, 518 data2); 519 520 checkpoint.Call(0); 521 stub2.callback().Run(OK); 522 523 ASSERT_EQ(1u, frames.size()); 524 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 525 EXPECT_TRUE(frames[0]->header.final); 526 EXPECT_FALSE(frames[0]->header.reserved1); 527 EXPECT_EQ("Hello", ToString(frames[0])); 528 } 529 530 TEST_F(WebSocketDeflateStreamTest, ReadInvalidCompressedPayload) { 531 const std::string data("\xf2\x48\xcdINVALID", 10); 532 ScopedVector<WebSocketFrame> frames_to_output; 533 AppendTo(&frames_to_output, 534 WebSocketFrameHeader::kOpCodeText, 535 kFinal | kReserved1, 536 data); 537 ReadFramesStub stub(OK, &frames_to_output); 538 CompletionCallback callback; 539 ScopedVector<WebSocketFrame> frames; 540 541 { 542 InSequence s; 543 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 544 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 545 } 546 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR, 547 deflate_stream_->ReadFrames(&frames, callback)); 548 ASSERT_EQ(0u, frames.size()); 549 } 550 551 TEST_F(WebSocketDeflateStreamTest, MergeMultipleFramesInReadFrames) { 552 const std::string data1("\xf2\x48\xcd", 3); 553 const std::string data2("\xc9\xc9\x07\x00", 4); 554 ScopedVector<WebSocketFrame> frames_to_output; 555 AppendTo(&frames_to_output, 556 WebSocketFrameHeader::kOpCodeText, 557 kReserved1, 558 data1); 559 AppendTo(&frames_to_output, 560 WebSocketFrameHeader::kOpCodeContinuation, 561 kFinal, 562 data2); 563 ReadFramesStub stub(OK, &frames_to_output); 564 CompletionCallback callback; 565 ScopedVector<WebSocketFrame> frames; 566 567 { 568 InSequence s; 569 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 570 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 571 } 572 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 573 ASSERT_EQ(1u, frames.size()); 574 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 575 EXPECT_TRUE(frames[0]->header.final); 576 EXPECT_FALSE(frames[0]->header.reserved1); 577 EXPECT_EQ("Hello", ToString(frames[0])); 578 } 579 580 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedEmptyFrames) { 581 ScopedVector<WebSocketFrame> frames_to_output; 582 AppendTo(&frames_to_output, 583 WebSocketFrameHeader::kOpCodeText, 584 kNoFlag); 585 AppendTo(&frames_to_output, 586 WebSocketFrameHeader::kOpCodeContinuation, 587 kFinal); 588 ReadFramesStub stub(OK, &frames_to_output); 589 CompletionCallback callback; 590 ScopedVector<WebSocketFrame> frames; 591 592 { 593 InSequence s; 594 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 595 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 596 } 597 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 598 ASSERT_EQ(2u, frames.size()); 599 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 600 EXPECT_FALSE(frames[0]->header.final); 601 EXPECT_FALSE(frames[0]->header.reserved1); 602 EXPECT_EQ("", ToString(frames[0])); 603 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 604 frames[1]->header.opcode); 605 EXPECT_TRUE(frames[1]->header.final); 606 EXPECT_FALSE(frames[1]->header.reserved1); 607 EXPECT_EQ("", ToString(frames[1])); 608 } 609 610 TEST_F(WebSocketDeflateStreamTest, ReadCompressedEmptyFrames) { 611 ScopedVector<WebSocketFrame> frames_to_output; 612 AppendTo(&frames_to_output, 613 WebSocketFrameHeader::kOpCodeText, 614 kReserved1, 615 std::string("\x02\x00", 1)); 616 AppendTo(&frames_to_output, 617 WebSocketFrameHeader::kOpCodeContinuation, 618 kFinal); 619 ReadFramesStub stub(OK, &frames_to_output); 620 CompletionCallback callback; 621 ScopedVector<WebSocketFrame> frames; 622 623 { 624 InSequence s; 625 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 626 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 627 } 628 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 629 ASSERT_EQ(1u, frames.size()); 630 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 631 EXPECT_TRUE(frames[0]->header.final); 632 EXPECT_FALSE(frames[0]->header.reserved1); 633 EXPECT_EQ("", ToString(frames[0])); 634 } 635 636 TEST_F(WebSocketDeflateStreamTest, 637 ReadCompressedFrameFollowedByEmptyFrame) { 638 const std::string data("\xf2\x48\xcd\xc9\xc9\x07\x00", 7); 639 ScopedVector<WebSocketFrame> frames_to_output; 640 AppendTo(&frames_to_output, 641 WebSocketFrameHeader::kOpCodeText, 642 kReserved1, 643 data); 644 AppendTo(&frames_to_output, 645 WebSocketFrameHeader::kOpCodeContinuation, 646 kFinal); 647 ReadFramesStub stub(OK, &frames_to_output); 648 CompletionCallback callback; 649 ScopedVector<WebSocketFrame> frames; 650 651 { 652 InSequence s; 653 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 654 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 655 } 656 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 657 ASSERT_EQ(1u, frames.size()); 658 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 659 EXPECT_TRUE(frames[0]->header.final); 660 EXPECT_FALSE(frames[0]->header.reserved1); 661 EXPECT_EQ("Hello", ToString(frames[0])); 662 } 663 664 TEST_F(WebSocketDeflateStreamTest, ReadControlFrameBetweenDataFrames) { 665 const std::string data1("\xf2\x48\xcd", 3); 666 const std::string data2("\xc9\xc9\x07\x00", 4); 667 ScopedVector<WebSocketFrame> frames_to_output; 668 AppendTo(&frames_to_output, 669 WebSocketFrameHeader::kOpCodeText, 670 kReserved1, 671 data1); 672 AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodePing, kFinal); 673 AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodeText, kFinal, data2); 674 ReadFramesStub stub(OK, &frames_to_output); 675 CompletionCallback callback; 676 ScopedVector<WebSocketFrame> frames; 677 678 { 679 InSequence s; 680 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 681 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 682 } 683 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 684 ASSERT_EQ(2u, frames.size()); 685 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames[0]->header.opcode); 686 EXPECT_TRUE(frames[0]->header.final); 687 EXPECT_FALSE(frames[0]->header.reserved1); 688 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); 689 EXPECT_TRUE(frames[1]->header.final); 690 EXPECT_FALSE(frames[1]->header.reserved1); 691 EXPECT_EQ("Hello", ToString(frames[1])); 692 } 693 694 TEST_F(WebSocketDeflateStreamTest, SplitToMultipleFramesInReadFrames) { 695 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); 696 deflater.Initialize(kWindowBits); 697 const size_t kSize = kChunkSize * 3; 698 const std::string original_data(kSize, 'a'); 699 deflater.AddBytes(original_data.data(), original_data.size()); 700 deflater.Finish(); 701 702 ScopedVector<WebSocketFrame> frames_to_output; 703 AppendTo(&frames_to_output, 704 WebSocketFrameHeader::kOpCodeBinary, 705 kFinal | kReserved1, 706 ToString(deflater.GetOutput(deflater.CurrentOutputSize()))); 707 708 ReadFramesStub stub(OK, &frames_to_output); 709 CompletionCallback callback; 710 ScopedVector<WebSocketFrame> frames; 711 { 712 InSequence s; 713 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 714 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 715 } 716 717 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 718 ASSERT_EQ(3u, frames.size()); 719 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode); 720 EXPECT_FALSE(frames[0]->header.final); 721 EXPECT_FALSE(frames[0]->header.reserved1); 722 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length)); 723 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 724 frames[1]->header.opcode); 725 EXPECT_FALSE(frames[1]->header.final); 726 EXPECT_FALSE(frames[1]->header.reserved1); 727 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[1]->header.payload_length)); 728 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 729 frames[2]->header.opcode); 730 EXPECT_TRUE(frames[2]->header.final); 731 EXPECT_FALSE(frames[2]->header.reserved1); 732 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[2]->header.payload_length)); 733 EXPECT_EQ(original_data, 734 ToString(frames[0]) + ToString(frames[1]) + ToString(frames[2])); 735 } 736 737 TEST_F(WebSocketDeflateStreamTest, InflaterInternalDataCanBeEmpty) { 738 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); 739 deflater.Initialize(kWindowBits); 740 const std::string original_data(kChunkSize, 'a'); 741 deflater.AddBytes(original_data.data(), original_data.size()); 742 deflater.Finish(); 743 744 ScopedVector<WebSocketFrame> frames_to_output; 745 AppendTo(&frames_to_output, 746 WebSocketFrameHeader::kOpCodeBinary, 747 kReserved1, 748 ToString(deflater.GetOutput(deflater.CurrentOutputSize()))); 749 AppendTo(&frames_to_output, 750 WebSocketFrameHeader::kOpCodeBinary, 751 kFinal, 752 ""); 753 754 ReadFramesStub stub(OK, &frames_to_output); 755 CompletionCallback callback; 756 ScopedVector<WebSocketFrame> frames; 757 { 758 InSequence s; 759 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 760 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 761 } 762 763 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 764 ASSERT_EQ(2u, frames.size()); 765 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode); 766 EXPECT_FALSE(frames[0]->header.final); 767 EXPECT_FALSE(frames[0]->header.reserved1); 768 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length)); 769 770 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 771 frames[1]->header.opcode); 772 EXPECT_TRUE(frames[1]->header.final); 773 EXPECT_FALSE(frames[1]->header.reserved1); 774 EXPECT_EQ(0u, static_cast<size_t>(frames[1]->header.payload_length)); 775 EXPECT_EQ(original_data, ToString(frames[0]) + ToString(frames[1])); 776 } 777 778 TEST_F(WebSocketDeflateStreamTest, 779 Reserved1TurnsOnDuringReadingCompressedContinuationFrame) { 780 const std::string data1("\xf2\x48\xcd", 3); 781 const std::string data2("\xc9\xc9\x07\x00", 4); 782 ScopedVector<WebSocketFrame> frames_to_output; 783 AppendTo(&frames_to_output, 784 WebSocketFrameHeader::kOpCodeText, 785 kReserved1, 786 data1); 787 AppendTo(&frames_to_output, 788 WebSocketFrameHeader::kOpCodeContinuation, 789 kFinal | kReserved1, 790 data2); 791 ReadFramesStub stub(OK, &frames_to_output); 792 CompletionCallback callback; 793 ScopedVector<WebSocketFrame> frames; 794 795 { 796 InSequence s; 797 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 798 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 799 } 800 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR, 801 deflate_stream_->ReadFrames(&frames, callback)); 802 } 803 804 TEST_F(WebSocketDeflateStreamTest, 805 Reserved1TurnsOnDuringReadingUncompressedContinuationFrame) { 806 ScopedVector<WebSocketFrame> frames_to_output; 807 AppendTo(&frames_to_output, 808 WebSocketFrameHeader::kOpCodeText, 809 kNoFlag, 810 "hello"); 811 AppendTo(&frames_to_output, 812 WebSocketFrameHeader::kOpCodeContinuation, 813 kFinal | kReserved1, 814 "world"); 815 ReadFramesStub stub(OK, &frames_to_output); 816 CompletionCallback callback; 817 ScopedVector<WebSocketFrame> frames; 818 819 { 820 InSequence s; 821 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 822 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 823 } 824 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR, 825 deflate_stream_->ReadFrames(&frames, callback)); 826 } 827 828 TEST_F(WebSocketDeflateStreamTest, ReadCompressedMessages) { 829 ScopedVector<WebSocketFrame> frames_to_output; 830 AppendTo(&frames_to_output, 831 WebSocketFrameHeader::kOpCodeText, 832 kFinal | kReserved1, 833 std::string( 834 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13)); 835 AppendTo(&frames_to_output, 836 WebSocketFrameHeader::kOpCodeText, 837 kFinal | kReserved1, 838 std::string("\x4a\x86\x33\x8d\x00\x00", 6)); 839 ReadFramesStub stub(OK, &frames_to_output); 840 CompletionCallback callback; 841 ScopedVector<WebSocketFrame> frames; 842 843 { 844 InSequence s; 845 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 846 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 847 } 848 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 849 ASSERT_EQ(2u, frames.size()); 850 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 851 EXPECT_TRUE(frames[0]->header.final); 852 EXPECT_FALSE(frames[0]->header.reserved1); 853 EXPECT_EQ("compressed1", ToString(frames[0])); 854 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); 855 EXPECT_TRUE(frames[1]->header.final); 856 EXPECT_FALSE(frames[1]->header.reserved1); 857 EXPECT_EQ("compressed2", ToString(frames[1])); 858 } 859 860 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedMessages) { 861 ScopedVector<WebSocketFrame> frames_to_output; 862 AppendTo(&frames_to_output, 863 WebSocketFrameHeader::kOpCodeText, 864 kFinal, 865 "uncompressed1"); 866 AppendTo(&frames_to_output, 867 WebSocketFrameHeader::kOpCodeText, 868 kFinal, 869 "uncompressed2"); 870 ReadFramesStub stub(OK, &frames_to_output); 871 CompletionCallback callback; 872 ScopedVector<WebSocketFrame> frames; 873 874 { 875 InSequence s; 876 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 877 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 878 } 879 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 880 ASSERT_EQ(2u, frames.size()); 881 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 882 EXPECT_TRUE(frames[0]->header.final); 883 EXPECT_FALSE(frames[0]->header.reserved1); 884 EXPECT_EQ("uncompressed1", ToString(frames[0])); 885 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); 886 EXPECT_TRUE(frames[1]->header.final); 887 EXPECT_FALSE(frames[1]->header.reserved1); 888 EXPECT_EQ("uncompressed2", ToString(frames[1])); 889 } 890 891 TEST_F(WebSocketDeflateStreamTest, 892 ReadCompressedMessageThenUncompressedMessage) { 893 ScopedVector<WebSocketFrame> frames_to_output; 894 AppendTo(&frames_to_output, 895 WebSocketFrameHeader::kOpCodeText, 896 kFinal | kReserved1, 897 std::string( 898 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12)); 899 AppendTo(&frames_to_output, 900 WebSocketFrameHeader::kOpCodeText, 901 kFinal, 902 "uncompressed"); 903 ReadFramesStub stub(OK, &frames_to_output); 904 CompletionCallback callback; 905 ScopedVector<WebSocketFrame> frames; 906 907 { 908 InSequence s; 909 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 910 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 911 } 912 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 913 ASSERT_EQ(2u, frames.size()); 914 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 915 EXPECT_TRUE(frames[0]->header.final); 916 EXPECT_FALSE(frames[0]->header.reserved1); 917 EXPECT_EQ("compressed", ToString(frames[0])); 918 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); 919 EXPECT_TRUE(frames[1]->header.final); 920 EXPECT_FALSE(frames[1]->header.reserved1); 921 EXPECT_EQ("uncompressed", ToString(frames[1])); 922 } 923 924 TEST_F(WebSocketDeflateStreamTest, 925 ReadUncompressedMessageThenCompressedMessage) { 926 ScopedVector<WebSocketFrame> frames_to_output; 927 AppendTo(&frames_to_output, 928 WebSocketFrameHeader::kOpCodeText, 929 kFinal, 930 "uncompressed"); 931 AppendTo(&frames_to_output, 932 WebSocketFrameHeader::kOpCodeText, 933 kFinal | kReserved1, 934 std::string( 935 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12)); 936 ReadFramesStub stub(OK, &frames_to_output); 937 CompletionCallback callback; 938 ScopedVector<WebSocketFrame> frames; 939 940 { 941 InSequence s; 942 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 943 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); 944 } 945 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); 946 ASSERT_EQ(2u, frames.size()); 947 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 948 EXPECT_TRUE(frames[0]->header.final); 949 EXPECT_FALSE(frames[0]->header.reserved1); 950 EXPECT_EQ("uncompressed", ToString(frames[0])); 951 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); 952 EXPECT_TRUE(frames[1]->header.final); 953 EXPECT_FALSE(frames[1]->header.reserved1); 954 EXPECT_EQ("compressed", ToString(frames[1])); 955 } 956 957 // This is a regression test for crbug.com/343506. 958 TEST_F(WebSocketDeflateStreamTest, ReadEmptyAsyncFrame) { 959 ScopedVector<ReadFramesStub> stub_vector; 960 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING)); 961 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING)); 962 MockCallback mock_callback; 963 CompletionCallback callback = 964 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); 965 ScopedVector<WebSocketFrame> frames; 966 967 { 968 InSequence s; 969 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 970 .WillOnce(Invoke(stub_vector[0], &ReadFramesStub::Call)); 971 972 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) 973 .WillOnce(Invoke(stub_vector[1], &ReadFramesStub::Call)); 974 975 EXPECT_CALL(mock_callback, Call(OK)); 976 } 977 978 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); 979 AppendTo(stub_vector[0]->frames_passed(), 980 WebSocketFrameHeader::kOpCodeText, 981 kReserved1, 982 std::string()); 983 stub_vector[0]->callback().Run(OK); 984 AppendTo(stub_vector[1]->frames_passed(), 985 WebSocketFrameHeader::kOpCodeContinuation, 986 kFinal, 987 std::string("\x02\x00")); 988 stub_vector[1]->callback().Run(OK); 989 ASSERT_EQ(1u, frames.size()); 990 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); 991 EXPECT_EQ("", ToString(frames[0])); 992 } 993 994 TEST_F(WebSocketDeflateStreamTest, WriteEmpty) { 995 ScopedVector<WebSocketFrame> frames; 996 CompletionCallback callback; 997 { 998 InSequence s; 999 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0); 1000 } 1001 EXPECT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1002 } 1003 1004 TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) { 1005 ScopedVector<WebSocketFrame> frames; 1006 CompletionCallback callback; 1007 { 1008 InSequence s; 1009 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1010 .WillOnce(Return(ERR_FAILED)); 1011 } 1012 1013 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello"); 1014 predictor_->AddFramesToBeInput(frames); 1015 EXPECT_EQ(ERR_FAILED, deflate_stream_->WriteFrames(&frames, callback)); 1016 predictor_->Clear(); 1017 } 1018 1019 TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) { 1020 ScopedVector<WebSocketFrame> frames; 1021 CompletionCallback callback; 1022 WriteFramesStub stub(predictor_, OK); 1023 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); 1024 predictor_->AddFramesToBeInput(frames); 1025 { 1026 InSequence s; 1027 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) 1028 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1029 } 1030 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1031 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1032 ASSERT_EQ(1u, frames_passed.size()); 1033 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); 1034 EXPECT_TRUE(frames_passed[0]->header.final); 1035 EXPECT_TRUE(frames_passed[0]->header.reserved1); 1036 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), 1037 ToString(frames_passed[0])); 1038 } 1039 1040 TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) { 1041 WriteFramesStub stub(predictor_, ERR_IO_PENDING); 1042 MockCallback mock_callback, checkpoint; 1043 CompletionCallback callback = 1044 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); 1045 ScopedVector<WebSocketFrame> frames; 1046 { 1047 InSequence s; 1048 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1049 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1050 EXPECT_CALL(checkpoint, Call(0)); 1051 EXPECT_CALL(mock_callback, Call(OK)); 1052 } 1053 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); 1054 predictor_->AddFramesToBeInput(frames); 1055 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->WriteFrames(&frames, callback)); 1056 1057 checkpoint.Call(0); 1058 stub.callback().Run(OK); 1059 1060 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1061 ASSERT_EQ(1u, frames_passed.size()); 1062 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); 1063 EXPECT_TRUE(frames_passed[0]->header.final); 1064 EXPECT_TRUE(frames_passed[0]->header.reserved1); 1065 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), 1066 ToString(frames_passed[0])); 1067 } 1068 1069 TEST_F(WebSocketDeflateStreamTest, WriteControlFrameBetweenDataFrames) { 1070 ScopedVector<WebSocketFrame> frames; 1071 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "Hel"); 1072 AppendTo(&frames, WebSocketFrameHeader::kOpCodePing, kFinal); 1073 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "lo"); 1074 predictor_->AddFramesToBeInput(frames); 1075 WriteFramesStub stub(predictor_, OK); 1076 CompletionCallback callback; 1077 1078 { 1079 InSequence s; 1080 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1081 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1082 } 1083 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1084 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1085 ASSERT_EQ(2u, frames_passed.size()); 1086 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames_passed[0]->header.opcode); 1087 EXPECT_TRUE(frames_passed[0]->header.final); 1088 EXPECT_FALSE(frames_passed[0]->header.reserved1); 1089 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode); 1090 EXPECT_TRUE(frames_passed[1]->header.final); 1091 EXPECT_TRUE(frames_passed[1]->header.reserved1); 1092 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), 1093 ToString(frames_passed[1])); 1094 } 1095 1096 TEST_F(WebSocketDeflateStreamTest, WriteEmptyMessage) { 1097 ScopedVector<WebSocketFrame> frames; 1098 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal); 1099 predictor_->AddFramesToBeInput(frames); 1100 WriteFramesStub stub(predictor_, OK); 1101 CompletionCallback callback; 1102 1103 { 1104 InSequence s; 1105 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1106 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1107 } 1108 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1109 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1110 ASSERT_EQ(1u, frames_passed.size()); 1111 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); 1112 EXPECT_TRUE(frames_passed[0]->header.final); 1113 EXPECT_TRUE(frames_passed[0]->header.reserved1); 1114 EXPECT_EQ(std::string("\x00", 1), ToString(frames_passed[0])); 1115 } 1116 1117 TEST_F(WebSocketDeflateStreamTest, WriteUncompressedMessage) { 1118 ScopedVector<WebSocketFrame> frames; 1119 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAA"); 1120 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AAA"); 1121 predictor_->AddFramesToBeInput(frames); 1122 WriteFramesStub stub(predictor_, OK); 1123 CompletionCallback callback; 1124 1125 predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE); 1126 1127 { 1128 InSequence s; 1129 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1130 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1131 } 1132 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1133 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1134 ASSERT_EQ(2u, frames_passed.size()); 1135 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); 1136 EXPECT_FALSE(frames_passed[0]->header.final); 1137 EXPECT_FALSE(frames_passed[0]->header.reserved1); 1138 EXPECT_EQ("AAAA", ToString(frames_passed[0])); 1139 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 1140 frames_passed[1]->header.opcode); 1141 EXPECT_TRUE(frames_passed[1]->header.final); 1142 EXPECT_FALSE(frames_passed[1]->header.reserved1); 1143 EXPECT_EQ("AAA", ToString(frames_passed[1])); 1144 } 1145 1146 TEST_F(WebSocketDeflateStreamTest, LargeDeflatedFramesShouldBeSplit) { 1147 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); 1148 LinearCongruentialGenerator lcg(133); 1149 WriteFramesStub stub(predictor_, OK); 1150 CompletionCallback callback; 1151 const size_t size = 1024; 1152 1153 { 1154 InSequence s; 1155 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) 1156 .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call)); 1157 } 1158 ScopedVector<WebSocketFrame> total_compressed_frames; 1159 1160 deflater.Initialize(kWindowBits); 1161 while (true) { 1162 bool is_final = (total_compressed_frames.size() >= 2); 1163 ScopedVector<WebSocketFrame> frames; 1164 std::string data; 1165 for (size_t i = 0; i < size; ++i) 1166 data += static_cast<char>(lcg.Generate()); 1167 deflater.AddBytes(data.data(), data.size()); 1168 FrameFlag flag = is_final ? kFinal : kNoFlag; 1169 AppendTo(&frames, WebSocketFrameHeader::kOpCodeBinary, flag, data); 1170 predictor_->AddFramesToBeInput(frames); 1171 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1172 total_compressed_frames.insert(total_compressed_frames.end(), 1173 stub.frames()->begin(), 1174 stub.frames()->end()); 1175 stub.frames()->weak_clear(); 1176 if (is_final) 1177 break; 1178 } 1179 deflater.Finish(); 1180 std::string total_deflated; 1181 for (size_t i = 0; i < total_compressed_frames.size(); ++i) { 1182 WebSocketFrame* frame = total_compressed_frames[i]; 1183 const WebSocketFrameHeader& header = frame->header; 1184 if (i > 0) { 1185 EXPECT_EQ(header.kOpCodeContinuation, header.opcode); 1186 EXPECT_FALSE(header.reserved1); 1187 } else { 1188 EXPECT_EQ(header.kOpCodeBinary, header.opcode); 1189 EXPECT_TRUE(header.reserved1); 1190 } 1191 const bool is_final_frame = (i + 1 == total_compressed_frames.size()); 1192 EXPECT_EQ(is_final_frame, header.final); 1193 if (!is_final_frame) 1194 EXPECT_GT(header.payload_length, 0ul); 1195 total_deflated += ToString(frame); 1196 } 1197 EXPECT_EQ(total_deflated, 1198 ToString(deflater.GetOutput(deflater.CurrentOutputSize()))); 1199 } 1200 1201 TEST_F(WebSocketDeflateStreamTest, WriteMultipleMessages) { 1202 ScopedVector<WebSocketFrame> frames; 1203 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); 1204 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); 1205 predictor_->AddFramesToBeInput(frames); 1206 WriteFramesStub stub(predictor_, OK); 1207 CompletionCallback callback; 1208 1209 { 1210 InSequence s; 1211 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1212 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1213 } 1214 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1215 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1216 ASSERT_EQ(2u, frames_passed.size()); 1217 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); 1218 EXPECT_TRUE(frames_passed[0]->header.final); 1219 EXPECT_TRUE(frames_passed[0]->header.reserved1); 1220 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), 1221 ToString(frames_passed[0])); 1222 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode); 1223 EXPECT_TRUE(frames_passed[1]->header.final); 1224 EXPECT_TRUE(frames_passed[1]->header.reserved1); 1225 EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed[1])); 1226 } 1227 1228 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest, 1229 WriteMultipleMessages) { 1230 ScopedVector<WebSocketFrame> frames; 1231 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); 1232 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); 1233 predictor_->AddFramesToBeInput(frames); 1234 WriteFramesStub stub(predictor_, OK); 1235 CompletionCallback callback; 1236 1237 { 1238 InSequence s; 1239 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1240 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1241 } 1242 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1243 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1244 ASSERT_EQ(2u, frames_passed.size()); 1245 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); 1246 EXPECT_TRUE(frames_passed[0]->header.final); 1247 EXPECT_TRUE(frames_passed[0]->header.reserved1); 1248 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), 1249 ToString(frames_passed[0])); 1250 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode); 1251 EXPECT_TRUE(frames_passed[1]->header.final); 1252 EXPECT_TRUE(frames_passed[1]->header.reserved1); 1253 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), 1254 ToString(frames_passed[1])); 1255 } 1256 1257 // In order to check the stream works correctly for multiple 1258 // "PossiblyCompressedMessage"s, we test various messages at one test case. 1259 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest, 1260 WritePossiblyCompressMessages) { 1261 ScopedVector<WebSocketFrame> frames; 1262 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "He"); 1263 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "llo"); 1264 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAAAAAAAA"); 1265 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AA"); 1266 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "XX"); 1267 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "YY"); 1268 predictor_->AddFramesToBeInput(frames); 1269 WriteFramesStub stub(predictor_, OK); 1270 CompletionCallback callback; 1271 predictor_->set_result(WebSocketDeflatePredictor::TRY_DEFLATE); 1272 1273 { 1274 InSequence s; 1275 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) 1276 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1277 } 1278 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); 1279 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1280 ASSERT_EQ(5u, frames_passed.size()); 1281 1282 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); 1283 EXPECT_FALSE(frames_passed[0]->header.final); 1284 EXPECT_FALSE(frames_passed[0]->header.reserved1); 1285 EXPECT_EQ("He", ToString(frames_passed[0])); 1286 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 1287 frames_passed[1]->header.opcode); 1288 EXPECT_TRUE(frames_passed[1]->header.final); 1289 EXPECT_FALSE(frames_passed[1]->header.reserved1); 1290 EXPECT_EQ("llo", ToString(frames_passed[1])); 1291 1292 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[2]->header.opcode); 1293 EXPECT_TRUE(frames_passed[2]->header.final); 1294 EXPECT_TRUE(frames_passed[2]->header.reserved1); 1295 EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6), 1296 ToString(frames_passed[2])); 1297 1298 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[3]->header.opcode); 1299 EXPECT_FALSE(frames_passed[3]->header.final); 1300 EXPECT_FALSE(frames_passed[3]->header.reserved1); 1301 EXPECT_EQ("XX", ToString(frames_passed[3])); 1302 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, 1303 frames_passed[4]->header.opcode); 1304 EXPECT_TRUE(frames_passed[4]->header.final); 1305 EXPECT_FALSE(frames_passed[4]->header.reserved1); 1306 EXPECT_EQ("YY", ToString(frames_passed[4])); 1307 } 1308 1309 // This is based on the similar test from websocket_deflater_test.cc 1310 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits8) { 1311 SetUpWithWindowBits(8); 1312 CompletionCallback callback; 1313 AddCompressibleFrameString(); 1314 WriteFramesStub stub(predictor_, OK); 1315 { 1316 InSequence s; 1317 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) 1318 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1319 } 1320 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback)); 1321 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1322 ASSERT_EQ(1u, frames_passed.size()); 1323 EXPECT_EQ(std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x39\xa3" 1324 "(?7\xb3\x34\x17\x00", 21), 1325 ToString(frames_passed[0])); 1326 } 1327 1328 // The same input with window_bits=10 returns smaller output. 1329 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits10) { 1330 SetUpWithWindowBits(10); 1331 CompletionCallback callback; 1332 AddCompressibleFrameString(); 1333 WriteFramesStub stub(predictor_, OK); 1334 { 1335 InSequence s; 1336 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) 1337 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); 1338 } 1339 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback)); 1340 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); 1341 ASSERT_EQ(1u, frames_passed.size()); 1342 EXPECT_EQ( 1343 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17), 1344 ToString(frames_passed[0])); 1345 } 1346 1347 } // namespace 1348 1349 } // namespace net 1350