Single-purpose extensions policy FAQ
[chromium-blink-merge.git] / net / websockets / websocket_deflate_stream_test.cc
bloba8b4e59c32b16fec0a636d3b93c3bdde7e098581
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, InflaterInternalDataCanBeEmpty) {
737 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
738 deflater.Initialize(kWindowBits);
739 const std::string original_data(kChunkSize, 'a');
740 deflater.AddBytes(original_data.data(), original_data.size());
741 deflater.Finish();
743 ScopedVector<WebSocketFrame> frames_to_output;
744 AppendTo(&frames_to_output,
745 WebSocketFrameHeader::kOpCodeBinary,
746 kReserved1,
747 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
748 AppendTo(&frames_to_output,
749 WebSocketFrameHeader::kOpCodeBinary,
750 kFinal,
751 "");
753 ReadFramesStub stub(OK, &frames_to_output);
754 CompletionCallback callback;
755 ScopedVector<WebSocketFrame> frames;
757 InSequence s;
758 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
759 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
762 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
763 ASSERT_EQ(2u, frames.size());
764 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode);
765 EXPECT_FALSE(frames[0]->header.final);
766 EXPECT_FALSE(frames[0]->header.reserved1);
767 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length));
769 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
770 frames[1]->header.opcode);
771 EXPECT_TRUE(frames[1]->header.final);
772 EXPECT_FALSE(frames[1]->header.reserved1);
773 EXPECT_EQ(0u, static_cast<size_t>(frames[1]->header.payload_length));
774 EXPECT_EQ(original_data, ToString(frames[0]) + ToString(frames[1]));
777 TEST_F(WebSocketDeflateStreamTest,
778 Reserved1TurnsOnDuringReadingCompressedContinuationFrame) {
779 const std::string data1("\xf2\x48\xcd", 3);
780 const std::string data2("\xc9\xc9\x07\x00", 4);
781 ScopedVector<WebSocketFrame> frames_to_output;
782 AppendTo(&frames_to_output,
783 WebSocketFrameHeader::kOpCodeText,
784 kReserved1,
785 data1);
786 AppendTo(&frames_to_output,
787 WebSocketFrameHeader::kOpCodeContinuation,
788 kFinal | kReserved1,
789 data2);
790 ReadFramesStub stub(OK, &frames_to_output);
791 CompletionCallback callback;
792 ScopedVector<WebSocketFrame> frames;
795 InSequence s;
796 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
797 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
799 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
800 deflate_stream_->ReadFrames(&frames, callback));
803 TEST_F(WebSocketDeflateStreamTest,
804 Reserved1TurnsOnDuringReadingUncompressedContinuationFrame) {
805 ScopedVector<WebSocketFrame> frames_to_output;
806 AppendTo(&frames_to_output,
807 WebSocketFrameHeader::kOpCodeText,
808 kNoFlag,
809 "hello");
810 AppendTo(&frames_to_output,
811 WebSocketFrameHeader::kOpCodeContinuation,
812 kFinal | kReserved1,
813 "world");
814 ReadFramesStub stub(OK, &frames_to_output);
815 CompletionCallback callback;
816 ScopedVector<WebSocketFrame> frames;
819 InSequence s;
820 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
821 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
823 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
824 deflate_stream_->ReadFrames(&frames, callback));
827 TEST_F(WebSocketDeflateStreamTest, ReadCompressedMessages) {
828 ScopedVector<WebSocketFrame> frames_to_output;
829 AppendTo(&frames_to_output,
830 WebSocketFrameHeader::kOpCodeText,
831 kFinal | kReserved1,
832 std::string(
833 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
834 AppendTo(&frames_to_output,
835 WebSocketFrameHeader::kOpCodeText,
836 kFinal | kReserved1,
837 std::string("\x4a\x86\x33\x8d\x00\x00", 6));
838 ReadFramesStub stub(OK, &frames_to_output);
839 CompletionCallback callback;
840 ScopedVector<WebSocketFrame> frames;
843 InSequence s;
844 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
845 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
847 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
848 ASSERT_EQ(2u, frames.size());
849 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
850 EXPECT_TRUE(frames[0]->header.final);
851 EXPECT_FALSE(frames[0]->header.reserved1);
852 EXPECT_EQ("compressed1", ToString(frames[0]));
853 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
854 EXPECT_TRUE(frames[1]->header.final);
855 EXPECT_FALSE(frames[1]->header.reserved1);
856 EXPECT_EQ("compressed2", ToString(frames[1]));
859 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedMessages) {
860 ScopedVector<WebSocketFrame> frames_to_output;
861 AppendTo(&frames_to_output,
862 WebSocketFrameHeader::kOpCodeText,
863 kFinal,
864 "uncompressed1");
865 AppendTo(&frames_to_output,
866 WebSocketFrameHeader::kOpCodeText,
867 kFinal,
868 "uncompressed2");
869 ReadFramesStub stub(OK, &frames_to_output);
870 CompletionCallback callback;
871 ScopedVector<WebSocketFrame> frames;
874 InSequence s;
875 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
876 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
878 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
879 ASSERT_EQ(2u, frames.size());
880 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
881 EXPECT_TRUE(frames[0]->header.final);
882 EXPECT_FALSE(frames[0]->header.reserved1);
883 EXPECT_EQ("uncompressed1", ToString(frames[0]));
884 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
885 EXPECT_TRUE(frames[1]->header.final);
886 EXPECT_FALSE(frames[1]->header.reserved1);
887 EXPECT_EQ("uncompressed2", ToString(frames[1]));
890 TEST_F(WebSocketDeflateStreamTest,
891 ReadCompressedMessageThenUncompressedMessage) {
892 ScopedVector<WebSocketFrame> frames_to_output;
893 AppendTo(&frames_to_output,
894 WebSocketFrameHeader::kOpCodeText,
895 kFinal | kReserved1,
896 std::string(
897 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
898 AppendTo(&frames_to_output,
899 WebSocketFrameHeader::kOpCodeText,
900 kFinal,
901 "uncompressed");
902 ReadFramesStub stub(OK, &frames_to_output);
903 CompletionCallback callback;
904 ScopedVector<WebSocketFrame> frames;
907 InSequence s;
908 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
909 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
911 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
912 ASSERT_EQ(2u, frames.size());
913 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
914 EXPECT_TRUE(frames[0]->header.final);
915 EXPECT_FALSE(frames[0]->header.reserved1);
916 EXPECT_EQ("compressed", ToString(frames[0]));
917 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
918 EXPECT_TRUE(frames[1]->header.final);
919 EXPECT_FALSE(frames[1]->header.reserved1);
920 EXPECT_EQ("uncompressed", ToString(frames[1]));
923 TEST_F(WebSocketDeflateStreamTest,
924 ReadUncompressedMessageThenCompressedMessage) {
925 ScopedVector<WebSocketFrame> frames_to_output;
926 AppendTo(&frames_to_output,
927 WebSocketFrameHeader::kOpCodeText,
928 kFinal,
929 "uncompressed");
930 AppendTo(&frames_to_output,
931 WebSocketFrameHeader::kOpCodeText,
932 kFinal | kReserved1,
933 std::string(
934 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
935 ReadFramesStub stub(OK, &frames_to_output);
936 CompletionCallback callback;
937 ScopedVector<WebSocketFrame> frames;
940 InSequence s;
941 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
942 .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
944 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
945 ASSERT_EQ(2u, frames.size());
946 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
947 EXPECT_TRUE(frames[0]->header.final);
948 EXPECT_FALSE(frames[0]->header.reserved1);
949 EXPECT_EQ("uncompressed", ToString(frames[0]));
950 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
951 EXPECT_TRUE(frames[1]->header.final);
952 EXPECT_FALSE(frames[1]->header.reserved1);
953 EXPECT_EQ("compressed", ToString(frames[1]));
956 // This is a regression test for crbug.com/343506.
957 TEST_F(WebSocketDeflateStreamTest, ReadEmptyAsyncFrame) {
958 ScopedVector<ReadFramesStub> stub_vector;
959 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING));
960 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING));
961 MockCallback mock_callback;
962 CompletionCallback callback =
963 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
964 ScopedVector<WebSocketFrame> frames;
967 InSequence s;
968 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
969 .WillOnce(Invoke(stub_vector[0], &ReadFramesStub::Call));
971 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
972 .WillOnce(Invoke(stub_vector[1], &ReadFramesStub::Call));
974 EXPECT_CALL(mock_callback, Call(OK));
977 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
978 AppendTo(stub_vector[0]->frames_passed(),
979 WebSocketFrameHeader::kOpCodeText,
980 kReserved1,
981 std::string());
982 stub_vector[0]->callback().Run(OK);
983 AppendTo(stub_vector[1]->frames_passed(),
984 WebSocketFrameHeader::kOpCodeContinuation,
985 kFinal,
986 std::string("\x02\x00"));
987 stub_vector[1]->callback().Run(OK);
988 ASSERT_EQ(1u, frames.size());
989 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
990 EXPECT_EQ("", ToString(frames[0]));
993 TEST_F(WebSocketDeflateStreamTest, WriteEmpty) {
994 ScopedVector<WebSocketFrame> frames;
995 CompletionCallback callback;
997 InSequence s;
998 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0);
1000 EXPECT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1003 TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) {
1004 ScopedVector<WebSocketFrame> frames;
1005 CompletionCallback callback;
1007 InSequence s;
1008 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1009 .WillOnce(Return(ERR_FAILED));
1012 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello");
1013 predictor_->AddFramesToBeInput(frames);
1014 EXPECT_EQ(ERR_FAILED, deflate_stream_->WriteFrames(&frames, callback));
1015 predictor_->Clear();
1018 TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) {
1019 ScopedVector<WebSocketFrame> frames;
1020 CompletionCallback callback;
1021 WriteFramesStub stub(predictor_, OK);
1022 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1023 predictor_->AddFramesToBeInput(frames);
1025 InSequence s;
1026 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1027 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1029 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1030 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1031 ASSERT_EQ(1u, frames_passed.size());
1032 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1033 EXPECT_TRUE(frames_passed[0]->header.final);
1034 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1035 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1036 ToString(frames_passed[0]));
1039 TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) {
1040 WriteFramesStub stub(predictor_, ERR_IO_PENDING);
1041 MockCallback mock_callback, checkpoint;
1042 CompletionCallback callback =
1043 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
1044 ScopedVector<WebSocketFrame> frames;
1046 InSequence s;
1047 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1048 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1049 EXPECT_CALL(checkpoint, Call(0));
1050 EXPECT_CALL(mock_callback, Call(OK));
1052 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1053 predictor_->AddFramesToBeInput(frames);
1054 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->WriteFrames(&frames, callback));
1056 checkpoint.Call(0);
1057 stub.callback().Run(OK);
1059 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1060 ASSERT_EQ(1u, frames_passed.size());
1061 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1062 EXPECT_TRUE(frames_passed[0]->header.final);
1063 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1064 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1065 ToString(frames_passed[0]));
1068 TEST_F(WebSocketDeflateStreamTest, WriteControlFrameBetweenDataFrames) {
1069 ScopedVector<WebSocketFrame> frames;
1070 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "Hel");
1071 AppendTo(&frames, WebSocketFrameHeader::kOpCodePing, kFinal);
1072 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "lo");
1073 predictor_->AddFramesToBeInput(frames);
1074 WriteFramesStub stub(predictor_, OK);
1075 CompletionCallback callback;
1078 InSequence s;
1079 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1080 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1082 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1083 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1084 ASSERT_EQ(2u, frames_passed.size());
1085 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames_passed[0]->header.opcode);
1086 EXPECT_TRUE(frames_passed[0]->header.final);
1087 EXPECT_FALSE(frames_passed[0]->header.reserved1);
1088 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1089 EXPECT_TRUE(frames_passed[1]->header.final);
1090 EXPECT_TRUE(frames_passed[1]->header.reserved1);
1091 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1092 ToString(frames_passed[1]));
1095 TEST_F(WebSocketDeflateStreamTest, WriteEmptyMessage) {
1096 ScopedVector<WebSocketFrame> frames;
1097 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal);
1098 predictor_->AddFramesToBeInput(frames);
1099 WriteFramesStub stub(predictor_, OK);
1100 CompletionCallback callback;
1103 InSequence s;
1104 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1105 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1107 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1108 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1109 ASSERT_EQ(1u, frames_passed.size());
1110 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1111 EXPECT_TRUE(frames_passed[0]->header.final);
1112 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1113 EXPECT_EQ(std::string("\x00", 1), ToString(frames_passed[0]));
1116 TEST_F(WebSocketDeflateStreamTest, WriteUncompressedMessage) {
1117 ScopedVector<WebSocketFrame> frames;
1118 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAA");
1119 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AAA");
1120 predictor_->AddFramesToBeInput(frames);
1121 WriteFramesStub stub(predictor_, OK);
1122 CompletionCallback callback;
1124 predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE);
1127 InSequence s;
1128 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1129 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1131 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1132 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1133 ASSERT_EQ(2u, frames_passed.size());
1134 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1135 EXPECT_FALSE(frames_passed[0]->header.final);
1136 EXPECT_FALSE(frames_passed[0]->header.reserved1);
1137 EXPECT_EQ("AAAA", ToString(frames_passed[0]));
1138 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1139 frames_passed[1]->header.opcode);
1140 EXPECT_TRUE(frames_passed[1]->header.final);
1141 EXPECT_FALSE(frames_passed[1]->header.reserved1);
1142 EXPECT_EQ("AAA", ToString(frames_passed[1]));
1145 TEST_F(WebSocketDeflateStreamTest, LargeDeflatedFramesShouldBeSplit) {
1146 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
1147 LinearCongruentialGenerator lcg(133);
1148 WriteFramesStub stub(predictor_, OK);
1149 CompletionCallback callback;
1150 const size_t size = 1024;
1153 InSequence s;
1154 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1155 .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call));
1157 ScopedVector<WebSocketFrame> total_compressed_frames;
1159 deflater.Initialize(kWindowBits);
1160 while (true) {
1161 bool is_final = (total_compressed_frames.size() >= 2);
1162 ScopedVector<WebSocketFrame> frames;
1163 std::string data;
1164 for (size_t i = 0; i < size; ++i)
1165 data += static_cast<char>(lcg.Generate());
1166 deflater.AddBytes(data.data(), data.size());
1167 FrameFlag flag = is_final ? kFinal : kNoFlag;
1168 AppendTo(&frames, WebSocketFrameHeader::kOpCodeBinary, flag, data);
1169 predictor_->AddFramesToBeInput(frames);
1170 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1171 total_compressed_frames.insert(total_compressed_frames.end(),
1172 stub.frames()->begin(),
1173 stub.frames()->end());
1174 stub.frames()->weak_clear();
1175 if (is_final)
1176 break;
1178 deflater.Finish();
1179 std::string total_deflated;
1180 for (size_t i = 0; i < total_compressed_frames.size(); ++i) {
1181 WebSocketFrame* frame = total_compressed_frames[i];
1182 const WebSocketFrameHeader& header = frame->header;
1183 if (i > 0) {
1184 EXPECT_EQ(header.kOpCodeContinuation, header.opcode);
1185 EXPECT_FALSE(header.reserved1);
1186 } else {
1187 EXPECT_EQ(header.kOpCodeBinary, header.opcode);
1188 EXPECT_TRUE(header.reserved1);
1190 const bool is_final_frame = (i + 1 == total_compressed_frames.size());
1191 EXPECT_EQ(is_final_frame, header.final);
1192 if (!is_final_frame)
1193 EXPECT_GT(header.payload_length, 0ul);
1194 total_deflated += ToString(frame);
1196 EXPECT_EQ(total_deflated,
1197 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
1200 TEST_F(WebSocketDeflateStreamTest, WriteMultipleMessages) {
1201 ScopedVector<WebSocketFrame> frames;
1202 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1203 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1204 predictor_->AddFramesToBeInput(frames);
1205 WriteFramesStub stub(predictor_, OK);
1206 CompletionCallback callback;
1209 InSequence s;
1210 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1211 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1213 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1214 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1215 ASSERT_EQ(2u, frames_passed.size());
1216 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1217 EXPECT_TRUE(frames_passed[0]->header.final);
1218 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1219 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1220 ToString(frames_passed[0]));
1221 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1222 EXPECT_TRUE(frames_passed[1]->header.final);
1223 EXPECT_TRUE(frames_passed[1]->header.reserved1);
1224 EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed[1]));
1227 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
1228 WriteMultipleMessages) {
1229 ScopedVector<WebSocketFrame> frames;
1230 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1231 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1232 predictor_->AddFramesToBeInput(frames);
1233 WriteFramesStub stub(predictor_, OK);
1234 CompletionCallback callback;
1237 InSequence s;
1238 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1239 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1241 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1242 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1243 ASSERT_EQ(2u, frames_passed.size());
1244 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1245 EXPECT_TRUE(frames_passed[0]->header.final);
1246 EXPECT_TRUE(frames_passed[0]->header.reserved1);
1247 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1248 ToString(frames_passed[0]));
1249 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1250 EXPECT_TRUE(frames_passed[1]->header.final);
1251 EXPECT_TRUE(frames_passed[1]->header.reserved1);
1252 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1253 ToString(frames_passed[1]));
1256 // In order to check the stream works correctly for multiple
1257 // "PossiblyCompressedMessage"s, we test various messages at one test case.
1258 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
1259 WritePossiblyCompressMessages) {
1260 ScopedVector<WebSocketFrame> frames;
1261 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "He");
1262 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "llo");
1263 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAAAAAAAA");
1264 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AA");
1265 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "XX");
1266 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "YY");
1267 predictor_->AddFramesToBeInput(frames);
1268 WriteFramesStub stub(predictor_, OK);
1269 CompletionCallback callback;
1270 predictor_->set_result(WebSocketDeflatePredictor::TRY_DEFLATE);
1273 InSequence s;
1274 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1275 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1277 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1278 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1279 ASSERT_EQ(5u, frames_passed.size());
1281 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1282 EXPECT_FALSE(frames_passed[0]->header.final);
1283 EXPECT_FALSE(frames_passed[0]->header.reserved1);
1284 EXPECT_EQ("He", ToString(frames_passed[0]));
1285 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1286 frames_passed[1]->header.opcode);
1287 EXPECT_TRUE(frames_passed[1]->header.final);
1288 EXPECT_FALSE(frames_passed[1]->header.reserved1);
1289 EXPECT_EQ("llo", ToString(frames_passed[1]));
1291 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[2]->header.opcode);
1292 EXPECT_TRUE(frames_passed[2]->header.final);
1293 EXPECT_TRUE(frames_passed[2]->header.reserved1);
1294 EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6),
1295 ToString(frames_passed[2]));
1297 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[3]->header.opcode);
1298 EXPECT_FALSE(frames_passed[3]->header.final);
1299 EXPECT_FALSE(frames_passed[3]->header.reserved1);
1300 EXPECT_EQ("XX", ToString(frames_passed[3]));
1301 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1302 frames_passed[4]->header.opcode);
1303 EXPECT_TRUE(frames_passed[4]->header.final);
1304 EXPECT_FALSE(frames_passed[4]->header.reserved1);
1305 EXPECT_EQ("YY", ToString(frames_passed[4]));
1308 // This is based on the similar test from websocket_deflater_test.cc
1309 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits8) {
1310 SetUpWithWindowBits(8);
1311 CompletionCallback callback;
1312 AddCompressibleFrameString();
1313 WriteFramesStub stub(predictor_, OK);
1315 InSequence s;
1316 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1317 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1319 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback));
1320 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1321 ASSERT_EQ(1u, frames_passed.size());
1322 EXPECT_EQ(std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x39\xa3"
1323 "(?7\xb3\x34\x17\x00", 21),
1324 ToString(frames_passed[0]));
1327 // The same input with window_bits=10 returns smaller output.
1328 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits10) {
1329 SetUpWithWindowBits(10);
1330 CompletionCallback callback;
1331 AddCompressibleFrameString();
1332 WriteFramesStub stub(predictor_, OK);
1334 InSequence s;
1335 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1336 .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1338 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback));
1339 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1340 ASSERT_EQ(1u, frames_passed.size());
1341 EXPECT_EQ(
1342 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17),
1343 ToString(frames_passed[0]));
1346 } // namespace
1348 } // namespace net