Show Pages in chrome://md-settings
[chromium-blink-merge.git] / net / websockets / websocket_deflate_stream_test.cc
blobc30ab3287092d2cd0eae828ff241d5b9bef7e885
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.
5 #include "net/websockets/websocket_deflate_stream.h"
7 #include <stdint.h>
8 #include <deque>
9 #include <string>
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"
28 namespace net {
29 namespace {
31 typedef ::testing::MockFunction<void(int)> MockCallback; // NOLINT
32 using ::testing::_;
33 using ::testing::InSequence;
34 using ::testing::Invoke;
35 using ::testing::Return;
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.
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;
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;
54 std::string ToString(IOBufferWithSize* buffer) {
55 return std::string(buffer->data(), buffer->size());
58 std::string ToString(const scoped_refptr<IOBufferWithSize>& buffer) {
59 return ToString(buffer.get());
62 std::string ToString(IOBuffer* buffer, size_t size) {
63 return std::string(buffer->data(), size);
66 std::string ToString(const scoped_refptr<IOBuffer>& buffer, size_t size) {
67 return ToString(buffer.get(), size);
70 std::string ToString(const WebSocketFrame* frame) {
71 return frame->data.get() ? ToString(frame->data, frame->header.payload_length)
72 : "";
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());
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());
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());
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;
120 if (!frames_written_.empty()) {
121 ADD_FAILURE() << "There are extra written frames.";
122 return;
126 // WebSocketDeflatePredictor functions.
127 Result Predict(const ScopedVector<WebSocketFrame>& frames,
128 size_t frame_index) override {
129 return result_;
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;
136 if (frame->header.reserved1) {
137 ADD_FAILURE() << "Input frame may not be compressed.";
138 return;
140 if (frames_to_be_input_.empty()) {
141 ADD_FAILURE() << "Unexpected input data frame";
142 return;
144 if (frame != frames_to_be_input_.front()) {
145 ADD_FAILURE() << "Input data frame does not match the expectation.";
146 return;
148 frames_to_be_input_.pop_front();
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;
155 frames_written_.push_back(frame);
158 // Sets |result_| for the |Predict| return value.
159 void set_result(Result result) { result_ = result; }
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);
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;
175 if (frame != frames_written_.front()) {
176 ADD_FAILURE() << "Written data frame does not match the expectation.";
177 return;
179 frames_written_.pop_front();
181 void AddFramesToBeInput(const ScopedVector<WebSocketFrame>& frames) {
182 for (size_t i = 0; i < frames.size(); ++i)
183 AddFrameToBeInput(frames[i]);
185 void VerifySentFrames(const ScopedVector<WebSocketFrame>& frames) {
186 for (size_t i = 0; i < frames.size(); ++i)
187 VerifySentFrame(frames[i]);
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();
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_;
207 DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock);
210 class WebSocketDeflateStreamTest : public ::testing::Test {
211 public:
212 WebSocketDeflateStreamTest()
213 : mock_stream_(NULL),
214 predictor_(NULL) {}
215 ~WebSocketDeflateStreamTest() override {}
217 void SetUp() override {
218 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, kWindowBits);
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_)));
234 scoped_ptr<WebSocketDeflateStream> deflate_stream_;
235 // Owned by |deflate_stream_|.
236 MockWebSocketStream* mock_stream_;
237 // Owned by |deflate_stream_|.
238 WebSocketDeflatePredictorMock* predictor_;
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 {}
250 void SetUp() override {
251 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT, kWindowBits);
255 class WebSocketDeflateStreamWithClientWindowBitsTest
256 : public WebSocketDeflateStreamTest {
257 public:
258 WebSocketDeflateStreamWithClientWindowBitsTest() {}
259 ~WebSocketDeflateStreamWithClientWindowBitsTest() override {}
261 // Overridden to postpone the call to Initialize().
262 void SetUp() override {}
264 // This needs to be called explicitly from the tests.
265 void SetUpWithWindowBits(int window_bits) {
266 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, window_bits);
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_);
278 protected:
279 ScopedVector<WebSocketFrame> frames_;
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) {}
289 ReadFramesStub(int result, ScopedVector<WebSocketFrame>* frames_to_output)
290 : result_(result) {
291 frames_to_output_.swap(*frames_to_output);
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_;
303 int result() const { return result_; }
304 const CompletionCallback callback() const { return callback_; }
305 ScopedVector<WebSocketFrame>* frames_passed() {
306 return frames_passed_;
309 private:
310 int result_;
311 CompletionCallback callback_;
312 ScopedVector<WebSocketFrame> frames_to_output_;
313 ScopedVector<WebSocketFrame>* frames_passed_;
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) {}
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_;
334 int result() const { return result_; }
335 const CompletionCallback callback() const { return callback_; }
336 ScopedVector<WebSocketFrame>* frames() { return &frames_; }
338 private:
339 int result_;
340 CompletionCallback callback_;
341 ScopedVector<WebSocketFrame> frames_;
342 WebSocketDeflatePredictorMock* predictor_;
345 TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) {
346 ScopedVector<WebSocketFrame> frames;
347 CompletionCallback callback;
349 InSequence s;
350 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
351 .WillOnce(Return(ERR_FAILED));
353 EXPECT_EQ(ERR_FAILED, deflate_stream_->ReadFrames(&frames, callback));
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;
366 InSequence s;
367 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
368 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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));
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));
393 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
394 ASSERT_EQ(0u, frames.size());
396 checkpoint.Call(0);
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]));
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));
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));
424 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
425 ASSERT_EQ(0u, frames.size());
427 checkpoint.Call(0);
429 AppendTo(stub.frames_passed(),
430 WebSocketFrameHeader::kOpCodeText,
431 kFinal,
432 "hello");
433 stub.callback().Run(ERR_FAILED);
434 ASSERT_EQ(0u, frames.size());
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;
447 InSequence s;
448 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
449 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
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));
472 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
474 checkpoint.Call(0);
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);
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]));
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;
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));
512 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
513 ASSERT_EQ(0u, frames.size());
515 AppendTo(stub2.frames_passed(),
516 WebSocketFrameHeader::kOpCodeText,
517 kFinal,
518 data2);
520 checkpoint.Call(0);
521 stub2.callback().Run(OK);
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]));
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;
542 InSequence s;
543 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
544 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
546 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
547 deflate_stream_->ReadFrames(&frames, callback));
548 ASSERT_EQ(0u, frames.size());
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;
568 InSequence s;
569 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
570 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
593 InSequence s;
594 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
595 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
624 InSequence s;
625 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
626 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
652 InSequence s;
653 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
654 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
679 InSequence s;
680 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
681 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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();
702 ScopedVector<WebSocketFrame> frames_to_output;
703 AppendTo(&frames_to_output,
704 WebSocketFrameHeader::kOpCodeBinary,
705 kFinal | kReserved1,
706 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
708 ReadFramesStub stub(OK, &frames_to_output);
709 CompletionCallback callback;
710 ScopedVector<WebSocketFrame> frames;
712 InSequence s;
713 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
714 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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();
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 "");
754 ReadFramesStub stub(OK, &frames_to_output);
755 CompletionCallback callback;
756 ScopedVector<WebSocketFrame> frames;
758 InSequence s;
759 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
760 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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));
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]));
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;
796 InSequence s;
797 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
798 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
800 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
801 deflate_stream_->ReadFrames(&frames, callback));
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;
820 InSequence s;
821 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
822 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
824 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
825 deflate_stream_->ReadFrames(&frames, callback));
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;
844 InSequence s;
845 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
846 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
875 InSequence s;
876 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
877 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
908 InSequence s;
909 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
910 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
941 InSequence s;
942 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
943 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
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]));
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;
968 InSequence s;
969 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
970 .WillOnce(Invoke(stub_vector[0], &ReadFramesStub::Call));
972 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
973 .WillOnce(Invoke(stub_vector[1], &ReadFramesStub::Call));
975 EXPECT_CALL(mock_callback, Call(OK));
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]));
994 TEST_F(WebSocketDeflateStreamTest, WriteEmpty) {
995 ScopedVector<WebSocketFrame> frames;
996 CompletionCallback callback;
998 InSequence s;
999 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0);
1001 EXPECT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1004 TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) {
1005 ScopedVector<WebSocketFrame> frames;
1006 CompletionCallback callback;
1008 InSequence s;
1009 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1010 .WillOnce(Return(ERR_FAILED));
1013 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello");
1014 predictor_->AddFramesToBeInput(frames);
1015 EXPECT_EQ(ERR_FAILED, deflate_stream_->WriteFrames(&frames, callback));
1016 predictor_->Clear();
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);
1026 InSequence s;
1027 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1028 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
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;
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));
1053 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1054 predictor_->AddFramesToBeInput(frames);
1055 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->WriteFrames(&frames, callback));
1057 checkpoint.Call(0);
1058 stub.callback().Run(OK);
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]));
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;
1079 InSequence s;
1080 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1081 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
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;
1104 InSequence s;
1105 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1106 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
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;
1125 predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE);
1128 InSequence s;
1129 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1130 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
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;
1154 InSequence s;
1155 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1156 .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call));
1158 ScopedVector<WebSocketFrame> total_compressed_frames;
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;
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);
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);
1197 EXPECT_EQ(total_deflated,
1198 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
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;
1210 InSequence s;
1211 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1212 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
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;
1238 InSequence s;
1239 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1240 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
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);
1274 InSequence s;
1275 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1276 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1278 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1279 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1280 ASSERT_EQ(5u, frames_passed.size());
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]));
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]));
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]));
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);
1316 InSequence s;
1317 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1318 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
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);
1335 InSequence s;
1336 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1337 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
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]));
1347 } // namespace
1349 } // namespace net