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_parameters.h"
20 #include "net/websockets/websocket_deflate_predictor.h"
21 #include "net/websockets/websocket_deflater.h"
22 #include "net/websockets/websocket_frame.h"
23 #include "net/websockets/websocket_inflater.h"
24 #include "net/websockets/websocket_stream.h"
25 #include "net/websockets/websocket_test_util.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
32 typedef ::testing::MockFunction
<void(int)> MockCallback
; // NOLINT
34 using ::testing::InSequence
;
35 using ::testing::Invoke
;
36 using ::testing::Return
;
38 typedef uint32_t FrameFlag
;
39 const FrameFlag kNoFlag
= 0;
40 const FrameFlag kFinal
= 1;
41 const FrameFlag kReserved1
= 2;
42 // We don't define values for other flags because we don't need them.
44 // The value must equal to the value of the corresponding
45 // constant in websocket_deflate_stream.cc
46 const size_t kChunkSize
= 4 * 1024;
47 const int kWindowBits
= 15;
49 scoped_refptr
<IOBuffer
> ToIOBuffer(const std::string
& s
) {
50 scoped_refptr
<IOBuffer
> buffer
= new IOBuffer(s
.size());
51 memcpy(buffer
->data(), s
.data(), s
.size());
55 std::string
ToString(IOBufferWithSize
* buffer
) {
56 return std::string(buffer
->data(), buffer
->size());
59 std::string
ToString(const scoped_refptr
<IOBufferWithSize
>& buffer
) {
60 return ToString(buffer
.get());
63 std::string
ToString(IOBuffer
* buffer
, size_t size
) {
64 return std::string(buffer
->data(), size
);
67 std::string
ToString(const scoped_refptr
<IOBuffer
>& buffer
, size_t size
) {
68 return ToString(buffer
.get(), size
);
71 std::string
ToString(const WebSocketFrame
* frame
) {
72 return frame
->data
.get() ? ToString(frame
->data
, frame
->header
.payload_length
)
76 void AppendTo(ScopedVector
<WebSocketFrame
>* frames
,
77 WebSocketFrameHeader::OpCode opcode
,
79 const std::string
& data
) {
80 scoped_ptr
<WebSocketFrame
> frame(new WebSocketFrame(opcode
));
81 frame
->header
.final
= (flag
& kFinal
);
82 frame
->header
.reserved1
= (flag
& kReserved1
);
83 frame
->data
= ToIOBuffer(data
);
84 frame
->header
.payload_length
= data
.size();
85 frames
->push_back(frame
.release());
88 void AppendTo(ScopedVector
<WebSocketFrame
>* frames
,
89 WebSocketFrameHeader::OpCode opcode
,
91 scoped_ptr
<WebSocketFrame
> frame(new WebSocketFrame(opcode
));
92 frame
->header
.final
= (flag
& kFinal
);
93 frame
->header
.reserved1
= (flag
& kReserved1
);
94 frames
->push_back(frame
.release());
97 class MockWebSocketStream
: public WebSocketStream
{
99 MOCK_METHOD2(ReadFrames
, int(ScopedVector
<WebSocketFrame
>*,
100 const CompletionCallback
&));
101 MOCK_METHOD2(WriteFrames
, int(ScopedVector
<WebSocketFrame
>*,
102 const CompletionCallback
&));
103 MOCK_METHOD0(Close
, void());
104 MOCK_CONST_METHOD0(GetSubProtocol
, std::string());
105 MOCK_CONST_METHOD0(GetExtensions
, std::string());
108 // This mock class relies on some assumptions.
109 // - RecordInputDataFrame is called after the corresponding WriteFrames
111 // - RecordWrittenDataFrame is called before writing the frame.
112 class WebSocketDeflatePredictorMock
: public WebSocketDeflatePredictor
{
114 WebSocketDeflatePredictorMock() : result_(DEFLATE
) {}
115 ~WebSocketDeflatePredictorMock() override
{
116 // Verify whether all expectaions are consumed.
117 if (!frames_to_be_input_
.empty()) {
118 ADD_FAILURE() << "There are missing frames to be input.";
121 if (!frames_written_
.empty()) {
122 ADD_FAILURE() << "There are extra written frames.";
127 // WebSocketDeflatePredictor functions.
128 Result
Predict(const ScopedVector
<WebSocketFrame
>& frames
,
129 size_t frame_index
) override
{
132 void RecordInputDataFrame(const WebSocketFrame
* frame
) override
{
133 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
)) {
134 ADD_FAILURE() << "Control frames should not be recorded.";
137 if (frame
->header
.reserved1
) {
138 ADD_FAILURE() << "Input frame may not be compressed.";
141 if (frames_to_be_input_
.empty()) {
142 ADD_FAILURE() << "Unexpected input data frame";
145 if (frame
!= frames_to_be_input_
.front()) {
146 ADD_FAILURE() << "Input data frame does not match the expectation.";
149 frames_to_be_input_
.pop_front();
151 void RecordWrittenDataFrame(const WebSocketFrame
* frame
) override
{
152 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
)) {
153 ADD_FAILURE() << "Control frames should not be recorded.";
156 frames_written_
.push_back(frame
);
159 // Sets |result_| for the |Predict| return value.
160 void set_result(Result result
) { result_
= result
; }
162 // Adds |frame| as an expectation of future |RecordInputDataFrame| call.
163 void AddFrameToBeInput(const WebSocketFrame
* frame
) {
164 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
))
166 frames_to_be_input_
.push_back(frame
);
168 // Verifies that |frame| is recorded in order.
169 void VerifySentFrame(const WebSocketFrame
* frame
) {
170 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame
->header
.opcode
))
172 if (frames_written_
.empty()) {
173 ADD_FAILURE() << "There are missing frames to be written.";
176 if (frame
!= frames_written_
.front()) {
177 ADD_FAILURE() << "Written data frame does not match the expectation.";
180 frames_written_
.pop_front();
182 void AddFramesToBeInput(const ScopedVector
<WebSocketFrame
>& frames
) {
183 for (size_t i
= 0; i
< frames
.size(); ++i
)
184 AddFrameToBeInput(frames
[i
]);
186 void VerifySentFrames(const ScopedVector
<WebSocketFrame
>& frames
) {
187 for (size_t i
= 0; i
< frames
.size(); ++i
)
188 VerifySentFrame(frames
[i
]);
190 // Call this method in order to disable checks in the destructor when
191 // WriteFrames fails.
193 frames_to_be_input_
.clear();
194 frames_written_
.clear();
199 // Data frames which will be recorded by |RecordInputFrames|.
200 // Pushed by |AddFrameToBeInput| and popped and verified by
201 // |RecordInputFrames|.
202 std::deque
<const WebSocketFrame
*> frames_to_be_input_
;
203 // Data frames recorded by |RecordWrittenFrames|.
204 // Pushed by |RecordWrittenFrames| and popped and verified by
205 // |VerifySentFrame|.
206 std::deque
<const WebSocketFrame
*> frames_written_
;
208 DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock
);
211 class WebSocketDeflateStreamTest
: public ::testing::Test
{
213 WebSocketDeflateStreamTest()
214 : mock_stream_(NULL
),
216 ~WebSocketDeflateStreamTest() override
{}
218 void SetUp() override
{
219 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT
, kWindowBits
);
223 // Initialize deflate_stream_ with the given parameters.
224 void Initialize(WebSocketDeflater::ContextTakeOverMode mode
,
226 WebSocketDeflateParameters parameters
;
227 if (mode
== WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT
) {
228 parameters
.SetClientNoContextTakeOver();
230 parameters
.SetClientMaxWindowBits(window_bits
);
231 mock_stream_
= new testing::StrictMock
<MockWebSocketStream
>;
232 predictor_
= new WebSocketDeflatePredictorMock
;
233 deflate_stream_
.reset(new WebSocketDeflateStream(
234 scoped_ptr
<WebSocketStream
>(mock_stream_
), parameters
,
235 scoped_ptr
<WebSocketDeflatePredictor
>(predictor_
)));
238 scoped_ptr
<WebSocketDeflateStream
> deflate_stream_
;
239 // Owned by |deflate_stream_|.
240 MockWebSocketStream
* mock_stream_
;
241 // Owned by |deflate_stream_|.
242 WebSocketDeflatePredictorMock
* predictor_
;
245 // Since WebSocketDeflater with DoNotTakeOverContext is well tested at
246 // websocket_deflater_test.cc, we have only a few tests for this configuration
248 class WebSocketDeflateStreamWithDoNotTakeOverContextTest
249 : public WebSocketDeflateStreamTest
{
251 WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
252 ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() override
{}
254 void SetUp() override
{
255 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT
, kWindowBits
);
259 class WebSocketDeflateStreamWithClientWindowBitsTest
260 : public WebSocketDeflateStreamTest
{
262 WebSocketDeflateStreamWithClientWindowBitsTest() {}
263 ~WebSocketDeflateStreamWithClientWindowBitsTest() override
{}
265 // Overridden to postpone the call to Initialize().
266 void SetUp() override
{}
268 // This needs to be called explicitly from the tests.
269 void SetUpWithWindowBits(int window_bits
) {
270 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT
, window_bits
);
273 // Add a frame which will be compressed to a smaller size if the window
274 // size is large enough.
275 void AddCompressibleFrameString() {
276 const std::string word
= "Chromium";
277 const std::string payload
= word
+ std::string(256, 'a') + word
;
278 AppendTo(&frames_
, WebSocketFrameHeader::kOpCodeText
, kFinal
, payload
);
279 predictor_
->AddFramesToBeInput(frames_
);
283 ScopedVector
<WebSocketFrame
> frames_
;
286 // ReadFrameStub is a stub for WebSocketStream::ReadFrames.
287 // It returns |result_| and |frames_to_output_| to the caller and
288 // saves parameters to |frames_passed_| and |callback_|.
289 class ReadFramesStub
{
291 explicit ReadFramesStub(int result
) : result_(result
) {}
293 ReadFramesStub(int result
, ScopedVector
<WebSocketFrame
>* frames_to_output
)
295 frames_to_output_
.swap(*frames_to_output
);
298 int Call(ScopedVector
<WebSocketFrame
>* frames
,
299 const CompletionCallback
& callback
) {
300 DCHECK(frames
->empty());
301 frames_passed_
= frames
;
302 callback_
= callback
;
303 frames
->swap(frames_to_output_
);
307 int result() const { return result_
; }
308 const CompletionCallback
callback() const { return callback_
; }
309 ScopedVector
<WebSocketFrame
>* frames_passed() {
310 return frames_passed_
;
315 CompletionCallback callback_
;
316 ScopedVector
<WebSocketFrame
> frames_to_output_
;
317 ScopedVector
<WebSocketFrame
>* frames_passed_
;
320 // WriteFramesStub is a stub for WebSocketStream::WriteFrames.
321 // It returns |result_| and |frames_| to the caller and
322 // saves |callback| parameter to |callback_|.
323 class WriteFramesStub
{
325 explicit WriteFramesStub(WebSocketDeflatePredictorMock
* predictor
,
327 : result_(result
), predictor_(predictor
) {}
329 int Call(ScopedVector
<WebSocketFrame
>* frames
,
330 const CompletionCallback
& callback
) {
331 frames_
.insert(frames_
.end(), frames
->begin(), frames
->end());
332 frames
->weak_clear();
333 callback_
= callback
;
334 predictor_
->VerifySentFrames(frames_
);
338 int result() const { return result_
; }
339 const CompletionCallback
callback() const { return callback_
; }
340 ScopedVector
<WebSocketFrame
>* frames() { return &frames_
; }
344 CompletionCallback callback_
;
345 ScopedVector
<WebSocketFrame
> frames_
;
346 WebSocketDeflatePredictorMock
* predictor_
;
349 TEST_F(WebSocketDeflateStreamTest
, ReadFailedImmediately
) {
350 ScopedVector
<WebSocketFrame
> frames
;
351 CompletionCallback callback
;
354 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
355 .WillOnce(Return(ERR_FAILED
));
357 EXPECT_EQ(ERR_FAILED
, deflate_stream_
->ReadFrames(&frames
, callback
));
360 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedFrameImmediately
) {
361 ScopedVector
<WebSocketFrame
> frames_to_output
;
362 AppendTo(&frames_to_output
,
363 WebSocketFrameHeader::kOpCodeText
,
366 ReadFramesStub
stub(OK
, &frames_to_output
);
367 ScopedVector
<WebSocketFrame
> frames
;
371 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
372 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
374 CompletionCallback callback
;
375 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
376 ASSERT_EQ(1u, frames
.size());
377 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
378 EXPECT_TRUE(frames
[0]->header
.final
);
379 EXPECT_FALSE(frames
[0]->header
.reserved1
);
380 EXPECT_EQ("hello", ToString(frames
[0]));
383 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedFrameAsync
) {
384 ReadFramesStub
stub(ERR_IO_PENDING
);
385 ScopedVector
<WebSocketFrame
> frames
;
386 MockCallback mock_callback
, checkpoint
;
387 CompletionCallback callback
=
388 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
392 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
393 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
394 EXPECT_CALL(checkpoint
, Call(0));
395 EXPECT_CALL(mock_callback
, Call(OK
));
397 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
398 ASSERT_EQ(0u, frames
.size());
402 AppendTo(stub
.frames_passed(),
403 WebSocketFrameHeader::kOpCodeText
,
406 stub
.callback().Run(OK
);
407 ASSERT_EQ(1u, frames
.size());
408 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
409 EXPECT_TRUE(frames
[0]->header
.final
);
410 EXPECT_FALSE(frames
[0]->header
.reserved1
);
411 EXPECT_EQ("hello", ToString(frames
[0]));
414 TEST_F(WebSocketDeflateStreamTest
, ReadFailedAsync
) {
415 ReadFramesStub
stub(ERR_IO_PENDING
);
416 ScopedVector
<WebSocketFrame
> frames
;
417 MockCallback mock_callback
, checkpoint
;
418 CompletionCallback callback
=
419 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
423 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
424 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
425 EXPECT_CALL(checkpoint
, Call(0));
426 EXPECT_CALL(mock_callback
, Call(ERR_FAILED
));
428 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
429 ASSERT_EQ(0u, frames
.size());
433 AppendTo(stub
.frames_passed(),
434 WebSocketFrameHeader::kOpCodeText
,
437 stub
.callback().Run(ERR_FAILED
);
438 ASSERT_EQ(0u, frames
.size());
441 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedFrameImmediately
) {
442 ScopedVector
<WebSocketFrame
> frames_to_output
;
443 AppendTo(&frames_to_output
,
444 WebSocketFrameHeader::kOpCodeText
,
446 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
447 ReadFramesStub
stub(OK
, &frames_to_output
);
448 CompletionCallback callback
;
449 ScopedVector
<WebSocketFrame
> frames
;
452 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
453 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
455 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
456 ASSERT_EQ(1u, frames
.size());
457 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
458 EXPECT_TRUE(frames
[0]->header
.final
);
459 EXPECT_FALSE(frames
[0]->header
.reserved1
);
460 EXPECT_EQ("Hello", ToString(frames
[0]));
463 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedFrameAsync
) {
464 ReadFramesStub
stub(ERR_IO_PENDING
);
465 MockCallback mock_callback
, checkpoint
;
466 CompletionCallback callback
=
467 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
468 ScopedVector
<WebSocketFrame
> frames
;
471 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
472 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
473 EXPECT_CALL(checkpoint
, Call(0));
474 EXPECT_CALL(mock_callback
, Call(OK
));
476 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
480 AppendTo(stub
.frames_passed(),
481 WebSocketFrameHeader::kOpCodeText
,
483 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
484 stub
.callback().Run(OK
);
486 ASSERT_EQ(1u, frames
.size());
487 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
488 EXPECT_TRUE(frames
[0]->header
.final
);
489 EXPECT_FALSE(frames
[0]->header
.reserved1
);
490 EXPECT_EQ("Hello", ToString(frames
[0]));
493 TEST_F(WebSocketDeflateStreamTest
,
494 ReadCompressedFrameFragmentImmediatelyButInflaterReturnsPending
) {
495 ScopedVector
<WebSocketFrame
> frames_to_output
;
496 const std::string
data1("\xf2", 1);
497 const std::string
data2("\x48\xcd\xc9\xc9\x07\x00", 6);
498 AppendTo(&frames_to_output
,
499 WebSocketFrameHeader::kOpCodeText
,
502 ReadFramesStub
stub1(OK
, &frames_to_output
), stub2(ERR_IO_PENDING
);
503 MockCallback mock_callback
, checkpoint
;
504 CompletionCallback callback
=
505 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
506 ScopedVector
<WebSocketFrame
> frames
;
510 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
511 .WillOnce(Invoke(&stub1
, &ReadFramesStub::Call
))
512 .WillOnce(Invoke(&stub2
, &ReadFramesStub::Call
));
513 EXPECT_CALL(checkpoint
, Call(0));
514 EXPECT_CALL(mock_callback
, Call(OK
));
516 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
517 ASSERT_EQ(0u, frames
.size());
519 AppendTo(stub2
.frames_passed(),
520 WebSocketFrameHeader::kOpCodeText
,
525 stub2
.callback().Run(OK
);
527 ASSERT_EQ(1u, frames
.size());
528 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
529 EXPECT_TRUE(frames
[0]->header
.final
);
530 EXPECT_FALSE(frames
[0]->header
.reserved1
);
531 EXPECT_EQ("Hello", ToString(frames
[0]));
534 TEST_F(WebSocketDeflateStreamTest
, ReadInvalidCompressedPayload
) {
535 const std::string
data("\xf2\x48\xcdINVALID", 10);
536 ScopedVector
<WebSocketFrame
> frames_to_output
;
537 AppendTo(&frames_to_output
,
538 WebSocketFrameHeader::kOpCodeText
,
541 ReadFramesStub
stub(OK
, &frames_to_output
);
542 CompletionCallback callback
;
543 ScopedVector
<WebSocketFrame
> frames
;
547 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
548 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
550 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR
,
551 deflate_stream_
->ReadFrames(&frames
, callback
));
552 ASSERT_EQ(0u, frames
.size());
555 TEST_F(WebSocketDeflateStreamTest
, MergeMultipleFramesInReadFrames
) {
556 const std::string
data1("\xf2\x48\xcd", 3);
557 const std::string
data2("\xc9\xc9\x07\x00", 4);
558 ScopedVector
<WebSocketFrame
> frames_to_output
;
559 AppendTo(&frames_to_output
,
560 WebSocketFrameHeader::kOpCodeText
,
563 AppendTo(&frames_to_output
,
564 WebSocketFrameHeader::kOpCodeContinuation
,
567 ReadFramesStub
stub(OK
, &frames_to_output
);
568 CompletionCallback callback
;
569 ScopedVector
<WebSocketFrame
> frames
;
573 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
574 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
576 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
577 ASSERT_EQ(1u, frames
.size());
578 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
579 EXPECT_TRUE(frames
[0]->header
.final
);
580 EXPECT_FALSE(frames
[0]->header
.reserved1
);
581 EXPECT_EQ("Hello", ToString(frames
[0]));
584 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedEmptyFrames
) {
585 ScopedVector
<WebSocketFrame
> frames_to_output
;
586 AppendTo(&frames_to_output
,
587 WebSocketFrameHeader::kOpCodeText
,
589 AppendTo(&frames_to_output
,
590 WebSocketFrameHeader::kOpCodeContinuation
,
592 ReadFramesStub
stub(OK
, &frames_to_output
);
593 CompletionCallback callback
;
594 ScopedVector
<WebSocketFrame
> frames
;
598 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
599 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
601 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
602 ASSERT_EQ(2u, frames
.size());
603 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
604 EXPECT_FALSE(frames
[0]->header
.final
);
605 EXPECT_FALSE(frames
[0]->header
.reserved1
);
606 EXPECT_EQ("", ToString(frames
[0]));
607 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
608 frames
[1]->header
.opcode
);
609 EXPECT_TRUE(frames
[1]->header
.final
);
610 EXPECT_FALSE(frames
[1]->header
.reserved1
);
611 EXPECT_EQ("", ToString(frames
[1]));
614 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedEmptyFrames
) {
615 ScopedVector
<WebSocketFrame
> frames_to_output
;
616 AppendTo(&frames_to_output
,
617 WebSocketFrameHeader::kOpCodeText
,
619 std::string("\x02\x00", 1));
620 AppendTo(&frames_to_output
,
621 WebSocketFrameHeader::kOpCodeContinuation
,
623 ReadFramesStub
stub(OK
, &frames_to_output
);
624 CompletionCallback callback
;
625 ScopedVector
<WebSocketFrame
> frames
;
629 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
630 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
632 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
633 ASSERT_EQ(1u, frames
.size());
634 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
635 EXPECT_TRUE(frames
[0]->header
.final
);
636 EXPECT_FALSE(frames
[0]->header
.reserved1
);
637 EXPECT_EQ("", ToString(frames
[0]));
640 TEST_F(WebSocketDeflateStreamTest
,
641 ReadCompressedFrameFollowedByEmptyFrame
) {
642 const std::string
data("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
643 ScopedVector
<WebSocketFrame
> frames_to_output
;
644 AppendTo(&frames_to_output
,
645 WebSocketFrameHeader::kOpCodeText
,
648 AppendTo(&frames_to_output
,
649 WebSocketFrameHeader::kOpCodeContinuation
,
651 ReadFramesStub
stub(OK
, &frames_to_output
);
652 CompletionCallback callback
;
653 ScopedVector
<WebSocketFrame
> frames
;
657 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
658 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
660 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
661 ASSERT_EQ(1u, frames
.size());
662 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
663 EXPECT_TRUE(frames
[0]->header
.final
);
664 EXPECT_FALSE(frames
[0]->header
.reserved1
);
665 EXPECT_EQ("Hello", ToString(frames
[0]));
668 TEST_F(WebSocketDeflateStreamTest
, ReadControlFrameBetweenDataFrames
) {
669 const std::string
data1("\xf2\x48\xcd", 3);
670 const std::string
data2("\xc9\xc9\x07\x00", 4);
671 ScopedVector
<WebSocketFrame
> frames_to_output
;
672 AppendTo(&frames_to_output
,
673 WebSocketFrameHeader::kOpCodeText
,
676 AppendTo(&frames_to_output
, WebSocketFrameHeader::kOpCodePing
, kFinal
);
677 AppendTo(&frames_to_output
, WebSocketFrameHeader::kOpCodeText
, kFinal
, data2
);
678 ReadFramesStub
stub(OK
, &frames_to_output
);
679 CompletionCallback callback
;
680 ScopedVector
<WebSocketFrame
> frames
;
684 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
685 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
687 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
688 ASSERT_EQ(2u, frames
.size());
689 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing
, frames
[0]->header
.opcode
);
690 EXPECT_TRUE(frames
[0]->header
.final
);
691 EXPECT_FALSE(frames
[0]->header
.reserved1
);
692 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
693 EXPECT_TRUE(frames
[1]->header
.final
);
694 EXPECT_FALSE(frames
[1]->header
.reserved1
);
695 EXPECT_EQ("Hello", ToString(frames
[1]));
698 TEST_F(WebSocketDeflateStreamTest
, SplitToMultipleFramesInReadFrames
) {
699 WebSocketDeflater
deflater(WebSocketDeflater::TAKE_OVER_CONTEXT
);
700 deflater
.Initialize(kWindowBits
);
701 const size_t kSize
= kChunkSize
* 3;
702 const std::string
original_data(kSize
, 'a');
703 deflater
.AddBytes(original_data
.data(), original_data
.size());
706 ScopedVector
<WebSocketFrame
> frames_to_output
;
707 AppendTo(&frames_to_output
,
708 WebSocketFrameHeader::kOpCodeBinary
,
710 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
712 ReadFramesStub
stub(OK
, &frames_to_output
);
713 CompletionCallback callback
;
714 ScopedVector
<WebSocketFrame
> frames
;
717 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
718 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
721 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
722 ASSERT_EQ(3u, frames
.size());
723 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary
, frames
[0]->header
.opcode
);
724 EXPECT_FALSE(frames
[0]->header
.final
);
725 EXPECT_FALSE(frames
[0]->header
.reserved1
);
726 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[0]->header
.payload_length
));
727 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
728 frames
[1]->header
.opcode
);
729 EXPECT_FALSE(frames
[1]->header
.final
);
730 EXPECT_FALSE(frames
[1]->header
.reserved1
);
731 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[1]->header
.payload_length
));
732 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
733 frames
[2]->header
.opcode
);
734 EXPECT_TRUE(frames
[2]->header
.final
);
735 EXPECT_FALSE(frames
[2]->header
.reserved1
);
736 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[2]->header
.payload_length
));
737 EXPECT_EQ(original_data
,
738 ToString(frames
[0]) + ToString(frames
[1]) + ToString(frames
[2]));
741 TEST_F(WebSocketDeflateStreamTest
, InflaterInternalDataCanBeEmpty
) {
742 WebSocketDeflater
deflater(WebSocketDeflater::TAKE_OVER_CONTEXT
);
743 deflater
.Initialize(kWindowBits
);
744 const std::string
original_data(kChunkSize
, 'a');
745 deflater
.AddBytes(original_data
.data(), original_data
.size());
748 ScopedVector
<WebSocketFrame
> frames_to_output
;
749 AppendTo(&frames_to_output
,
750 WebSocketFrameHeader::kOpCodeBinary
,
752 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
753 AppendTo(&frames_to_output
,
754 WebSocketFrameHeader::kOpCodeBinary
,
758 ReadFramesStub
stub(OK
, &frames_to_output
);
759 CompletionCallback callback
;
760 ScopedVector
<WebSocketFrame
> frames
;
763 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
764 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
767 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
768 ASSERT_EQ(2u, frames
.size());
769 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary
, frames
[0]->header
.opcode
);
770 EXPECT_FALSE(frames
[0]->header
.final
);
771 EXPECT_FALSE(frames
[0]->header
.reserved1
);
772 EXPECT_EQ(kChunkSize
, static_cast<size_t>(frames
[0]->header
.payload_length
));
774 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
775 frames
[1]->header
.opcode
);
776 EXPECT_TRUE(frames
[1]->header
.final
);
777 EXPECT_FALSE(frames
[1]->header
.reserved1
);
778 EXPECT_EQ(0u, static_cast<size_t>(frames
[1]->header
.payload_length
));
779 EXPECT_EQ(original_data
, ToString(frames
[0]) + ToString(frames
[1]));
782 TEST_F(WebSocketDeflateStreamTest
,
783 Reserved1TurnsOnDuringReadingCompressedContinuationFrame
) {
784 const std::string
data1("\xf2\x48\xcd", 3);
785 const std::string
data2("\xc9\xc9\x07\x00", 4);
786 ScopedVector
<WebSocketFrame
> frames_to_output
;
787 AppendTo(&frames_to_output
,
788 WebSocketFrameHeader::kOpCodeText
,
791 AppendTo(&frames_to_output
,
792 WebSocketFrameHeader::kOpCodeContinuation
,
795 ReadFramesStub
stub(OK
, &frames_to_output
);
796 CompletionCallback callback
;
797 ScopedVector
<WebSocketFrame
> frames
;
801 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
802 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
804 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR
,
805 deflate_stream_
->ReadFrames(&frames
, callback
));
808 TEST_F(WebSocketDeflateStreamTest
,
809 Reserved1TurnsOnDuringReadingUncompressedContinuationFrame
) {
810 ScopedVector
<WebSocketFrame
> frames_to_output
;
811 AppendTo(&frames_to_output
,
812 WebSocketFrameHeader::kOpCodeText
,
815 AppendTo(&frames_to_output
,
816 WebSocketFrameHeader::kOpCodeContinuation
,
819 ReadFramesStub
stub(OK
, &frames_to_output
);
820 CompletionCallback callback
;
821 ScopedVector
<WebSocketFrame
> frames
;
825 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
826 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
828 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR
,
829 deflate_stream_
->ReadFrames(&frames
, callback
));
832 TEST_F(WebSocketDeflateStreamTest
, ReadCompressedMessages
) {
833 ScopedVector
<WebSocketFrame
> frames_to_output
;
834 AppendTo(&frames_to_output
,
835 WebSocketFrameHeader::kOpCodeText
,
838 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
839 AppendTo(&frames_to_output
,
840 WebSocketFrameHeader::kOpCodeText
,
842 std::string("\x4a\x86\x33\x8d\x00\x00", 6));
843 ReadFramesStub
stub(OK
, &frames_to_output
);
844 CompletionCallback callback
;
845 ScopedVector
<WebSocketFrame
> frames
;
849 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
850 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
852 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
853 ASSERT_EQ(2u, frames
.size());
854 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
855 EXPECT_TRUE(frames
[0]->header
.final
);
856 EXPECT_FALSE(frames
[0]->header
.reserved1
);
857 EXPECT_EQ("compressed1", ToString(frames
[0]));
858 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
859 EXPECT_TRUE(frames
[1]->header
.final
);
860 EXPECT_FALSE(frames
[1]->header
.reserved1
);
861 EXPECT_EQ("compressed2", ToString(frames
[1]));
864 TEST_F(WebSocketDeflateStreamTest
, ReadUncompressedMessages
) {
865 ScopedVector
<WebSocketFrame
> frames_to_output
;
866 AppendTo(&frames_to_output
,
867 WebSocketFrameHeader::kOpCodeText
,
870 AppendTo(&frames_to_output
,
871 WebSocketFrameHeader::kOpCodeText
,
874 ReadFramesStub
stub(OK
, &frames_to_output
);
875 CompletionCallback callback
;
876 ScopedVector
<WebSocketFrame
> frames
;
880 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
881 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
883 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
884 ASSERT_EQ(2u, frames
.size());
885 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
886 EXPECT_TRUE(frames
[0]->header
.final
);
887 EXPECT_FALSE(frames
[0]->header
.reserved1
);
888 EXPECT_EQ("uncompressed1", ToString(frames
[0]));
889 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
890 EXPECT_TRUE(frames
[1]->header
.final
);
891 EXPECT_FALSE(frames
[1]->header
.reserved1
);
892 EXPECT_EQ("uncompressed2", ToString(frames
[1]));
895 TEST_F(WebSocketDeflateStreamTest
,
896 ReadCompressedMessageThenUncompressedMessage
) {
897 ScopedVector
<WebSocketFrame
> frames_to_output
;
898 AppendTo(&frames_to_output
,
899 WebSocketFrameHeader::kOpCodeText
,
902 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
903 AppendTo(&frames_to_output
,
904 WebSocketFrameHeader::kOpCodeText
,
907 ReadFramesStub
stub(OK
, &frames_to_output
);
908 CompletionCallback callback
;
909 ScopedVector
<WebSocketFrame
> frames
;
913 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
914 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
916 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
917 ASSERT_EQ(2u, frames
.size());
918 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
919 EXPECT_TRUE(frames
[0]->header
.final
);
920 EXPECT_FALSE(frames
[0]->header
.reserved1
);
921 EXPECT_EQ("compressed", ToString(frames
[0]));
922 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
923 EXPECT_TRUE(frames
[1]->header
.final
);
924 EXPECT_FALSE(frames
[1]->header
.reserved1
);
925 EXPECT_EQ("uncompressed", ToString(frames
[1]));
928 TEST_F(WebSocketDeflateStreamTest
,
929 ReadUncompressedMessageThenCompressedMessage
) {
930 ScopedVector
<WebSocketFrame
> frames_to_output
;
931 AppendTo(&frames_to_output
,
932 WebSocketFrameHeader::kOpCodeText
,
935 AppendTo(&frames_to_output
,
936 WebSocketFrameHeader::kOpCodeText
,
939 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
940 ReadFramesStub
stub(OK
, &frames_to_output
);
941 CompletionCallback callback
;
942 ScopedVector
<WebSocketFrame
> frames
;
946 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
947 .WillOnce(Invoke(&stub
, &ReadFramesStub::Call
));
949 ASSERT_EQ(OK
, deflate_stream_
->ReadFrames(&frames
, callback
));
950 ASSERT_EQ(2u, frames
.size());
951 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
952 EXPECT_TRUE(frames
[0]->header
.final
);
953 EXPECT_FALSE(frames
[0]->header
.reserved1
);
954 EXPECT_EQ("uncompressed", ToString(frames
[0]));
955 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[1]->header
.opcode
);
956 EXPECT_TRUE(frames
[1]->header
.final
);
957 EXPECT_FALSE(frames
[1]->header
.reserved1
);
958 EXPECT_EQ("compressed", ToString(frames
[1]));
961 // This is a regression test for crbug.com/343506.
962 TEST_F(WebSocketDeflateStreamTest
, ReadEmptyAsyncFrame
) {
963 ScopedVector
<ReadFramesStub
> stub_vector
;
964 stub_vector
.push_back(new ReadFramesStub(ERR_IO_PENDING
));
965 stub_vector
.push_back(new ReadFramesStub(ERR_IO_PENDING
));
966 MockCallback mock_callback
;
967 CompletionCallback callback
=
968 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
969 ScopedVector
<WebSocketFrame
> frames
;
973 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
974 .WillOnce(Invoke(stub_vector
[0], &ReadFramesStub::Call
));
976 EXPECT_CALL(*mock_stream_
, ReadFrames(&frames
, _
))
977 .WillOnce(Invoke(stub_vector
[1], &ReadFramesStub::Call
));
979 EXPECT_CALL(mock_callback
, Call(OK
));
982 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->ReadFrames(&frames
, callback
));
983 AppendTo(stub_vector
[0]->frames_passed(),
984 WebSocketFrameHeader::kOpCodeText
,
987 stub_vector
[0]->callback().Run(OK
);
988 AppendTo(stub_vector
[1]->frames_passed(),
989 WebSocketFrameHeader::kOpCodeContinuation
,
991 std::string("\x02\x00"));
992 stub_vector
[1]->callback().Run(OK
);
993 ASSERT_EQ(1u, frames
.size());
994 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames
[0]->header
.opcode
);
995 EXPECT_EQ("", ToString(frames
[0]));
998 TEST_F(WebSocketDeflateStreamTest
, WriteEmpty
) {
999 ScopedVector
<WebSocketFrame
> frames
;
1000 CompletionCallback callback
;
1003 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
)).Times(0);
1005 EXPECT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1008 TEST_F(WebSocketDeflateStreamTest
, WriteFailedImmediately
) {
1009 ScopedVector
<WebSocketFrame
> frames
;
1010 CompletionCallback callback
;
1013 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1014 .WillOnce(Return(ERR_FAILED
));
1017 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "hello");
1018 predictor_
->AddFramesToBeInput(frames
);
1019 EXPECT_EQ(ERR_FAILED
, deflate_stream_
->WriteFrames(&frames
, callback
));
1020 predictor_
->Clear();
1023 TEST_F(WebSocketDeflateStreamTest
, WriteFrameImmediately
) {
1024 ScopedVector
<WebSocketFrame
> frames
;
1025 CompletionCallback callback
;
1026 WriteFramesStub
stub(predictor_
, OK
);
1027 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1028 predictor_
->AddFramesToBeInput(frames
);
1031 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1032 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1034 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1035 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1036 ASSERT_EQ(1u, frames_passed
.size());
1037 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1038 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1039 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1040 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1041 ToString(frames_passed
[0]));
1044 TEST_F(WebSocketDeflateStreamTest
, WriteFrameAsync
) {
1045 WriteFramesStub
stub(predictor_
, ERR_IO_PENDING
);
1046 MockCallback mock_callback
, checkpoint
;
1047 CompletionCallback callback
=
1048 base::Bind(&MockCallback::Call
, base::Unretained(&mock_callback
));
1049 ScopedVector
<WebSocketFrame
> frames
;
1052 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1053 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1054 EXPECT_CALL(checkpoint
, Call(0));
1055 EXPECT_CALL(mock_callback
, Call(OK
));
1057 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1058 predictor_
->AddFramesToBeInput(frames
);
1059 ASSERT_EQ(ERR_IO_PENDING
, deflate_stream_
->WriteFrames(&frames
, callback
));
1062 stub
.callback().Run(OK
);
1064 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1065 ASSERT_EQ(1u, frames_passed
.size());
1066 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1067 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1068 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1069 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1070 ToString(frames_passed
[0]));
1073 TEST_F(WebSocketDeflateStreamTest
, WriteControlFrameBetweenDataFrames
) {
1074 ScopedVector
<WebSocketFrame
> frames
;
1075 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "Hel");
1076 AppendTo(&frames
, WebSocketFrameHeader::kOpCodePing
, kFinal
);
1077 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "lo");
1078 predictor_
->AddFramesToBeInput(frames
);
1079 WriteFramesStub
stub(predictor_
, OK
);
1080 CompletionCallback callback
;
1084 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1085 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1087 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1088 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1089 ASSERT_EQ(2u, frames_passed
.size());
1090 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing
, frames_passed
[0]->header
.opcode
);
1091 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1092 EXPECT_FALSE(frames_passed
[0]->header
.reserved1
);
1093 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[1]->header
.opcode
);
1094 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1095 EXPECT_TRUE(frames_passed
[1]->header
.reserved1
);
1096 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1097 ToString(frames_passed
[1]));
1100 TEST_F(WebSocketDeflateStreamTest
, WriteEmptyMessage
) {
1101 ScopedVector
<WebSocketFrame
> frames
;
1102 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
);
1103 predictor_
->AddFramesToBeInput(frames
);
1104 WriteFramesStub
stub(predictor_
, OK
);
1105 CompletionCallback callback
;
1109 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1110 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1112 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1113 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1114 ASSERT_EQ(1u, frames_passed
.size());
1115 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1116 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1117 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1118 EXPECT_EQ(std::string("\x00", 1), ToString(frames_passed
[0]));
1121 TEST_F(WebSocketDeflateStreamTest
, WriteUncompressedMessage
) {
1122 ScopedVector
<WebSocketFrame
> frames
;
1123 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "AAAA");
1124 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "AAA");
1125 predictor_
->AddFramesToBeInput(frames
);
1126 WriteFramesStub
stub(predictor_
, OK
);
1127 CompletionCallback callback
;
1129 predictor_
->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE
);
1133 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1134 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1136 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1137 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1138 ASSERT_EQ(2u, frames_passed
.size());
1139 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1140 EXPECT_FALSE(frames_passed
[0]->header
.final
);
1141 EXPECT_FALSE(frames_passed
[0]->header
.reserved1
);
1142 EXPECT_EQ("AAAA", ToString(frames_passed
[0]));
1143 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
1144 frames_passed
[1]->header
.opcode
);
1145 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1146 EXPECT_FALSE(frames_passed
[1]->header
.reserved1
);
1147 EXPECT_EQ("AAA", ToString(frames_passed
[1]));
1150 TEST_F(WebSocketDeflateStreamTest
, LargeDeflatedFramesShouldBeSplit
) {
1151 WebSocketDeflater
deflater(WebSocketDeflater::TAKE_OVER_CONTEXT
);
1152 LinearCongruentialGenerator
lcg(133);
1153 WriteFramesStub
stub(predictor_
, OK
);
1154 CompletionCallback callback
;
1155 const size_t size
= 1024;
1159 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1160 .WillRepeatedly(Invoke(&stub
, &WriteFramesStub::Call
));
1162 ScopedVector
<WebSocketFrame
> total_compressed_frames
;
1164 deflater
.Initialize(kWindowBits
);
1166 bool is_final
= (total_compressed_frames
.size() >= 2);
1167 ScopedVector
<WebSocketFrame
> frames
;
1169 for (size_t i
= 0; i
< size
; ++i
)
1170 data
+= static_cast<char>(lcg
.Generate());
1171 deflater
.AddBytes(data
.data(), data
.size());
1172 FrameFlag flag
= is_final
? kFinal
: kNoFlag
;
1173 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeBinary
, flag
, data
);
1174 predictor_
->AddFramesToBeInput(frames
);
1175 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1176 total_compressed_frames
.insert(total_compressed_frames
.end(),
1177 stub
.frames()->begin(),
1178 stub
.frames()->end());
1179 stub
.frames()->weak_clear();
1184 std::string total_deflated
;
1185 for (size_t i
= 0; i
< total_compressed_frames
.size(); ++i
) {
1186 WebSocketFrame
* frame
= total_compressed_frames
[i
];
1187 const WebSocketFrameHeader
& header
= frame
->header
;
1189 EXPECT_EQ(header
.kOpCodeContinuation
, header
.opcode
);
1190 EXPECT_FALSE(header
.reserved1
);
1192 EXPECT_EQ(header
.kOpCodeBinary
, header
.opcode
);
1193 EXPECT_TRUE(header
.reserved1
);
1195 const bool is_final_frame
= (i
+ 1 == total_compressed_frames
.size());
1196 EXPECT_EQ(is_final_frame
, header
.final
);
1197 if (!is_final_frame
)
1198 EXPECT_GT(header
.payload_length
, 0ul);
1199 total_deflated
+= ToString(frame
);
1201 EXPECT_EQ(total_deflated
,
1202 ToString(deflater
.GetOutput(deflater
.CurrentOutputSize())));
1205 TEST_F(WebSocketDeflateStreamTest
, WriteMultipleMessages
) {
1206 ScopedVector
<WebSocketFrame
> frames
;
1207 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1208 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1209 predictor_
->AddFramesToBeInput(frames
);
1210 WriteFramesStub
stub(predictor_
, OK
);
1211 CompletionCallback callback
;
1215 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1216 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1218 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1219 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1220 ASSERT_EQ(2u, frames_passed
.size());
1221 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1222 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1223 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1224 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1225 ToString(frames_passed
[0]));
1226 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[1]->header
.opcode
);
1227 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1228 EXPECT_TRUE(frames_passed
[1]->header
.reserved1
);
1229 EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed
[1]));
1232 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest
,
1233 WriteMultipleMessages
) {
1234 ScopedVector
<WebSocketFrame
> frames
;
1235 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1236 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kFinal
, "Hello");
1237 predictor_
->AddFramesToBeInput(frames
);
1238 WriteFramesStub
stub(predictor_
, OK
);
1239 CompletionCallback callback
;
1243 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1244 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1246 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1247 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1248 ASSERT_EQ(2u, frames_passed
.size());
1249 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1250 EXPECT_TRUE(frames_passed
[0]->header
.final
);
1251 EXPECT_TRUE(frames_passed
[0]->header
.reserved1
);
1252 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1253 ToString(frames_passed
[0]));
1254 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[1]->header
.opcode
);
1255 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1256 EXPECT_TRUE(frames_passed
[1]->header
.reserved1
);
1257 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1258 ToString(frames_passed
[1]));
1261 // In order to check the stream works correctly for multiple
1262 // "PossiblyCompressedMessage"s, we test various messages at one test case.
1263 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest
,
1264 WritePossiblyCompressMessages
) {
1265 ScopedVector
<WebSocketFrame
> frames
;
1266 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "He");
1267 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "llo");
1268 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "AAAAAAAAAA");
1269 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "AA");
1270 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeText
, kNoFlag
, "XX");
1271 AppendTo(&frames
, WebSocketFrameHeader::kOpCodeContinuation
, kFinal
, "YY");
1272 predictor_
->AddFramesToBeInput(frames
);
1273 WriteFramesStub
stub(predictor_
, OK
);
1274 CompletionCallback callback
;
1275 predictor_
->set_result(WebSocketDeflatePredictor::TRY_DEFLATE
);
1279 EXPECT_CALL(*mock_stream_
, WriteFrames(&frames
, _
))
1280 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1282 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames
, callback
));
1283 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1284 ASSERT_EQ(5u, frames_passed
.size());
1286 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[0]->header
.opcode
);
1287 EXPECT_FALSE(frames_passed
[0]->header
.final
);
1288 EXPECT_FALSE(frames_passed
[0]->header
.reserved1
);
1289 EXPECT_EQ("He", ToString(frames_passed
[0]));
1290 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
1291 frames_passed
[1]->header
.opcode
);
1292 EXPECT_TRUE(frames_passed
[1]->header
.final
);
1293 EXPECT_FALSE(frames_passed
[1]->header
.reserved1
);
1294 EXPECT_EQ("llo", ToString(frames_passed
[1]));
1296 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[2]->header
.opcode
);
1297 EXPECT_TRUE(frames_passed
[2]->header
.final
);
1298 EXPECT_TRUE(frames_passed
[2]->header
.reserved1
);
1299 EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6),
1300 ToString(frames_passed
[2]));
1302 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText
, frames_passed
[3]->header
.opcode
);
1303 EXPECT_FALSE(frames_passed
[3]->header
.final
);
1304 EXPECT_FALSE(frames_passed
[3]->header
.reserved1
);
1305 EXPECT_EQ("XX", ToString(frames_passed
[3]));
1306 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation
,
1307 frames_passed
[4]->header
.opcode
);
1308 EXPECT_TRUE(frames_passed
[4]->header
.final
);
1309 EXPECT_FALSE(frames_passed
[4]->header
.reserved1
);
1310 EXPECT_EQ("YY", ToString(frames_passed
[4]));
1313 // This is based on the similar test from websocket_deflater_test.cc
1314 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest
, WindowBits8
) {
1315 SetUpWithWindowBits(8);
1316 CompletionCallback callback
;
1317 AddCompressibleFrameString();
1318 WriteFramesStub
stub(predictor_
, OK
);
1321 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1322 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1324 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames_
, callback
));
1325 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1326 ASSERT_EQ(1u, frames_passed
.size());
1327 EXPECT_EQ(std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x39\xa3"
1328 "(?7\xb3\x34\x17\x00", 21),
1329 ToString(frames_passed
[0]));
1332 // The same input with window_bits=10 returns smaller output.
1333 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest
, WindowBits10
) {
1334 SetUpWithWindowBits(10);
1335 CompletionCallback callback
;
1336 AddCompressibleFrameString();
1337 WriteFramesStub
stub(predictor_
, OK
);
1340 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
1341 .WillOnce(Invoke(&stub
, &WriteFramesStub::Call
));
1343 ASSERT_EQ(OK
, deflate_stream_
->WriteFrames(&frames_
, callback
));
1344 const ScopedVector
<WebSocketFrame
>& frames_passed
= *stub
.frames();
1345 ASSERT_EQ(1u, frames_passed
.size());
1347 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17),
1348 ToString(frames_passed
[0]));