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
.get() ? ToString(frame
->data
, frame
->header
.payload_length
)
75 void AppendTo(ScopedVector
<WebSocketFrame
>* frames
,
76 WebSocketFrameHeader::OpCode opcode
,
78 const std::string
& data
) {
79 scoped_ptr
<WebSocketFrame
> frame(new WebSocketFrame(opcode
));
80 frame
->header
.final
= (flag
& kFinal
);
81 frame
->header
.reserved1
= (flag
& kReserved1
);
82 frame
->data
= ToIOBuffer(data
);
83 frame
->header
.payload_length
= data
.size();
84 frames
->push_back(frame
.release());
87 void AppendTo(ScopedVector
<WebSocketFrame
>* frames
,
88 WebSocketFrameHeader::OpCode opcode
,
90 scoped_ptr
<WebSocketFrame
> frame(new WebSocketFrame(opcode
));
91 frame
->header
.final
= (flag
& kFinal
);
92 frame
->header
.reserved1
= (flag
& kReserved1
);
93 frames
->push_back(frame
.release());
96 class MockWebSocketStream
: public WebSocketStream
{
98 MOCK_METHOD2(ReadFrames
, int(ScopedVector
<WebSocketFrame
>*,
99 const CompletionCallback
&));
100 MOCK_METHOD2(WriteFrames
, int(ScopedVector
<WebSocketFrame
>*,
101 const CompletionCallback
&));
102 MOCK_METHOD0(Close
, void());
103 MOCK_CONST_METHOD0(GetSubProtocol
, std::string());
104 MOCK_CONST_METHOD0(GetExtensions
, std::string());
107 // This mock class relies on some assumptions.
108 // - RecordInputDataFrame is called after the corresponding WriteFrames
110 // - RecordWrittenDataFrame is called before writing the frame.
111 class WebSocketDeflatePredictorMock
: public WebSocketDeflatePredictor
{
113 WebSocketDeflatePredictorMock() : result_(DEFLATE
) {}
114 ~WebSocketDeflatePredictorMock() override
{
115 // Verify whether all expectaions are consumed.
116 if (!frames_to_be_input_
.empty()) {
117 ADD_FAILURE() << "There are missing frames to be input.";
120 if (!frames_written_
.empty()) {
121 ADD_FAILURE() << "There are extra written frames.";
126 // WebSocketDeflatePredictor functions.
127 Result
Predict(const ScopedVector
<WebSocketFrame
>& frames
,
128 size_t frame_index
) override
{
131 void RecordInputDataFrame(const WebSocketFrame
* frame
) override
{
132 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
)) {
133 ADD_FAILURE() << "Control frames should not be recorded.";
136 if (frame
->header
.reserved1
) {
137 ADD_FAILURE() << "Input frame may not be compressed.";
140 if (frames_to_be_input_
.empty()) {
141 ADD_FAILURE() << "Unexpected input data frame";
144 if (frame
!= frames_to_be_input_
.front()) {
145 ADD_FAILURE() << "Input data frame does not match the expectation.";
148 frames_to_be_input_
.pop_front();
150 void RecordWrittenDataFrame(const WebSocketFrame
* frame
) override
{
151 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
)) {
152 ADD_FAILURE() << "Control frames should not be recorded.";
155 frames_written_
.push_back(frame
);
158 // Sets |result_| for the |Predict| return value.
159 void set_result(Result result
) { result_
= result
; }
161 // Adds |frame| as an expectation of future |RecordInputDataFrame| call.
162 void AddFrameToBeInput(const WebSocketFrame
* frame
) {
163 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
))
165 frames_to_be_input_
.push_back(frame
);
167 // Verifies that |frame| is recorded in order.
168 void VerifySentFrame(const WebSocketFrame
* frame
) {
169 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
))
171 if (frames_written_
.empty()) {
172 ADD_FAILURE() << "There are missing frames to be written.";
175 if (frame
!= frames_written_
.front()) {
176 ADD_FAILURE() << "Written data frame does not match the expectation.";
179 frames_written_
.pop_front();
181 void AddFramesToBeInput(const ScopedVector
<WebSocketFrame
>& frames
) {
182 for (size_t i
= 0; i
< frames
.size(); ++i
)
183 AddFrameToBeInput(frames
[i
]);
185 void VerifySentFrames(const ScopedVector
<WebSocketFrame
>& frames
) {
186 for (size_t i
= 0; i
< frames
.size(); ++i
)
187 VerifySentFrame(frames
[i
]);
189 // Call this method in order to disable checks in the destructor when
190 // WriteFrames fails.
192 frames_to_be_input_
.clear();
193 frames_written_
.clear();
198 // Data frames which will be recorded by |RecordInputFrames|.
199 // Pushed by |AddFrameToBeInput| and popped and verified by
200 // |RecordInputFrames|.
201 std::deque
<const WebSocketFrame
*> frames_to_be_input_
;
202 // Data frames recorded by |RecordWrittenFrames|.
203 // Pushed by |RecordWrittenFrames| and popped and verified by
204 // |VerifySentFrame|.
205 std::deque
<const WebSocketFrame
*> frames_written_
;
207 DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock
);
210 class WebSocketDeflateStreamTest
: public ::testing::Test
{
212 WebSocketDeflateStreamTest()
213 : mock_stream_(NULL
),
215 ~WebSocketDeflateStreamTest() override
{}
217 void SetUp() override
{
218 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT
, kWindowBits
);
222 // Initialize deflate_stream_ with the given parameters.
223 void Initialize(WebSocketDeflater::ContextTakeOverMode mode
,
225 mock_stream_
= new testing::StrictMock
<MockWebSocketStream
>;
226 predictor_
= new WebSocketDeflatePredictorMock
;
227 deflate_stream_
.reset(new WebSocketDeflateStream(
228 scoped_ptr
<WebSocketStream
>(mock_stream_
),
231 scoped_ptr
<WebSocketDeflatePredictor
>(predictor_
)));
234 scoped_ptr
<WebSocketDeflateStream
> deflate_stream_
;
235 // Owned by |deflate_stream_|.
236 MockWebSocketStream
* mock_stream_
;
237 // Owned by |deflate_stream_|.
238 WebSocketDeflatePredictorMock
* predictor_
;
241 // Since WebSocketDeflater with DoNotTakeOverContext is well tested at
242 // websocket_deflater_test.cc, we have only a few tests for this configuration
244 class WebSocketDeflateStreamWithDoNotTakeOverContextTest
245 : public WebSocketDeflateStreamTest
{
247 WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
248 ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() override
{}
250 void SetUp() override
{
251 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT
, kWindowBits
);
255 class WebSocketDeflateStreamWithClientWindowBitsTest
256 : public WebSocketDeflateStreamTest
{
258 WebSocketDeflateStreamWithClientWindowBitsTest() {}
259 ~WebSocketDeflateStreamWithClientWindowBitsTest() override
{}
261 // Overridden to postpone the call to Initialize().
262 void SetUp() override
{}
264 // This needs to be called explicitly from the tests.
265 void SetUpWithWindowBits(int window_bits
) {
266 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT
, window_bits
);
269 // Add a frame which will be compressed to a smaller size if the window
270 // size is large enough.
271 void AddCompressibleFrameString() {
272 const std::string word
= "Chromium";
273 const std::string payload
= word
+ std::string(256, 'a') + word
;
274 AppendTo(&frames_
, WebSocketFrameHeader::kOpCodeText
, kFinal
, payload
);
275 predictor_
->AddFramesToBeInput(frames_
);
279 ScopedVector
<WebSocketFrame
> frames_
;
282 // ReadFrameStub is a stub for WebSocketStream::ReadFrames.
283 // It returns |result_| and |frames_to_output_| to the caller and
284 // saves parameters to |frames_passed_| and |callback_|.
285 class ReadFramesStub
{
287 explicit ReadFramesStub(int result
) : result_(result
) {}
289 ReadFramesStub(int result
, ScopedVector
<WebSocketFrame
>* frames_to_output
)
291 frames_to_output_
.swap(*frames_to_output
);
294 int Call(ScopedVector
<WebSocketFrame
>* frames
,
295 const CompletionCallback
& callback
) {
296 DCHECK(frames
->empty());
297 frames_passed_
= frames
;
298 callback_
= callback
;
299 frames
->swap(frames_to_output_
);
303 int result() const { return result_
; }
304 const CompletionCallback
callback() const { return callback_
; }
305 ScopedVector
<WebSocketFrame
>* frames_passed() {
306 return frames_passed_
;
311 CompletionCallback callback_
;
312 ScopedVector
<WebSocketFrame
> frames_to_output_
;
313 ScopedVector
<WebSocketFrame
>* frames_passed_
;
316 // WriteFramesStub is a stub for WebSocketStream::WriteFrames.
317 // It returns |result_| and |frames_| to the caller and
318 // saves |callback| parameter to |callback_|.
319 class WriteFramesStub
{
321 explicit WriteFramesStub(WebSocketDeflatePredictorMock
* predictor
,
323 : result_(result
), predictor_(predictor
) {}
325 int Call(ScopedVector
<WebSocketFrame
>* frames
,
326 const CompletionCallback
& callback
) {
327 frames_
.insert(frames_
.end(), frames
->begin(), frames
->end());
328 frames
->weak_clear();
329 callback_
= callback
;
330 predictor_
->VerifySentFrames(frames_
);
334 int result() const { return result_
; }
335 const CompletionCallback
callback() const { return callback_
; }
336 ScopedVector
<WebSocketFrame
>* frames() { return &frames_
; }
340 CompletionCallback callback_
;
341 ScopedVector
<WebSocketFrame
> frames_
;
342 WebSocketDeflatePredictorMock
* predictor_
;
345 TEST_F(WebSocketDeflateStreamTest
, ReadFailedImmediately
) {
346 ScopedVector
<WebSocketFrame
> frames
;
347 CompletionCallback callback
;
350 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
351 .WillOnce(Return(ERR_FAILED
));
353 EXPECT_EQ(ERR_FAILED
, deflate_stream_
->ReadFrames(&frames
, callback
));
356 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedFrameImmediately
) {
357 ScopedVector
<WebSocketFrame
> frames_to_output
;
358 AppendTo(&frames_to_output
,
359 WebSocketFrameHeader::kOpCodeText
,
362 ReadFramesStub
stub(OK
, &frames_to_output
);
363 ScopedVector
<WebSocketFrame
> frames
;
367 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
368 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
370 CompletionCallback callback
;
371 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
372 ASSERT_EQ(1u, frames
.size());
373 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
374 EXPECT_TRUE(frames
[0]->header
.final
);
375 EXPECT_FALSE(frames
[0]->header
.reserved1
);
376 EXPECT_EQ("hello", ToString(frames
[0]));
379 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedFrameAsync
) {
380 ReadFramesStub
stub(ERR_IO_PENDING
);
381 ScopedVector
<WebSocketFrame
> frames
;
382 MockCallback mock_callback
, checkpoint
;
383 CompletionCallback callback
=
384 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
388 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
389 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
390 EXPECT_CALL(checkpoint
, Call(0));
391 EXPECT_CALL(mock_callback
, Call(OK
));
393 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
394 ASSERT_EQ(0u, frames
.size());
398 AppendTo(stub
.frames_passed(),
399 WebSocketFrameHeader::kOpCodeText
,
402 stub
.callback().Run(OK
);
403 ASSERT_EQ(1u, frames
.size());
404 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
405 EXPECT_TRUE(frames
[0]->header
.final
);
406 EXPECT_FALSE(frames
[0]->header
.reserved1
);
407 EXPECT_EQ("hello", ToString(frames
[0]));
410 TEST_F(WebSocketDeflateStreamTest
, ReadFailedAsync
) {
411 ReadFramesStub
stub(ERR_IO_PENDING
);
412 ScopedVector
<WebSocketFrame
> frames
;
413 MockCallback mock_callback
, checkpoint
;
414 CompletionCallback callback
=
415 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
419 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
420 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
421 EXPECT_CALL(checkpoint
, Call(0));
422 EXPECT_CALL(mock_callback
, Call(ERR_FAILED
));
424 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
425 ASSERT_EQ(0u, frames
.size());
429 AppendTo(stub
.frames_passed(),
430 WebSocketFrameHeader::kOpCodeText
,
433 stub
.callback().Run(ERR_FAILED
);
434 ASSERT_EQ(0u, frames
.size());
437 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedFrameImmediately
) {
438 ScopedVector
<WebSocketFrame
> frames_to_output
;
439 AppendTo(&frames_to_output
,
440 WebSocketFrameHeader::kOpCodeText
,
442 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
443 ReadFramesStub
stub(OK
, &frames_to_output
);
444 CompletionCallback callback
;
445 ScopedVector
<WebSocketFrame
> frames
;
448 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
449 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
451 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
452 ASSERT_EQ(1u, frames
.size());
453 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
454 EXPECT_TRUE(frames
[0]->header
.final
);
455 EXPECT_FALSE(frames
[0]->header
.reserved1
);
456 EXPECT_EQ("Hello", ToString(frames
[0]));
459 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedFrameAsync
) {
460 ReadFramesStub
stub(ERR_IO_PENDING
);
461 MockCallback mock_callback
, checkpoint
;
462 CompletionCallback callback
=
463 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
464 ScopedVector
<WebSocketFrame
> frames
;
467 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
468 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
469 EXPECT_CALL(checkpoint
, Call(0));
470 EXPECT_CALL(mock_callback
, Call(OK
));
472 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
476 AppendTo(stub
.frames_passed(),
477 WebSocketFrameHeader::kOpCodeText
,
479 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
480 stub
.callback().Run(OK
);
482 ASSERT_EQ(1u, frames
.size());
483 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
484 EXPECT_TRUE(frames
[0]->header
.final
);
485 EXPECT_FALSE(frames
[0]->header
.reserved1
);
486 EXPECT_EQ("Hello", ToString(frames
[0]));
489 TEST_F(WebSocketDeflateStreamTest
,
490 ReadCompressedFrameFragmentImmediatelyButInflaterReturnsPending
) {
491 ScopedVector
<WebSocketFrame
> frames_to_output
;
492 const std::string
data1("\xf2", 1);
493 const std::string
data2("\x48\xcd\xc9\xc9\x07\x00", 6);
494 AppendTo(&frames_to_output
,
495 WebSocketFrameHeader::kOpCodeText
,
498 ReadFramesStub
stub1(OK
, &frames_to_output
), stub2(ERR_IO_PENDING
);
499 MockCallback mock_callback
, checkpoint
;
500 CompletionCallback callback
=
501 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
502 ScopedVector
<WebSocketFrame
> frames
;
506 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
507 .WillOnce(Invoke(&stub1
, &ReadFramesStub::Call
))
508 .WillOnce(Invoke(&stub2
, &ReadFramesStub::Call
));
509 EXPECT_CALL(checkpoint
, Call(0));
510 EXPECT_CALL(mock_callback
, Call(OK
));
512 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
513 ASSERT_EQ(0u, frames
.size());
515 AppendTo(stub2
.frames_passed(),
516 WebSocketFrameHeader::kOpCodeText
,
521 stub2
.callback().Run(OK
);
523 ASSERT_EQ(1u, frames
.size());
524 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
525 EXPECT_TRUE(frames
[0]->header
.final
);
526 EXPECT_FALSE(frames
[0]->header
.reserved1
);
527 EXPECT_EQ("Hello", ToString(frames
[0]));
530 TEST_F(WebSocketDeflateStreamTest
, ReadInvalidCompressedPayload
) {
531 const std::string
data("\xf2\x48\xcdINVALID", 10);
532 ScopedVector
<WebSocketFrame
> frames_to_output
;
533 AppendTo(&frames_to_output
,
534 WebSocketFrameHeader::kOpCodeText
,
537 ReadFramesStub
stub(OK
, &frames_to_output
);
538 CompletionCallback callback
;
539 ScopedVector
<WebSocketFrame
> frames
;
543 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
544 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
546 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR
,
547 deflate_stream_
->ReadFrames(&frames
, callback
));
548 ASSERT_EQ(0u, frames
.size());
551 TEST_F(WebSocketDeflateStreamTest
, MergeMultipleFramesInReadFrames
) {
552 const std::string
data1("\xf2\x48\xcd", 3);
553 const std::string
data2("\xc9\xc9\x07\x00", 4);
554 ScopedVector
<WebSocketFrame
> frames_to_output
;
555 AppendTo(&frames_to_output
,
556 WebSocketFrameHeader::kOpCodeText
,
559 AppendTo(&frames_to_output
,
560 WebSocketFrameHeader::kOpCodeContinuation
,
563 ReadFramesStub
stub(OK
, &frames_to_output
);
564 CompletionCallback callback
;
565 ScopedVector
<WebSocketFrame
> frames
;
569 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
570 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
572 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
573 ASSERT_EQ(1u, frames
.size());
574 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
575 EXPECT_TRUE(frames
[0]->header
.final
);
576 EXPECT_FALSE(frames
[0]->header
.reserved1
);
577 EXPECT_EQ("Hello", ToString(frames
[0]));
580 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedEmptyFrames
) {
581 ScopedVector
<WebSocketFrame
> frames_to_output
;
582 AppendTo(&frames_to_output
,
583 WebSocketFrameHeader::kOpCodeText
,
585 AppendTo(&frames_to_output
,
586 WebSocketFrameHeader::kOpCodeContinuation
,
588 ReadFramesStub
stub(OK
, &frames_to_output
);
589 CompletionCallback callback
;
590 ScopedVector
<WebSocketFrame
> frames
;
594 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
595 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
597 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
598 ASSERT_EQ(2u, frames
.size());
599 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
600 EXPECT_FALSE(frames
[0]->header
.final
);
601 EXPECT_FALSE(frames
[0]->header
.reserved1
);
602 EXPECT_EQ("", ToString(frames
[0]));
603 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
604 frames
[1]->header
.opcode
);
605 EXPECT_TRUE(frames
[1]->header
.final
);
606 EXPECT_FALSE(frames
[1]->header
.reserved1
);
607 EXPECT_EQ("", ToString(frames
[1]));
610 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedEmptyFrames
) {
611 ScopedVector
<WebSocketFrame
> frames_to_output
;
612 AppendTo(&frames_to_output
,
613 WebSocketFrameHeader::kOpCodeText
,
615 std::string("\x02\x00", 1));
616 AppendTo(&frames_to_output
,
617 WebSocketFrameHeader::kOpCodeContinuation
,
619 ReadFramesStub
stub(OK
, &frames_to_output
);
620 CompletionCallback callback
;
621 ScopedVector
<WebSocketFrame
> frames
;
625 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
626 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
628 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
629 ASSERT_EQ(1u, frames
.size());
630 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
631 EXPECT_TRUE(frames
[0]->header
.final
);
632 EXPECT_FALSE(frames
[0]->header
.reserved1
);
633 EXPECT_EQ("", ToString(frames
[0]));
636 TEST_F(WebSocketDeflateStreamTest
,
637 ReadCompressedFrameFollowedByEmptyFrame
) {
638 const std::string
data("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
639 ScopedVector
<WebSocketFrame
> frames_to_output
;
640 AppendTo(&frames_to_output
,
641 WebSocketFrameHeader::kOpCodeText
,
644 AppendTo(&frames_to_output
,
645 WebSocketFrameHeader::kOpCodeContinuation
,
647 ReadFramesStub
stub(OK
, &frames_to_output
);
648 CompletionCallback callback
;
649 ScopedVector
<WebSocketFrame
> frames
;
653 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
654 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
656 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
657 ASSERT_EQ(1u, frames
.size());
658 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
659 EXPECT_TRUE(frames
[0]->header
.final
);
660 EXPECT_FALSE(frames
[0]->header
.reserved1
);
661 EXPECT_EQ("Hello", ToString(frames
[0]));
664 TEST_F(WebSocketDeflateStreamTest
, ReadControlFrameBetweenDataFrames
) {
665 const std::string
data1("\xf2\x48\xcd", 3);
666 const std::string
data2("\xc9\xc9\x07\x00", 4);
667 ScopedVector
<WebSocketFrame
> frames_to_output
;
668 AppendTo(&frames_to_output
,
669 WebSocketFrameHeader::kOpCodeText
,
672 AppendTo(&frames_to_output
, WebSocketFrameHeader::kOpCodePing
, kFinal
);
673 AppendTo(&frames_to_output
, WebSocketFrameHeader::kOpCodeText
, kFinal
, data2
);
674 ReadFramesStub
stub(OK
, &frames_to_output
);
675 CompletionCallback callback
;
676 ScopedVector
<WebSocketFrame
> frames
;
680 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
681 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
683 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
684 ASSERT_EQ(2u, frames
.size());
685 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing
, frames
[0]->header
.opcode
);
686 EXPECT_TRUE(frames
[0]->header
.final
);
687 EXPECT_FALSE(frames
[0]->header
.reserved1
);
688 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
689 EXPECT_TRUE(frames
[1]->header
.final
);
690 EXPECT_FALSE(frames
[1]->header
.reserved1
);
691 EXPECT_EQ("Hello", ToString(frames
[1]));
694 TEST_F(WebSocketDeflateStreamTest
, SplitToMultipleFramesInReadFrames
) {
695 WebSocketDeflater
deflater(WebSocketDeflater::TAKE_OVER_CONTEXT
);
696 deflater
.Initialize(kWindowBits
);
697 const size_t kSize
= kChunkSize
* 3;
698 const std::string
original_data(kSize
, 'a');
699 deflater
.AddBytes(original_data
.data(), original_data
.size());
702 ScopedVector
<WebSocketFrame
> frames_to_output
;
703 AppendTo(&frames_to_output
,
704 WebSocketFrameHeader::kOpCodeBinary
,
706 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
708 ReadFramesStub
stub(OK
, &frames_to_output
);
709 CompletionCallback callback
;
710 ScopedVector
<WebSocketFrame
> frames
;
713 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
714 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
717 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
718 ASSERT_EQ(3u, frames
.size());
719 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary
, frames
[0]->header
.opcode
);
720 EXPECT_FALSE(frames
[0]->header
.final
);
721 EXPECT_FALSE(frames
[0]->header
.reserved1
);
722 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[0]->header
.payload_length
));
723 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
724 frames
[1]->header
.opcode
);
725 EXPECT_FALSE(frames
[1]->header
.final
);
726 EXPECT_FALSE(frames
[1]->header
.reserved1
);
727 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[1]->header
.payload_length
));
728 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
729 frames
[2]->header
.opcode
);
730 EXPECT_TRUE(frames
[2]->header
.final
);
731 EXPECT_FALSE(frames
[2]->header
.reserved1
);
732 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[2]->header
.payload_length
));
733 EXPECT_EQ(original_data
,
734 ToString(frames
[0]) + ToString(frames
[1]) + ToString(frames
[2]));
737 TEST_F(WebSocketDeflateStreamTest
, InflaterInternalDataCanBeEmpty
) {
738 WebSocketDeflater
deflater(WebSocketDeflater::TAKE_OVER_CONTEXT
);
739 deflater
.Initialize(kWindowBits
);
740 const std::string
original_data(kChunkSize
, 'a');
741 deflater
.AddBytes(original_data
.data(), original_data
.size());
744 ScopedVector
<WebSocketFrame
> frames_to_output
;
745 AppendTo(&frames_to_output
,
746 WebSocketFrameHeader::kOpCodeBinary
,
748 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
749 AppendTo(&frames_to_output
,
750 WebSocketFrameHeader::kOpCodeBinary
,
754 ReadFramesStub
stub(OK
, &frames_to_output
);
755 CompletionCallback callback
;
756 ScopedVector
<WebSocketFrame
> frames
;
759 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
760 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
763 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
764 ASSERT_EQ(2u, frames
.size());
765 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary
, frames
[0]->header
.opcode
);
766 EXPECT_FALSE(frames
[0]->header
.final
);
767 EXPECT_FALSE(frames
[0]->header
.reserved1
);
768 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[0]->header
.payload_length
));
770 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
771 frames
[1]->header
.opcode
);
772 EXPECT_TRUE(frames
[1]->header
.final
);
773 EXPECT_FALSE(frames
[1]->header
.reserved1
);
774 EXPECT_EQ(0u, static_cast<size_t>(frames
[1]->header
.payload_length
));
775 EXPECT_EQ(original_data
, ToString(frames
[0]) + ToString(frames
[1]));
778 TEST_F(WebSocketDeflateStreamTest
,
779 Reserved1TurnsOnDuringReadingCompressedContinuationFrame
) {
780 const std::string
data1("\xf2\x48\xcd", 3);
781 const std::string
data2("\xc9\xc9\x07\x00", 4);
782 ScopedVector
<WebSocketFrame
> frames_to_output
;
783 AppendTo(&frames_to_output
,
784 WebSocketFrameHeader::kOpCodeText
,
787 AppendTo(&frames_to_output
,
788 WebSocketFrameHeader::kOpCodeContinuation
,
791 ReadFramesStub
stub(OK
, &frames_to_output
);
792 CompletionCallback callback
;
793 ScopedVector
<WebSocketFrame
> frames
;
797 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
798 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
800 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR
,
801 deflate_stream_
->ReadFrames(&frames
, callback
));
804 TEST_F(WebSocketDeflateStreamTest
,
805 Reserved1TurnsOnDuringReadingUncompressedContinuationFrame
) {
806 ScopedVector
<WebSocketFrame
> frames_to_output
;
807 AppendTo(&frames_to_output
,
808 WebSocketFrameHeader::kOpCodeText
,
811 AppendTo(&frames_to_output
,
812 WebSocketFrameHeader::kOpCodeContinuation
,
815 ReadFramesStub
stub(OK
, &frames_to_output
);
816 CompletionCallback callback
;
817 ScopedVector
<WebSocketFrame
> frames
;
821 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
822 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
824 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR
,
825 deflate_stream_
->ReadFrames(&frames
, callback
));
828 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedMessages
) {
829 ScopedVector
<WebSocketFrame
> frames_to_output
;
830 AppendTo(&frames_to_output
,
831 WebSocketFrameHeader::kOpCodeText
,
834 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
835 AppendTo(&frames_to_output
,
836 WebSocketFrameHeader::kOpCodeText
,
838 std::string("\x4a\x86\x33\x8d\x00\x00", 6));
839 ReadFramesStub
stub(OK
, &frames_to_output
);
840 CompletionCallback callback
;
841 ScopedVector
<WebSocketFrame
> frames
;
845 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
846 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
848 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
849 ASSERT_EQ(2u, frames
.size());
850 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
851 EXPECT_TRUE(frames
[0]->header
.final
);
852 EXPECT_FALSE(frames
[0]->header
.reserved1
);
853 EXPECT_EQ("compressed1", ToString(frames
[0]));
854 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
855 EXPECT_TRUE(frames
[1]->header
.final
);
856 EXPECT_FALSE(frames
[1]->header
.reserved1
);
857 EXPECT_EQ("compressed2", ToString(frames
[1]));
860 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedMessages
) {
861 ScopedVector
<WebSocketFrame
> frames_to_output
;
862 AppendTo(&frames_to_output
,
863 WebSocketFrameHeader::kOpCodeText
,
866 AppendTo(&frames_to_output
,
867 WebSocketFrameHeader::kOpCodeText
,
870 ReadFramesStub
stub(OK
, &frames_to_output
);
871 CompletionCallback callback
;
872 ScopedVector
<WebSocketFrame
> frames
;
876 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
877 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
879 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
880 ASSERT_EQ(2u, frames
.size());
881 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
882 EXPECT_TRUE(frames
[0]->header
.final
);
883 EXPECT_FALSE(frames
[0]->header
.reserved1
);
884 EXPECT_EQ("uncompressed1", ToString(frames
[0]));
885 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
886 EXPECT_TRUE(frames
[1]->header
.final
);
887 EXPECT_FALSE(frames
[1]->header
.reserved1
);
888 EXPECT_EQ("uncompressed2", ToString(frames
[1]));
891 TEST_F(WebSocketDeflateStreamTest
,
892 ReadCompressedMessageThenUncompressedMessage
) {
893 ScopedVector
<WebSocketFrame
> frames_to_output
;
894 AppendTo(&frames_to_output
,
895 WebSocketFrameHeader::kOpCodeText
,
898 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
899 AppendTo(&frames_to_output
,
900 WebSocketFrameHeader::kOpCodeText
,
903 ReadFramesStub
stub(OK
, &frames_to_output
);
904 CompletionCallback callback
;
905 ScopedVector
<WebSocketFrame
> frames
;
909 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
910 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
912 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
913 ASSERT_EQ(2u, frames
.size());
914 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
915 EXPECT_TRUE(frames
[0]->header
.final
);
916 EXPECT_FALSE(frames
[0]->header
.reserved1
);
917 EXPECT_EQ("compressed", ToString(frames
[0]));
918 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
919 EXPECT_TRUE(frames
[1]->header
.final
);
920 EXPECT_FALSE(frames
[1]->header
.reserved1
);
921 EXPECT_EQ("uncompressed", ToString(frames
[1]));
924 TEST_F(WebSocketDeflateStreamTest
,
925 ReadUncompressedMessageThenCompressedMessage
) {
926 ScopedVector
<WebSocketFrame
> frames_to_output
;
927 AppendTo(&frames_to_output
,
928 WebSocketFrameHeader::kOpCodeText
,
931 AppendTo(&frames_to_output
,
932 WebSocketFrameHeader::kOpCodeText
,
935 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
936 ReadFramesStub
stub(OK
, &frames_to_output
);
937 CompletionCallback callback
;
938 ScopedVector
<WebSocketFrame
> frames
;
942 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
943 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
945 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
946 ASSERT_EQ(2u, frames
.size());
947 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
948 EXPECT_TRUE(frames
[0]->header
.final
);
949 EXPECT_FALSE(frames
[0]->header
.reserved1
);
950 EXPECT_EQ("uncompressed", ToString(frames
[0]));
951 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
952 EXPECT_TRUE(frames
[1]->header
.final
);
953 EXPECT_FALSE(frames
[1]->header
.reserved1
);
954 EXPECT_EQ("compressed", ToString(frames
[1]));
957 // This is a regression test for crbug.com/343506.
958 TEST_F(WebSocketDeflateStreamTest
, ReadEmptyAsyncFrame
) {
959 ScopedVector
<ReadFramesStub
> stub_vector
;
960 stub_vector
.push_back(new ReadFramesStub(ERR_IO_PENDING
));
961 stub_vector
.push_back(new ReadFramesStub(ERR_IO_PENDING
));
962 MockCallback mock_callback
;
963 CompletionCallback callback
=
964 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
965 ScopedVector
<WebSocketFrame
> frames
;
969 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
970 .WillOnce(Invoke(stub_vector
[0], &ReadFramesStub::Call
));
972 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
973 .WillOnce(Invoke(stub_vector
[1], &ReadFramesStub::Call
));
975 EXPECT_CALL(mock_callback
, Call(OK
));
978 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
979 AppendTo(stub_vector
[0]->frames_passed(),
980 WebSocketFrameHeader::kOpCodeText
,
983 stub_vector
[0]->callback().Run(OK
);
984 AppendTo(stub_vector
[1]->frames_passed(),
985 WebSocketFrameHeader::kOpCodeContinuation
,
987 std::string("\x02\x00"));
988 stub_vector
[1]->callback().Run(OK
);
989 ASSERT_EQ(1u, frames
.size());
990 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
991 EXPECT_EQ("", ToString(frames
[0]));
994 TEST_F(WebSocketDeflateStreamTest
, WriteEmpty
) {
995 ScopedVector
<WebSocketFrame
> frames
;
996 CompletionCallback callback
;
999 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
)).Times(0);
1001 EXPECT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1004 TEST_F(WebSocketDeflateStreamTest
, WriteFailedImmediately
) {
1005 ScopedVector
<WebSocketFrame
> frames
;
1006 CompletionCallback callback
;
1009 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1010 .WillOnce(Return(ERR_FAILED
));
1013 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "hello");
1014 predictor_
->AddFramesToBeInput(frames
);
1015 EXPECT_EQ(ERR_FAILED
, deflate_stream_
->WriteFrames(&frames
, callback
));
1016 predictor_
->Clear();
1019 TEST_F(WebSocketDeflateStreamTest
, WriteFrameImmediately
) {
1020 ScopedVector
<WebSocketFrame
> frames
;
1021 CompletionCallback callback
;
1022 WriteFramesStub
stub(predictor_
, OK
);
1023 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1024 predictor_
->AddFramesToBeInput(frames
);
1027 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1028 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1030 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1031 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1032 ASSERT_EQ(1u, frames_passed
.size());
1033 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1034 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1035 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1036 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1037 ToString(frames_passed
[0]));
1040 TEST_F(WebSocketDeflateStreamTest
, WriteFrameAsync
) {
1041 WriteFramesStub
stub(predictor_
, ERR_IO_PENDING
);
1042 MockCallback mock_callback
, checkpoint
;
1043 CompletionCallback callback
=
1044 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
1045 ScopedVector
<WebSocketFrame
> frames
;
1048 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1049 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1050 EXPECT_CALL(checkpoint
, Call(0));
1051 EXPECT_CALL(mock_callback
, Call(OK
));
1053 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1054 predictor_
->AddFramesToBeInput(frames
);
1055 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->WriteFrames(&frames
, callback
));
1058 stub
.callback().Run(OK
);
1060 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1061 ASSERT_EQ(1u, frames_passed
.size());
1062 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1063 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1064 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1065 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1066 ToString(frames_passed
[0]));
1069 TEST_F(WebSocketDeflateStreamTest
, WriteControlFrameBetweenDataFrames
) {
1070 ScopedVector
<WebSocketFrame
> frames
;
1071 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "Hel");
1072 AppendTo(&frames
, WebSocketFrameHeader::kOpCodePing
, kFinal
);
1073 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "lo");
1074 predictor_
->AddFramesToBeInput(frames
);
1075 WriteFramesStub
stub(predictor_
, OK
);
1076 CompletionCallback callback
;
1080 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1081 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1083 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1084 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1085 ASSERT_EQ(2u, frames_passed
.size());
1086 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing
, frames_passed
[0]->header
.opcode
);
1087 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1088 EXPECT_FALSE(frames_passed
[0]->header
.reserved1
);
1089 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[1]->header
.opcode
);
1090 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1091 EXPECT_TRUE(frames_passed
[1]->header
.reserved1
);
1092 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1093 ToString(frames_passed
[1]));
1096 TEST_F(WebSocketDeflateStreamTest
, WriteEmptyMessage
) {
1097 ScopedVector
<WebSocketFrame
> frames
;
1098 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
);
1099 predictor_
->AddFramesToBeInput(frames
);
1100 WriteFramesStub
stub(predictor_
, OK
);
1101 CompletionCallback callback
;
1105 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1106 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1108 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1109 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1110 ASSERT_EQ(1u, frames_passed
.size());
1111 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1112 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1113 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1114 EXPECT_EQ(std::string("\x00", 1), ToString(frames_passed
[0]));
1117 TEST_F(WebSocketDeflateStreamTest
, WriteUncompressedMessage
) {
1118 ScopedVector
<WebSocketFrame
> frames
;
1119 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "AAAA");
1120 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "AAA");
1121 predictor_
->AddFramesToBeInput(frames
);
1122 WriteFramesStub
stub(predictor_
, OK
);
1123 CompletionCallback callback
;
1125 predictor_
->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE
);
1129 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1130 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1132 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1133 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1134 ASSERT_EQ(2u, frames_passed
.size());
1135 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1136 EXPECT_FALSE(frames_passed
[0]->header
.final
);
1137 EXPECT_FALSE(frames_passed
[0]->header
.reserved1
);
1138 EXPECT_EQ("AAAA", ToString(frames_passed
[0]));
1139 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
1140 frames_passed
[1]->header
.opcode
);
1141 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1142 EXPECT_FALSE(frames_passed
[1]->header
.reserved1
);
1143 EXPECT_EQ("AAA", ToString(frames_passed
[1]));
1146 TEST_F(WebSocketDeflateStreamTest
, LargeDeflatedFramesShouldBeSplit
) {
1147 WebSocketDeflater
deflater(WebSocketDeflater::TAKE_OVER_CONTEXT
);
1148 LinearCongruentialGenerator
lcg(133);
1149 WriteFramesStub
stub(predictor_
, OK
);
1150 CompletionCallback callback
;
1151 const size_t size
= 1024;
1155 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1156 .WillRepeatedly(Invoke(&stub
, &WriteFramesStub::Call
));
1158 ScopedVector
<WebSocketFrame
> total_compressed_frames
;
1160 deflater
.Initialize(kWindowBits
);
1162 bool is_final
= (total_compressed_frames
.size() >= 2);
1163 ScopedVector
<WebSocketFrame
> frames
;
1165 for (size_t i
= 0; i
< size
; ++i
)
1166 data
+= static_cast<char>(lcg
.Generate());
1167 deflater
.AddBytes(data
.data(), data
.size());
1168 FrameFlag flag
= is_final
? kFinal
: kNoFlag
;
1169 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeBinary
, flag
, data
);
1170 predictor_
->AddFramesToBeInput(frames
);
1171 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1172 total_compressed_frames
.insert(total_compressed_frames
.end(),
1173 stub
.frames()->begin(),
1174 stub
.frames()->end());
1175 stub
.frames()->weak_clear();
1180 std::string total_deflated
;
1181 for (size_t i
= 0; i
< total_compressed_frames
.size(); ++i
) {
1182 WebSocketFrame
* frame
= total_compressed_frames
[i
];
1183 const WebSocketFrameHeader
& header
= frame
->header
;
1185 EXPECT_EQ(header
.kOpCodeContinuation
, header
.opcode
);
1186 EXPECT_FALSE(header
.reserved1
);
1188 EXPECT_EQ(header
.kOpCodeBinary
, header
.opcode
);
1189 EXPECT_TRUE(header
.reserved1
);
1191 const bool is_final_frame
= (i
+ 1 == total_compressed_frames
.size());
1192 EXPECT_EQ(is_final_frame
, header
.final
);
1193 if (!is_final_frame
)
1194 EXPECT_GT(header
.payload_length
, 0ul);
1195 total_deflated
+= ToString(frame
);
1197 EXPECT_EQ(total_deflated
,
1198 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
1201 TEST_F(WebSocketDeflateStreamTest
, WriteMultipleMessages
) {
1202 ScopedVector
<WebSocketFrame
> frames
;
1203 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1204 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1205 predictor_
->AddFramesToBeInput(frames
);
1206 WriteFramesStub
stub(predictor_
, OK
);
1207 CompletionCallback callback
;
1211 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1212 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1214 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1215 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1216 ASSERT_EQ(2u, frames_passed
.size());
1217 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1218 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1219 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1220 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1221 ToString(frames_passed
[0]));
1222 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[1]->header
.opcode
);
1223 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1224 EXPECT_TRUE(frames_passed
[1]->header
.reserved1
);
1225 EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed
[1]));
1228 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest
,
1229 WriteMultipleMessages
) {
1230 ScopedVector
<WebSocketFrame
> frames
;
1231 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1232 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1233 predictor_
->AddFramesToBeInput(frames
);
1234 WriteFramesStub
stub(predictor_
, OK
);
1235 CompletionCallback callback
;
1239 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1240 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1242 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1243 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1244 ASSERT_EQ(2u, frames_passed
.size());
1245 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1246 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1247 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1248 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1249 ToString(frames_passed
[0]));
1250 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[1]->header
.opcode
);
1251 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1252 EXPECT_TRUE(frames_passed
[1]->header
.reserved1
);
1253 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1254 ToString(frames_passed
[1]));
1257 // In order to check the stream works correctly for multiple
1258 // "PossiblyCompressedMessage"s, we test various messages at one test case.
1259 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest
,
1260 WritePossiblyCompressMessages
) {
1261 ScopedVector
<WebSocketFrame
> frames
;
1262 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "He");
1263 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "llo");
1264 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "AAAAAAAAAA");
1265 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "AA");
1266 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "XX");
1267 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "YY");
1268 predictor_
->AddFramesToBeInput(frames
);
1269 WriteFramesStub
stub(predictor_
, OK
);
1270 CompletionCallback callback
;
1271 predictor_
->set_result(WebSocketDeflatePredictor::TRY_DEFLATE
);
1275 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1276 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1278 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1279 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1280 ASSERT_EQ(5u, frames_passed
.size());
1282 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1283 EXPECT_FALSE(frames_passed
[0]->header
.final
);
1284 EXPECT_FALSE(frames_passed
[0]->header
.reserved1
);
1285 EXPECT_EQ("He", ToString(frames_passed
[0]));
1286 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
1287 frames_passed
[1]->header
.opcode
);
1288 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1289 EXPECT_FALSE(frames_passed
[1]->header
.reserved1
);
1290 EXPECT_EQ("llo", ToString(frames_passed
[1]));
1292 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[2]->header
.opcode
);
1293 EXPECT_TRUE(frames_passed
[2]->header
.final
);
1294 EXPECT_TRUE(frames_passed
[2]->header
.reserved1
);
1295 EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6),
1296 ToString(frames_passed
[2]));
1298 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[3]->header
.opcode
);
1299 EXPECT_FALSE(frames_passed
[3]->header
.final
);
1300 EXPECT_FALSE(frames_passed
[3]->header
.reserved1
);
1301 EXPECT_EQ("XX", ToString(frames_passed
[3]));
1302 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
1303 frames_passed
[4]->header
.opcode
);
1304 EXPECT_TRUE(frames_passed
[4]->header
.final
);
1305 EXPECT_FALSE(frames_passed
[4]->header
.reserved1
);
1306 EXPECT_EQ("YY", ToString(frames_passed
[4]));
1309 // This is based on the similar test from websocket_deflater_test.cc
1310 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest
, WindowBits8
) {
1311 SetUpWithWindowBits(8);
1312 CompletionCallback callback
;
1313 AddCompressibleFrameString();
1314 WriteFramesStub
stub(predictor_
, OK
);
1317 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1318 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1320 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames_
, callback
));
1321 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1322 ASSERT_EQ(1u, frames_passed
.size());
1323 EXPECT_EQ(std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x39\xa3"
1324 "(?7\xb3\x34\x17\x00", 21),
1325 ToString(frames_passed
[0]));
1328 // The same input with window_bits=10 returns smaller output.
1329 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest
, WindowBits10
) {
1330 SetUpWithWindowBits(10);
1331 CompletionCallback callback
;
1332 AddCompressibleFrameString();
1333 WriteFramesStub
stub(predictor_
, OK
);
1336 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1337 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1339 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames_
, callback
));
1340 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1341 ASSERT_EQ(1u, frames_passed
.size());
1343 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17),
1344 ToString(frames_passed
[0]));