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