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"
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"
31 typedef ::testing::MockFunction
<void(int)> MockCallback
; // NOLINT
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());
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
,
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
,
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
{
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
109 // - RecordWrittenDataFrame is called before writing the frame.
110 class WebSocketDeflatePredictorMock
: public WebSocketDeflatePredictor
{
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.";
119 if (!frames_written_
.empty()) {
120 ADD_FAILURE() << "There are extra written frames.";
125 // WebSocketDeflatePredictor functions.
126 virtual Result
Predict(const ScopedVector
<WebSocketFrame
>& frames
,
127 size_t frame_index
) OVERRIDE
{
130 virtual void RecordInputDataFrame(const WebSocketFrame
* frame
) OVERRIDE
{
131 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
)) {
132 ADD_FAILURE() << "Control frames should not be recorded.";
135 if (frame
->header
.reserved1
) {
136 ADD_FAILURE() << "Input frame may not be compressed.";
139 if (frames_to_be_input_
.empty()) {
140 ADD_FAILURE() << "Unexpected input data frame";
143 if (frame
!= frames_to_be_input_
.front()) {
144 ADD_FAILURE() << "Input data frame does not match the expectation.";
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.";
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
))
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
))
170 if (frames_written_
.empty()) {
171 ADD_FAILURE() << "There are missing frames to be written.";
174 if (frame
!= frames_written_
.front()) {
175 ADD_FAILURE() << "Written data frame does not match the expectation.";
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.
191 frames_to_be_input_
.clear();
192 frames_written_
.clear();
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
{
211 WebSocketDeflateStreamTest()
212 : mock_stream_(NULL
),
214 virtual ~WebSocketDeflateStreamTest() {}
216 virtual void SetUp() {
217 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT
, kWindowBits
);
221 // Initialize deflate_stream_ with the given parameters.
222 void Initialize(WebSocketDeflater::ContextTakeOverMode mode
,
224 mock_stream_
= new testing::StrictMock
<MockWebSocketStream
>;
225 predictor_
= new WebSocketDeflatePredictorMock
;
226 deflate_stream_
.reset(new WebSocketDeflateStream(
227 scoped_ptr
<WebSocketStream
>(mock_stream_
),
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
243 class WebSocketDeflateStreamWithDoNotTakeOverContextTest
244 : public WebSocketDeflateStreamTest
{
246 WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
247 virtual ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
249 virtual void SetUp() {
250 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT
, kWindowBits
);
254 class WebSocketDeflateStreamWithClientWindowBitsTest
255 : public WebSocketDeflateStreamTest
{
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_
);
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
{
286 explicit ReadFramesStub(int result
) : result_(result
) {}
288 ReadFramesStub(int result
, ScopedVector
<WebSocketFrame
>* frames_to_output
)
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_
);
302 int result() const { return result_
; }
303 const CompletionCallback
callback() const { return callback_
; }
304 ScopedVector
<WebSocketFrame
>* frames_passed() {
305 return frames_passed_
;
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
{
320 explicit WriteFramesStub(WebSocketDeflatePredictorMock
* predictor
,
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_
);
333 int result() const { return result_
; }
334 const CompletionCallback
callback() const { return callback_
; }
335 ScopedVector
<WebSocketFrame
>* frames() { return &frames_
; }
339 CompletionCallback callback_
;
340 ScopedVector
<WebSocketFrame
> frames_
;
341 WebSocketDeflatePredictorMock
* predictor_
;
344 TEST_F(WebSocketDeflateStreamTest
, ReadFailedImmediately
) {
345 ScopedVector
<WebSocketFrame
> frames
;
346 CompletionCallback callback
;
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
,
361 ReadFramesStub
stub(OK
, &frames_to_output
);
362 ScopedVector
<WebSocketFrame
> frames
;
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
));
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());
397 AppendTo(stub
.frames_passed(),
398 WebSocketFrameHeader::kOpCodeText
,
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
));
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());
428 AppendTo(stub
.frames_passed(),
429 WebSocketFrameHeader::kOpCodeText
,
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
,
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
;
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
;
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
));
475 AppendTo(stub
.frames_passed(),
476 WebSocketFrameHeader::kOpCodeText
,
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
,
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
;
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
,
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
,
536 ReadFramesStub
stub(OK
, &frames_to_output
);
537 CompletionCallback callback
;
538 ScopedVector
<WebSocketFrame
> frames
;
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
,
558 AppendTo(&frames_to_output
,
559 WebSocketFrameHeader::kOpCodeContinuation
,
562 ReadFramesStub
stub(OK
, &frames_to_output
);
563 CompletionCallback callback
;
564 ScopedVector
<WebSocketFrame
> frames
;
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
,
584 AppendTo(&frames_to_output
,
585 WebSocketFrameHeader::kOpCodeContinuation
,
587 ReadFramesStub
stub(OK
, &frames_to_output
);
588 CompletionCallback callback
;
589 ScopedVector
<WebSocketFrame
> frames
;
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
,
614 std::string("\x02\x00", 1));
615 AppendTo(&frames_to_output
,
616 WebSocketFrameHeader::kOpCodeContinuation
,
618 ReadFramesStub
stub(OK
, &frames_to_output
);
619 CompletionCallback callback
;
620 ScopedVector
<WebSocketFrame
> frames
;
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
,
643 AppendTo(&frames_to_output
,
644 WebSocketFrameHeader::kOpCodeContinuation
,
646 ReadFramesStub
stub(OK
, &frames_to_output
);
647 CompletionCallback callback
;
648 ScopedVector
<WebSocketFrame
> frames
;
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
,
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
;
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());
701 ScopedVector
<WebSocketFrame
> frames_to_output
;
702 AppendTo(&frames_to_output
,
703 WebSocketFrameHeader::kOpCodeBinary
,
705 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
707 ReadFramesStub
stub(OK
, &frames_to_output
);
708 CompletionCallback callback
;
709 ScopedVector
<WebSocketFrame
> frames
;
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());
743 ScopedVector
<WebSocketFrame
> frames_to_output
;
744 AppendTo(&frames_to_output
,
745 WebSocketFrameHeader::kOpCodeBinary
,
747 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
748 AppendTo(&frames_to_output
,
749 WebSocketFrameHeader::kOpCodeBinary
,
753 ReadFramesStub
stub(OK
, &frames_to_output
);
754 CompletionCallback callback
;
755 ScopedVector
<WebSocketFrame
> frames
;
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
,
786 AppendTo(&frames_to_output
,
787 WebSocketFrameHeader::kOpCodeContinuation
,
790 ReadFramesStub
stub(OK
, &frames_to_output
);
791 CompletionCallback callback
;
792 ScopedVector
<WebSocketFrame
> frames
;
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
,
810 AppendTo(&frames_to_output
,
811 WebSocketFrameHeader::kOpCodeContinuation
,
814 ReadFramesStub
stub(OK
, &frames_to_output
);
815 CompletionCallback callback
;
816 ScopedVector
<WebSocketFrame
> frames
;
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
,
833 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
834 AppendTo(&frames_to_output
,
835 WebSocketFrameHeader::kOpCodeText
,
837 std::string("\x4a\x86\x33\x8d\x00\x00", 6));
838 ReadFramesStub
stub(OK
, &frames_to_output
);
839 CompletionCallback callback
;
840 ScopedVector
<WebSocketFrame
> frames
;
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
,
865 AppendTo(&frames_to_output
,
866 WebSocketFrameHeader::kOpCodeText
,
869 ReadFramesStub
stub(OK
, &frames_to_output
);
870 CompletionCallback callback
;
871 ScopedVector
<WebSocketFrame
> frames
;
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
,
897 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
898 AppendTo(&frames_to_output
,
899 WebSocketFrameHeader::kOpCodeText
,
902 ReadFramesStub
stub(OK
, &frames_to_output
);
903 CompletionCallback callback
;
904 ScopedVector
<WebSocketFrame
> frames
;
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
,
930 AppendTo(&frames_to_output
,
931 WebSocketFrameHeader::kOpCodeText
,
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
;
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
;
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
,
982 stub_vector
[0]->callback().Run(OK
);
983 AppendTo(stub_vector
[1]->frames_passed(),
984 WebSocketFrameHeader::kOpCodeContinuation
,
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
;
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
;
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
);
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
;
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
));
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
;
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
;
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
);
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;
1154 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1155 .WillRepeatedly(Invoke(&stub
, &WriteFramesStub::Call
));
1157 ScopedVector
<WebSocketFrame
> total_compressed_frames
;
1159 deflater
.Initialize(kWindowBits
);
1161 bool is_final
= (total_compressed_frames
.size() >= 2);
1162 ScopedVector
<WebSocketFrame
> frames
;
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();
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
;
1184 EXPECT_EQ(header
.kOpCodeContinuation
, header
.opcode
);
1185 EXPECT_FALSE(header
.reserved1
);
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
;
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
;
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
);
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
);
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
);
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());
1342 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17),
1343 ToString(frames_passed
[0]));