| OLD | NEW |
| (Empty) |
| 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 ~WebSocketDeflatePredictorMock() override { | |
| 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 Result Predict(const ScopedVector<WebSocketFrame>& frames, | |
| 128 size_t frame_index) override { | |
| 129 return result_; | |
| 130 } | |
| 131 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 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 ~WebSocketDeflateStreamTest() override {} | |
| 216 | |
| 217 void SetUp() override { | |
| 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 ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() override {} | |
| 249 | |
| 250 void SetUp() override { | |
| 251 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT, kWindowBits); | |
| 252 } | |
| 253 }; | |
| 254 | |
| 255 class WebSocketDeflateStreamWithClientWindowBitsTest | |
| 256 : public WebSocketDeflateStreamTest { | |
| 257 public: | |
| 258 WebSocketDeflateStreamWithClientWindowBitsTest() {} | |
| 259 ~WebSocketDeflateStreamWithClientWindowBitsTest() override {} | |
| 260 | |
| 261 // Overridden to postpone the call to Initialize(). | |
| 262 void SetUp() override {} | |
| 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 | |
| OLD | NEW |