Prevent bookmark apps from triggering a sync loop.
[chromium-blink-merge.git] / net / websockets / websocket_deflate_stream_test.cc
blob6d29a2b2048caee9f040b811bf4634ddaead9905
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 ? ToString(frame->data, frame->header.payload_length) : "";
74 void AppendTo(ScopedVector<WebSocketFrame>* frames,
75 WebSocketFrameHeader::OpCode opcode,
76 FrameFlag flag,
77 const std::string& data) {
78 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode));
79 frame->header.final = (flag & kFinal);
80 frame->header.reserved1 = (flag & kReserved1);
81 frame->data = ToIOBuffer(data);
82 frame->header.payload_length = data.size();
83 frames->push_back(frame.release());
86 void AppendTo(ScopedVector<WebSocketFrame>* frames,
87 WebSocketFrameHeader::OpCode opcode,
88 FrameFlag flag) {
89 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode));
90 frame->header.final = (flag & kFinal);
91 frame->header.reserved1 = (flag & kReserved1);
92 frames->push_back(frame.release());
95 class MockWebSocketStream : public WebSocketStream {
96 public:
97 MOCK_METHOD2(ReadFrames, int(ScopedVector<WebSocketFrame>*,
98 const CompletionCallback&));
99 MOCK_METHOD2(WriteFrames, int(ScopedVector<WebSocketFrame>*,
100 const CompletionCallback&));
101 MOCK_METHOD0(Close, void());
102 MOCK_CONST_METHOD0(GetSubProtocol, std::string());
103 MOCK_CONST_METHOD0(GetExtensions, std::string());
106 // This mock class relies on some assumptions.
107 // - RecordInputDataFrame is called after the corresponding WriteFrames
108 // call.
109 // - RecordWrittenDataFrame is called before writing the frame.
110 class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor {
111 public:
112 WebSocketDeflatePredictorMock() : result_(DEFLATE) {}
113 virtual ~WebSocketDeflatePredictorMock() {
114 // Verify whether all expectaions are consumed.
115 if (!frames_to_be_input_.empty()) {
116 ADD_FAILURE() << "There are missing frames to be input.";
117 return;
119 if (!frames_written_.empty()) {
120 ADD_FAILURE() << "There are extra written frames.";
121 return;
125 // WebSocketDeflatePredictor functions.
126 virtual Result Predict(const ScopedVector<WebSocketFrame>& frames,
127 size_t frame_index) OVERRIDE {
128 return result_;
130 virtual void RecordInputDataFrame(const WebSocketFrame* frame) OVERRIDE {
131 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
132 ADD_FAILURE() << "Control frames should not be recorded.";
133 return;
135 if (frame->header.reserved1) {
136 ADD_FAILURE() << "Input frame may not be compressed.";
137 return;
139 if (frames_to_be_input_.empty()) {
140 ADD_FAILURE() << "Unexpected input data frame";
141 return;
143 if (frame != frames_to_be_input_.front()) {
144 ADD_FAILURE() << "Input data frame does not match the expectation.";
145 return;
147 frames_to_be_input_.pop_front();
149 virtual void RecordWrittenDataFrame(const WebSocketFrame* frame) OVERRIDE {
150 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
151 ADD_FAILURE() << "Control frames should not be recorded.";
152 return;
154 frames_written_.push_back(frame);
157 // Sets |result_| for the |Predict| return value.
158 void set_result(Result result) { result_ = result; }
160 // Adds |frame| as an expectation of future |RecordInputDataFrame| call.
161 void AddFrameToBeInput(const WebSocketFrame* frame) {
162 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode))
163 return;
164 frames_to_be_input_.push_back(frame);
166 // Verifies that |frame| is recorded in order.
167 void VerifySentFrame(const WebSocketFrame* frame) {
168 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode))
169 return;
170 if (frames_written_.empty()) {
171 ADD_FAILURE() << "There are missing frames to be written.";
172 return;
174 if (frame != frames_written_.front()) {
175 ADD_FAILURE() << "Written data frame does not match the expectation.";
176 return;
178 frames_written_.pop_front();
180 void AddFramesToBeInput(const ScopedVector<WebSocketFrame>& frames) {
181 for (size_t i = 0; i < frames.size(); ++i)
182 AddFrameToBeInput(frames[i]);
184 void VerifySentFrames(const ScopedVector<WebSocketFrame>& frames) {
185 for (size_t i = 0; i < frames.size(); ++i)
186 VerifySentFrame(frames[i]);
188 // Call this method in order to disable checks in the destructor when
189 // WriteFrames fails.
190 void Clear() {
191 frames_to_be_input_.clear();
192 frames_written_.clear();
195 private:
196 Result result_;
197 // Data frames which will be recorded by |RecordInputFrames|.
198 // Pushed by |AddFrameToBeInput| and popped and verified by
199 // |RecordInputFrames|.
200 std::deque<const WebSocketFrame*> frames_to_be_input_;
201 // Data frames recorded by |RecordWrittenFrames|.
202 // Pushed by |RecordWrittenFrames| and popped and verified by
203 // |VerifySentFrame|.
204 std::deque<const WebSocketFrame*> frames_written_;
206 DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock);
209 class WebSocketDeflateStreamTest : public ::testing::Test {
210 public:
211 WebSocketDeflateStreamTest()
212 : mock_stream_(NULL),
213 predictor_(NULL) {}
214 virtual ~WebSocketDeflateStreamTest() {}
216 virtual void SetUp() {
217 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, kWindowBits);
220 protected:
221 // Initialize deflate_stream_ with the given parameters.
222 void Initialize(WebSocketDeflater::ContextTakeOverMode mode,
223 int window_bits) {
224 mock_stream_ = new testing::StrictMock<MockWebSocketStream>;
225 predictor_ = new WebSocketDeflatePredictorMock;
226 deflate_stream_.reset(new WebSocketDeflateStream(
227 scoped_ptr<WebSocketStream>(mock_stream_),
228 mode,
229 window_bits,
230 scoped_ptr<WebSocketDeflatePredictor>(predictor_)));
233 scoped_ptr<WebSocketDeflateStream> deflate_stream_;
234 // Owned by |deflate_stream_|.
235 MockWebSocketStream* mock_stream_;
236 // Owned by |deflate_stream_|.
237 WebSocketDeflatePredictorMock* predictor_;
240 // Since WebSocketDeflater with DoNotTakeOverContext is well tested at
241 // websocket_deflater_test.cc, we have only a few tests for this configuration
242 // here.
243 class WebSocketDeflateStreamWithDoNotTakeOverContextTest
244 : public WebSocketDeflateStreamTest {
245 public:
246 WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
247 virtual ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
249 virtual void SetUp() {
250 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT, kWindowBits);
254 class WebSocketDeflateStreamWithClientWindowBitsTest
255 : public WebSocketDeflateStreamTest {
256 public:
257 WebSocketDeflateStreamWithClientWindowBitsTest() {}
258 virtual ~WebSocketDeflateStreamWithClientWindowBitsTest() {}
260 // Overridden to postpone the call to Initialize().
261 virtual void SetUp() {}
263 // This needs to be called explicitly from the tests.
264 void SetUpWithWindowBits(int window_bits) {
265 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, window_bits);
268 // Add a frame which will be compressed to a smaller size if the window
269 // size is large enough.
270 void AddCompressibleFrameString() {
271 const std::string word = "Chromium";
272 const std::string payload = word + std::string(256, 'a') + word;
273 AppendTo(&frames_, WebSocketFrameHeader::kOpCodeText, kFinal, payload);
274 predictor_->AddFramesToBeInput(frames_);
277 protected:
278 ScopedVector<WebSocketFrame> frames_;
281 // ReadFrameStub is a stub for WebSocketStream::ReadFrames.
282 // It returns |result_| and |frames_to_output_| to the caller and
283 // saves parameters to |frames_passed_| and |callback_|.
284 class ReadFramesStub {
285 public:
286 explicit ReadFramesStub(int result) : result_(result) {}
288 ReadFramesStub(int result, ScopedVector<WebSocketFrame>* frames_to_output)
289 : result_(result) {
290 frames_to_output_.swap(*frames_to_output);
293 int Call(ScopedVector<WebSocketFrame>* frames,
294 const CompletionCallback& callback) {
295 DCHECK(frames->empty());
296 frames_passed_ = frames;
297 callback_ = callback;
298 frames->swap(frames_to_output_);
299 return result_;
302 int result() const { return result_; }
303 const CompletionCallback callback() const { return callback_; }
304 ScopedVector<WebSocketFrame>* frames_passed() {
305 return frames_passed_;
308 private:
309 int result_;
310 CompletionCallback callback_;
311 ScopedVector<WebSocketFrame> frames_to_output_;
312 ScopedVector<WebSocketFrame>* frames_passed_;
315 // WriteFramesStub is a stub for WebSocketStream::WriteFrames.
316 // It returns |result_| and |frames_| to the caller and
317 // saves |callback| parameter to |callback_|.
318 class WriteFramesStub {
319 public:
320 explicit WriteFramesStub(WebSocketDeflatePredictorMock* predictor,
321 int result)
322 : result_(result), predictor_(predictor) {}
324 int Call(ScopedVector<WebSocketFrame>* frames,
325 const CompletionCallback& callback) {
326 frames_.insert(frames_.end(), frames->begin(), frames->end());
327 frames->weak_clear();
328 callback_ = callback;
329 predictor_->VerifySentFrames(frames_);
330 return result_;
333 int result() const { return result_; }
334 const CompletionCallback callback() const { return callback_; }
335 ScopedVector<WebSocketFrame>* frames() { return &frames_; }
337 private:
338 int result_;
339 CompletionCallback callback_;
340 ScopedVector<WebSocketFrame> frames_;
341 WebSocketDeflatePredictorMock* predictor_;
344 TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) {
345 ScopedVector<WebSocketFrame> frames;
346 CompletionCallback callback;
348 InSequence s;
349 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
350 .WillOnce(Return(ERR_FAILED));
352 EXPECT_EQ(ERR_FAILED, deflate_stream_->ReadFrames(&frames, callback));
355 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameImmediately) {
356 ScopedVector<WebSocketFrame> frames_to_output;
357 AppendTo(&frames_to_output,
358 WebSocketFrameHeader::kOpCodeText,
359 kFinal,
360 "hello");
361 ReadFramesStub stub(OK, &frames_to_output);
362 ScopedVector<WebSocketFrame> frames;
365 InSequence s;
366 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
367 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
369 CompletionCallback callback;
370 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
371 ASSERT_EQ(1u, frames.size());
372 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
373 EXPECT_TRUE(frames[0]->header.final);
374 EXPECT_FALSE(frames[0]->header.reserved1);
375 EXPECT_EQ("hello", ToString(frames[0]));
378 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) {
379 ReadFramesStub stub(ERR_IO_PENDING);
380 ScopedVector<WebSocketFrame> frames;
381 MockCallback mock_callback, checkpoint;
382 CompletionCallback callback =
383 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
386 InSequence s;
387 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
388 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
389 EXPECT_CALL(checkpoint, Call(0));
390 EXPECT_CALL(mock_callback, Call(OK));
392 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
393 ASSERT_EQ(0u, frames.size());
395 checkpoint.Call(0);
397 AppendTo(stub.frames_passed(),
398 WebSocketFrameHeader::kOpCodeText,
399 kFinal,
400 "hello");
401 stub.callback().Run(OK);
402 ASSERT_EQ(1u, frames.size());
403 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
404 EXPECT_TRUE(frames[0]->header.final);
405 EXPECT_FALSE(frames[0]->header.reserved1);
406 EXPECT_EQ("hello", ToString(frames[0]));
409 TEST_F(WebSocketDeflateStreamTest, ReadFailedAsync) {
410 ReadFramesStub stub(ERR_IO_PENDING);
411 ScopedVector<WebSocketFrame> frames;
412 MockCallback mock_callback, checkpoint;
413 CompletionCallback callback =
414 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
417 InSequence s;
418 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
419 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
420 EXPECT_CALL(checkpoint, Call(0));
421 EXPECT_CALL(mock_callback, Call(ERR_FAILED));
423 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
424 ASSERT_EQ(0u, frames.size());
426 checkpoint.Call(0);
428 AppendTo(stub.frames_passed(),
429 WebSocketFrameHeader::kOpCodeText,
430 kFinal,
431 "hello");
432 stub.callback().Run(ERR_FAILED);
433 ASSERT_EQ(0u, frames.size());
436 TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameImmediately) {
437 ScopedVector<WebSocketFrame> frames_to_output;
438 AppendTo(&frames_to_output,
439 WebSocketFrameHeader::kOpCodeText,
440 kFinal | kReserved1,
441 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
442 ReadFramesStub stub(OK, &frames_to_output);
443 CompletionCallback callback;
444 ScopedVector<WebSocketFrame> frames;
446 InSequence s;
447 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
448 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
450 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
451 ASSERT_EQ(1u, frames.size());
452 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
453 EXPECT_TRUE(frames[0]->header.final);
454 EXPECT_FALSE(frames[0]->header.reserved1);
455 EXPECT_EQ("Hello", ToString(frames[0]));
458 TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameAsync) {
459 ReadFramesStub stub(ERR_IO_PENDING);
460 MockCallback mock_callback, checkpoint;
461 CompletionCallback callback =
462 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
463 ScopedVector<WebSocketFrame> frames;
465 InSequence s;
466 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
467 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
468 EXPECT_CALL(checkpoint, Call(0));
469 EXPECT_CALL(mock_callback, Call(OK));
471 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
473 checkpoint.Call(0);
475 AppendTo(stub.frames_passed(),
476 WebSocketFrameHeader::kOpCodeText,
477 kFinal | kReserved1,
478 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
479 stub.callback().Run(OK);
481 ASSERT_EQ(1u, frames.size());
482 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
483 EXPECT_TRUE(frames[0]->header.final);
484 EXPECT_FALSE(frames[0]->header.reserved1);
485 EXPECT_EQ("Hello", ToString(frames[0]));
488 TEST_F(WebSocketDeflateStreamTest,
489 ReadCompressedFrameFragmentImmediatelyButInflaterReturnsPending) {
490 ScopedVector<WebSocketFrame> frames_to_output;
491 const std::string data1("\xf2", 1);
492 const std::string data2("\x48\xcd\xc9\xc9\x07\x00", 6);
493 AppendTo(&frames_to_output,
494 WebSocketFrameHeader::kOpCodeText,
495 kReserved1,
496 data1);
497 ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING);
498 MockCallback mock_callback, checkpoint;
499 CompletionCallback callback =
500 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
501 ScopedVector<WebSocketFrame> frames;
504 InSequence s;
505 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
506 .WillOnce(Invoke(&stub1, &ReadFramesStub::Call))
507 .WillOnce(Invoke(&stub2, &ReadFramesStub::Call));
508 EXPECT_CALL(checkpoint, Call(0));
509 EXPECT_CALL(mock_callback, Call(OK));
511 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
512 ASSERT_EQ(0u, frames.size());
514 AppendTo(stub2.frames_passed(),
515 WebSocketFrameHeader::kOpCodeText,
516 kFinal,
517 data2);
519 checkpoint.Call(0);
520 stub2.callback().Run(OK);
522 ASSERT_EQ(1u, frames.size());
523 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
524 EXPECT_TRUE(frames[0]->header.final);
525 EXPECT_FALSE(frames[0]->header.reserved1);
526 EXPECT_EQ("Hello", ToString(frames[0]));
529 TEST_F(WebSocketDeflateStreamTest, ReadInvalidCompressedPayload) {
530 const std::string data("\xf2\x48\xcdINVALID", 10);
531 ScopedVector<WebSocketFrame> frames_to_output;
532 AppendTo(&frames_to_output,
533 WebSocketFrameHeader::kOpCodeText,
534 kFinal | kReserved1,
535 data);
536 ReadFramesStub stub(OK, &frames_to_output);
537 CompletionCallback callback;
538 ScopedVector<WebSocketFrame> frames;
541 InSequence s;
542 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
543 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
545 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
546 deflate_stream_->ReadFrames(&frames, callback));
547 ASSERT_EQ(0u, frames.size());
550 TEST_F(WebSocketDeflateStreamTest, MergeMultipleFramesInReadFrames) {
551 const std::string data1("\xf2\x48\xcd", 3);
552 const std::string data2("\xc9\xc9\x07\x00", 4);
553 ScopedVector<WebSocketFrame> frames_to_output;
554 AppendTo(&frames_to_output,
555 WebSocketFrameHeader::kOpCodeText,
556 kReserved1,
557 data1);
558 AppendTo(&frames_to_output,
559 WebSocketFrameHeader::kOpCodeContinuation,
560 kFinal,
561 data2);
562 ReadFramesStub stub(OK, &frames_to_output);
563 CompletionCallback callback;
564 ScopedVector<WebSocketFrame> frames;
567 InSequence s;
568 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
569 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
571 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
572 ASSERT_EQ(1u, frames.size());
573 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
574 EXPECT_TRUE(frames[0]->header.final);
575 EXPECT_FALSE(frames[0]->header.reserved1);
576 EXPECT_EQ("Hello", ToString(frames[0]));
579 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedEmptyFrames) {
580 ScopedVector<WebSocketFrame> frames_to_output;
581 AppendTo(&frames_to_output,
582 WebSocketFrameHeader::kOpCodeText,
583 kNoFlag);
584 AppendTo(&frames_to_output,
585 WebSocketFrameHeader::kOpCodeContinuation,
586 kFinal);
587 ReadFramesStub stub(OK, &frames_to_output);
588 CompletionCallback callback;
589 ScopedVector<WebSocketFrame> frames;
592 InSequence s;
593 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
594 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
596 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
597 ASSERT_EQ(2u, frames.size());
598 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
599 EXPECT_FALSE(frames[0]->header.final);
600 EXPECT_FALSE(frames[0]->header.reserved1);
601 EXPECT_EQ("", ToString(frames[0]));
602 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
603 frames[1]->header.opcode);
604 EXPECT_TRUE(frames[1]->header.final);
605 EXPECT_FALSE(frames[1]->header.reserved1);
606 EXPECT_EQ("", ToString(frames[1]));
609 TEST_F(WebSocketDeflateStreamTest, ReadCompressedEmptyFrames) {
610 ScopedVector<WebSocketFrame> frames_to_output;
611 AppendTo(&frames_to_output,
612 WebSocketFrameHeader::kOpCodeText,
613 kReserved1,
614 std::string("\x02\x00", 1));
615 AppendTo(&frames_to_output,
616 WebSocketFrameHeader::kOpCodeContinuation,
617 kFinal);
618 ReadFramesStub stub(OK, &frames_to_output);
619 CompletionCallback callback;
620 ScopedVector<WebSocketFrame> frames;
623 InSequence s;
624 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
625 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
627 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
628 ASSERT_EQ(1u, frames.size());
629 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
630 EXPECT_TRUE(frames[0]->header.final);
631 EXPECT_FALSE(frames[0]->header.reserved1);
632 EXPECT_EQ("", ToString(frames[0]));
635 TEST_F(WebSocketDeflateStreamTest,
636 ReadCompressedFrameFollowedByEmptyFrame) {
637 const std::string data("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
638 ScopedVector<WebSocketFrame> frames_to_output;
639 AppendTo(&frames_to_output,
640 WebSocketFrameHeader::kOpCodeText,
641 kReserved1,
642 data);
643 AppendTo(&frames_to_output,
644 WebSocketFrameHeader::kOpCodeContinuation,
645 kFinal);
646 ReadFramesStub stub(OK, &frames_to_output);
647 CompletionCallback callback;
648 ScopedVector<WebSocketFrame> frames;
651 InSequence s;
652 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
653 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
655 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
656 ASSERT_EQ(1u, frames.size());
657 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
658 EXPECT_TRUE(frames[0]->header.final);
659 EXPECT_FALSE(frames[0]->header.reserved1);
660 EXPECT_EQ("Hello", ToString(frames[0]));
663 TEST_F(WebSocketDeflateStreamTest, ReadControlFrameBetweenDataFrames) {
664 const std::string data1("\xf2\x48\xcd", 3);
665 const std::string data2("\xc9\xc9\x07\x00", 4);
666 ScopedVector<WebSocketFrame> frames_to_output;
667 AppendTo(&frames_to_output,
668 WebSocketFrameHeader::kOpCodeText,
669 kReserved1,
670 data1);
671 AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodePing, kFinal);
672 AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodeText, kFinal, data2);
673 ReadFramesStub stub(OK, &frames_to_output);
674 CompletionCallback callback;
675 ScopedVector<WebSocketFrame> frames;
678 InSequence s;
679 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
680 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
682 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
683 ASSERT_EQ(2u, frames.size());
684 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames[0]->header.opcode);
685 EXPECT_TRUE(frames[0]->header.final);
686 EXPECT_FALSE(frames[0]->header.reserved1);
687 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
688 EXPECT_TRUE(frames[1]->header.final);
689 EXPECT_FALSE(frames[1]->header.reserved1);
690 EXPECT_EQ("Hello", ToString(frames[1]));
693 TEST_F(WebSocketDeflateStreamTest, SplitToMultipleFramesInReadFrames) {
694 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
695 deflater.Initialize(kWindowBits);
696 const size_t kSize = kChunkSize * 3;
697 const std::string original_data(kSize, 'a');
698 deflater.AddBytes(original_data.data(), original_data.size());
699 deflater.Finish();
701 ScopedVector<WebSocketFrame> frames_to_output;
702 AppendTo(&frames_to_output,
703 WebSocketFrameHeader::kOpCodeBinary,
704 kFinal | kReserved1,
705 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
707 ReadFramesStub stub(OK, &frames_to_output);
708 CompletionCallback callback;
709 ScopedVector<WebSocketFrame> frames;
711 InSequence s;
712 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
713 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
716 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
717 ASSERT_EQ(3u, frames.size());
718 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode);
719 EXPECT_FALSE(frames[0]->header.final);
720 EXPECT_FALSE(frames[0]->header.reserved1);
721 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length));
722 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
723 frames[1]->header.opcode);
724 EXPECT_FALSE(frames[1]->header.final);
725 EXPECT_FALSE(frames[1]->header.reserved1);
726 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[1]->header.payload_length));
727 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
728 frames[2]->header.opcode);
729 EXPECT_TRUE(frames[2]->header.final);
730 EXPECT_FALSE(frames[2]->header.reserved1);
731 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[2]->header.payload_length));
732 EXPECT_EQ(original_data,
733 ToString(frames[0]) + ToString(frames[1]) + ToString(frames[2]));
736 TEST_F(WebSocketDeflateStreamTest,
737 Reserved1TurnsOnDuringReadingCompressedContinuationFrame) {
738 const std::string data1("\xf2\x48\xcd", 3);
739 const std::string data2("\xc9\xc9\x07\x00", 4);
740 ScopedVector<WebSocketFrame> frames_to_output;
741 AppendTo(&frames_to_output,
742 WebSocketFrameHeader::kOpCodeText,
743 kReserved1,
744 data1);
745 AppendTo(&frames_to_output,
746 WebSocketFrameHeader::kOpCodeContinuation,
747 kFinal | kReserved1,
748 data2);
749 ReadFramesStub stub(OK, &frames_to_output);
750 CompletionCallback callback;
751 ScopedVector<WebSocketFrame> frames;
754 InSequence s;
755 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
756 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
758 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
759 deflate_stream_->ReadFrames(&frames, callback));
762 TEST_F(WebSocketDeflateStreamTest,
763 Reserved1TurnsOnDuringReadingUncompressedContinuationFrame) {
764 ScopedVector<WebSocketFrame> frames_to_output;
765 AppendTo(&frames_to_output,
766 WebSocketFrameHeader::kOpCodeText,
767 kNoFlag,
768 "hello");
769 AppendTo(&frames_to_output,
770 WebSocketFrameHeader::kOpCodeContinuation,
771 kFinal | kReserved1,
772 "world");
773 ReadFramesStub stub(OK, &frames_to_output);
774 CompletionCallback callback;
775 ScopedVector<WebSocketFrame> frames;
778 InSequence s;
779 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
780 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
782 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
783 deflate_stream_->ReadFrames(&frames, callback));
786 TEST_F(WebSocketDeflateStreamTest, ReadCompressedMessages) {
787 ScopedVector<WebSocketFrame> frames_to_output;
788 AppendTo(&frames_to_output,
789 WebSocketFrameHeader::kOpCodeText,
790 kFinal | kReserved1,
791 std::string(
792 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
793 AppendTo(&frames_to_output,
794 WebSocketFrameHeader::kOpCodeText,
795 kFinal | kReserved1,
796 std::string("\x4a\x86\x33\x8d\x00\x00", 6));
797 ReadFramesStub stub(OK, &frames_to_output);
798 CompletionCallback callback;
799 ScopedVector<WebSocketFrame> frames;
802 InSequence s;
803 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
804 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
806 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
807 ASSERT_EQ(2u, frames.size());
808 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
809 EXPECT_TRUE(frames[0]->header.final);
810 EXPECT_FALSE(frames[0]->header.reserved1);
811 EXPECT_EQ("compressed1", ToString(frames[0]));
812 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
813 EXPECT_TRUE(frames[1]->header.final);
814 EXPECT_FALSE(frames[1]->header.reserved1);
815 EXPECT_EQ("compressed2", ToString(frames[1]));
818 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedMessages) {
819 ScopedVector<WebSocketFrame> frames_to_output;
820 AppendTo(&frames_to_output,
821 WebSocketFrameHeader::kOpCodeText,
822 kFinal,
823 "uncompressed1");
824 AppendTo(&frames_to_output,
825 WebSocketFrameHeader::kOpCodeText,
826 kFinal,
827 "uncompressed2");
828 ReadFramesStub stub(OK, &frames_to_output);
829 CompletionCallback callback;
830 ScopedVector<WebSocketFrame> frames;
833 InSequence s;
834 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
835 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
837 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
838 ASSERT_EQ(2u, frames.size());
839 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
840 EXPECT_TRUE(frames[0]->header.final);
841 EXPECT_FALSE(frames[0]->header.reserved1);
842 EXPECT_EQ("uncompressed1", ToString(frames[0]));
843 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
844 EXPECT_TRUE(frames[1]->header.final);
845 EXPECT_FALSE(frames[1]->header.reserved1);
846 EXPECT_EQ("uncompressed2", ToString(frames[1]));
849 TEST_F(WebSocketDeflateStreamTest,
850 ReadCompressedMessageThenUncompressedMessage) {
851 ScopedVector<WebSocketFrame> frames_to_output;
852 AppendTo(&frames_to_output,
853 WebSocketFrameHeader::kOpCodeText,
854 kFinal | kReserved1,
855 std::string(
856 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
857 AppendTo(&frames_to_output,
858 WebSocketFrameHeader::kOpCodeText,
859 kFinal,
860 "uncompressed");
861 ReadFramesStub stub(OK, &frames_to_output);
862 CompletionCallback callback;
863 ScopedVector<WebSocketFrame> frames;
866 InSequence s;
867 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
868 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
870 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
871 ASSERT_EQ(2u, frames.size());
872 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
873 EXPECT_TRUE(frames[0]->header.final);
874 EXPECT_FALSE(frames[0]->header.reserved1);
875 EXPECT_EQ("compressed", ToString(frames[0]));
876 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
877 EXPECT_TRUE(frames[1]->header.final);
878 EXPECT_FALSE(frames[1]->header.reserved1);
879 EXPECT_EQ("uncompressed", ToString(frames[1]));
882 TEST_F(WebSocketDeflateStreamTest,
883 ReadUncompressedMessageThenCompressedMessage) {
884 ScopedVector<WebSocketFrame> frames_to_output;
885 AppendTo(&frames_to_output,
886 WebSocketFrameHeader::kOpCodeText,
887 kFinal,
888 "uncompressed");
889 AppendTo(&frames_to_output,
890 WebSocketFrameHeader::kOpCodeText,
891 kFinal | kReserved1,
892 std::string(
893 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
894 ReadFramesStub stub(OK, &frames_to_output);
895 CompletionCallback callback;
896 ScopedVector<WebSocketFrame> frames;
899 InSequence s;
900 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
901 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
903 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
904 ASSERT_EQ(2u, frames.size());
905 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
906 EXPECT_TRUE(frames[0]->header.final);
907 EXPECT_FALSE(frames[0]->header.reserved1);
908 EXPECT_EQ("uncompressed", ToString(frames[0]));
909 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
910 EXPECT_TRUE(frames[1]->header.final);
911 EXPECT_FALSE(frames[1]->header.reserved1);
912 EXPECT_EQ("compressed", ToString(frames[1]));
915 // This is a regression test for crbug.com/343506.
916 TEST_F(WebSocketDeflateStreamTest, ReadEmptyAsyncFrame) {
917 ScopedVector<ReadFramesStub> stub_vector;
918 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING));
919 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING));
920 MockCallback mock_callback;
921 CompletionCallback callback =
922 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
923 ScopedVector<WebSocketFrame> frames;
926 InSequence s;
927 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
928 .WillOnce(Invoke(stub_vector[0], &ReadFramesStub::Call));
930 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
931 .WillOnce(Invoke(stub_vector[1], &ReadFramesStub::Call));
933 EXPECT_CALL(mock_callback, Call(OK));
936 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
937 AppendTo(stub_vector[0]->frames_passed(),
938 WebSocketFrameHeader::kOpCodeText,
939 kReserved1,
940 std::string());
941 stub_vector[0]->callback().Run(OK);
942 AppendTo(stub_vector[1]->frames_passed(),
943 WebSocketFrameHeader::kOpCodeContinuation,
944 kFinal,
945 std::string("\x02\x00"));
946 stub_vector[1]->callback().Run(OK);
947 ASSERT_EQ(1u, frames.size());
948 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
949 EXPECT_EQ("", ToString(frames[0]));
952 TEST_F(WebSocketDeflateStreamTest, WriteEmpty) {
953 ScopedVector<WebSocketFrame> frames;
954 CompletionCallback callback;
956 InSequence s;
957 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0);
959 EXPECT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
962 TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) {
963 ScopedVector<WebSocketFrame> frames;
964 CompletionCallback callback;
966 InSequence s;
967 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
968 .WillOnce(Return(ERR_FAILED));
971 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello");
972 predictor_->AddFramesToBeInput(frames);
973 EXPECT_EQ(ERR_FAILED, deflate_stream_->WriteFrames(&frames, callback));
974 predictor_->Clear();
977 TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) {
978 ScopedVector<WebSocketFrame> frames;
979 CompletionCallback callback;
980 WriteFramesStub stub(predictor_, OK);
981 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
982 predictor_->AddFramesToBeInput(frames);
984 InSequence s;
985 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
986 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
988 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
989 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
990 ASSERT_EQ(1u, frames_passed.size());
991 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
992 EXPECT_TRUE(frames_passed[0]->header.final);
993 EXPECT_TRUE(frames_passed[0]->header.reserved1);
994 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
995 ToString(frames_passed[0]));
998 TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) {
999 WriteFramesStub stub(predictor_, ERR_IO_PENDING);
1000 MockCallback mock_callback, checkpoint;
1001 CompletionCallback callback =
1002 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
1003 ScopedVector<WebSocketFrame> frames;
1005 InSequence s;
1006 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1007 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1008 EXPECT_CALL(checkpoint, Call(0));
1009 EXPECT_CALL(mock_callback, Call(OK));
1011 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1012 predictor_->AddFramesToBeInput(frames);
1013 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->WriteFrames(&frames, callback));
1015 checkpoint.Call(0);
1016 stub.callback().Run(OK);
1018 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1019 ASSERT_EQ(1u, frames_passed.size());
1020 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1021 EXPECT_TRUE(frames_passed[0]->header.final);
1022 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1023 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1024 ToString(frames_passed[0]));
1027 TEST_F(WebSocketDeflateStreamTest, WriteControlFrameBetweenDataFrames) {
1028 ScopedVector<WebSocketFrame> frames;
1029 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "Hel");
1030 AppendTo(&frames, WebSocketFrameHeader::kOpCodePing, kFinal);
1031 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "lo");
1032 predictor_->AddFramesToBeInput(frames);
1033 WriteFramesStub stub(predictor_, OK);
1034 CompletionCallback callback;
1037 InSequence s;
1038 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1039 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1041 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1042 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1043 ASSERT_EQ(2u, frames_passed.size());
1044 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames_passed[0]->header.opcode);
1045 EXPECT_TRUE(frames_passed[0]->header.final);
1046 EXPECT_FALSE(frames_passed[0]->header.reserved1);
1047 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1048 EXPECT_TRUE(frames_passed[1]->header.final);
1049 EXPECT_TRUE(frames_passed[1]->header.reserved1);
1050 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1051 ToString(frames_passed[1]));
1054 TEST_F(WebSocketDeflateStreamTest, WriteEmptyMessage) {
1055 ScopedVector<WebSocketFrame> frames;
1056 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal);
1057 predictor_->AddFramesToBeInput(frames);
1058 WriteFramesStub stub(predictor_, OK);
1059 CompletionCallback callback;
1062 InSequence s;
1063 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1064 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1066 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1067 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1068 ASSERT_EQ(1u, frames_passed.size());
1069 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1070 EXPECT_TRUE(frames_passed[0]->header.final);
1071 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1072 EXPECT_EQ(std::string("\x00", 1), ToString(frames_passed[0]));
1075 TEST_F(WebSocketDeflateStreamTest, WriteUncompressedMessage) {
1076 ScopedVector<WebSocketFrame> frames;
1077 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAA");
1078 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AAA");
1079 predictor_->AddFramesToBeInput(frames);
1080 WriteFramesStub stub(predictor_, OK);
1081 CompletionCallback callback;
1083 predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE);
1086 InSequence s;
1087 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1088 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1090 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1091 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1092 ASSERT_EQ(2u, frames_passed.size());
1093 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1094 EXPECT_FALSE(frames_passed[0]->header.final);
1095 EXPECT_FALSE(frames_passed[0]->header.reserved1);
1096 EXPECT_EQ("AAAA", ToString(frames_passed[0]));
1097 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1098 frames_passed[1]->header.opcode);
1099 EXPECT_TRUE(frames_passed[1]->header.final);
1100 EXPECT_FALSE(frames_passed[1]->header.reserved1);
1101 EXPECT_EQ("AAA", ToString(frames_passed[1]));
1104 TEST_F(WebSocketDeflateStreamTest, LargeDeflatedFramesShouldBeSplit) {
1105 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
1106 LinearCongruentialGenerator lcg(133);
1107 WriteFramesStub stub(predictor_, OK);
1108 CompletionCallback callback;
1109 const size_t size = 1024;
1112 InSequence s;
1113 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1114 .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call));
1116 ScopedVector<WebSocketFrame> total_compressed_frames;
1118 deflater.Initialize(kWindowBits);
1119 while (true) {
1120 bool is_final = (total_compressed_frames.size() >= 2);
1121 ScopedVector<WebSocketFrame> frames;
1122 std::string data;
1123 for (size_t i = 0; i < size; ++i)
1124 data += static_cast<char>(lcg.Generate());
1125 deflater.AddBytes(data.data(), data.size());
1126 FrameFlag flag = is_final ? kFinal : kNoFlag;
1127 AppendTo(&frames, WebSocketFrameHeader::kOpCodeBinary, flag, data);
1128 predictor_->AddFramesToBeInput(frames);
1129 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1130 total_compressed_frames.insert(total_compressed_frames.end(),
1131 stub.frames()->begin(),
1132 stub.frames()->end());
1133 stub.frames()->weak_clear();
1134 if (is_final)
1135 break;
1137 deflater.Finish();
1138 std::string total_deflated;
1139 for (size_t i = 0; i < total_compressed_frames.size(); ++i) {
1140 WebSocketFrame* frame = total_compressed_frames[i];
1141 const WebSocketFrameHeader& header = frame->header;
1142 if (i > 0) {
1143 EXPECT_EQ(header.kOpCodeContinuation, header.opcode);
1144 EXPECT_FALSE(header.reserved1);
1145 } else {
1146 EXPECT_EQ(header.kOpCodeBinary, header.opcode);
1147 EXPECT_TRUE(header.reserved1);
1149 const bool is_final_frame = (i + 1 == total_compressed_frames.size());
1150 EXPECT_EQ(is_final_frame, header.final);
1151 if (!is_final_frame)
1152 EXPECT_GT(header.payload_length, 0ul);
1153 total_deflated += ToString(frame);
1155 EXPECT_EQ(total_deflated,
1156 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
1159 TEST_F(WebSocketDeflateStreamTest, WriteMultipleMessages) {
1160 ScopedVector<WebSocketFrame> frames;
1161 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1162 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1163 predictor_->AddFramesToBeInput(frames);
1164 WriteFramesStub stub(predictor_, OK);
1165 CompletionCallback callback;
1168 InSequence s;
1169 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1170 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1172 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1173 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1174 ASSERT_EQ(2u, frames_passed.size());
1175 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1176 EXPECT_TRUE(frames_passed[0]->header.final);
1177 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1178 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1179 ToString(frames_passed[0]));
1180 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1181 EXPECT_TRUE(frames_passed[1]->header.final);
1182 EXPECT_TRUE(frames_passed[1]->header.reserved1);
1183 EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed[1]));
1186 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
1187 WriteMultipleMessages) {
1188 ScopedVector<WebSocketFrame> frames;
1189 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1190 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1191 predictor_->AddFramesToBeInput(frames);
1192 WriteFramesStub stub(predictor_, OK);
1193 CompletionCallback callback;
1196 InSequence s;
1197 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1198 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1200 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1201 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1202 ASSERT_EQ(2u, frames_passed.size());
1203 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1204 EXPECT_TRUE(frames_passed[0]->header.final);
1205 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1206 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1207 ToString(frames_passed[0]));
1208 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1209 EXPECT_TRUE(frames_passed[1]->header.final);
1210 EXPECT_TRUE(frames_passed[1]->header.reserved1);
1211 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1212 ToString(frames_passed[1]));
1215 // In order to check the stream works correctly for multiple
1216 // "PossiblyCompressedMessage"s, we test various messages at one test case.
1217 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
1218 WritePossiblyCompressMessages) {
1219 ScopedVector<WebSocketFrame> frames;
1220 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "He");
1221 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "llo");
1222 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAAAAAAAA");
1223 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AA");
1224 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "XX");
1225 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "YY");
1226 predictor_->AddFramesToBeInput(frames);
1227 WriteFramesStub stub(predictor_, OK);
1228 CompletionCallback callback;
1229 predictor_->set_result(WebSocketDeflatePredictor::TRY_DEFLATE);
1232 InSequence s;
1233 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1234 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1236 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1237 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1238 ASSERT_EQ(5u, frames_passed.size());
1240 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1241 EXPECT_FALSE(frames_passed[0]->header.final);
1242 EXPECT_FALSE(frames_passed[0]->header.reserved1);
1243 EXPECT_EQ("He", ToString(frames_passed[0]));
1244 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1245 frames_passed[1]->header.opcode);
1246 EXPECT_TRUE(frames_passed[1]->header.final);
1247 EXPECT_FALSE(frames_passed[1]->header.reserved1);
1248 EXPECT_EQ("llo", ToString(frames_passed[1]));
1250 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[2]->header.opcode);
1251 EXPECT_TRUE(frames_passed[2]->header.final);
1252 EXPECT_TRUE(frames_passed[2]->header.reserved1);
1253 EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6),
1254 ToString(frames_passed[2]));
1256 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[3]->header.opcode);
1257 EXPECT_FALSE(frames_passed[3]->header.final);
1258 EXPECT_FALSE(frames_passed[3]->header.reserved1);
1259 EXPECT_EQ("XX", ToString(frames_passed[3]));
1260 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1261 frames_passed[4]->header.opcode);
1262 EXPECT_TRUE(frames_passed[4]->header.final);
1263 EXPECT_FALSE(frames_passed[4]->header.reserved1);
1264 EXPECT_EQ("YY", ToString(frames_passed[4]));
1267 // This is based on the similar test from websocket_deflater_test.cc
1268 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits8) {
1269 SetUpWithWindowBits(8);
1270 CompletionCallback callback;
1271 AddCompressibleFrameString();
1272 WriteFramesStub stub(predictor_, OK);
1274 InSequence s;
1275 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
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(1u, frames_passed.size());
1281 EXPECT_EQ(std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x39\xa3"
1282 "(?7\xb3\x34\x17\x00", 21),
1283 ToString(frames_passed[0]));
1286 // The same input with window_bits=10 returns smaller output.
1287 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits10) {
1288 SetUpWithWindowBits(10);
1289 CompletionCallback callback;
1290 AddCompressibleFrameString();
1291 WriteFramesStub stub(predictor_, OK);
1293 InSequence s;
1294 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1295 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1297 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback));
1298 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1299 ASSERT_EQ(1u, frames_passed.size());
1300 EXPECT_EQ(
1301 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17),
1302 ToString(frames_passed[0]));
1305 } // namespace
1307 } // namespace net