Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / websockets / websocket_deflate_stream_test.cc
blob4d5d9f2674800c21eeafbc533e90aaf4e83fabb9
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/websockets/websocket_deflate_stream.h"
7 #include <stdint.h>
8 #include <deque>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "net/base/completion_callback.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h"
19 #include "net/websockets/websocket_deflate_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"
29 namespace net {
30 namespace {
32 typedef ::testing::MockFunction<void(int)> MockCallback; // NOLINT
33 using ::testing::_;
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());
52 return buffer;
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)
73 : "";
76 void AppendTo(ScopedVector<WebSocketFrame>* frames,
77 WebSocketFrameHeader::OpCode opcode,
78 FrameFlag flag,
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,
90 FrameFlag flag) {
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 {
98 public:
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
110 // call.
111 // - RecordWrittenDataFrame is called before writing the frame.
112 class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor {
113 public:
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.";
119 return;
121 if (!frames_written_.empty()) {
122 ADD_FAILURE() << "There are extra written frames.";
123 return;
127 // WebSocketDeflatePredictor functions.
128 Result Predict(const ScopedVector<WebSocketFrame>& frames,
129 size_t frame_index) override {
130 return result_;
132 void RecordInputDataFrame(const WebSocketFrame* frame) override {
133 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
134 ADD_FAILURE() << "Control frames should not be recorded.";
135 return;
137 if (frame->header.reserved1) {
138 ADD_FAILURE() << "Input frame may not be compressed.";
139 return;
141 if (frames_to_be_input_.empty()) {
142 ADD_FAILURE() << "Unexpected input data frame";
143 return;
145 if (frame != frames_to_be_input_.front()) {
146 ADD_FAILURE() << "Input data frame does not match the expectation.";
147 return;
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.";
154 return;
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))
165 return;
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))
171 return;
172 if (frames_written_.empty()) {
173 ADD_FAILURE() << "There are missing frames to be written.";
174 return;
176 if (frame != frames_written_.front()) {
177 ADD_FAILURE() << "Written data frame does not match the expectation.";
178 return;
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.
192 void Clear() {
193 frames_to_be_input_.clear();
194 frames_written_.clear();
197 private:
198 Result result_;
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 {
212 public:
213 WebSocketDeflateStreamTest()
214 : mock_stream_(NULL),
215 predictor_(NULL) {}
216 ~WebSocketDeflateStreamTest() override {}
218 void SetUp() override {
219 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, kWindowBits);
222 protected:
223 // Initialize deflate_stream_ with the given parameters.
224 void Initialize(WebSocketDeflater::ContextTakeOverMode mode,
225 int window_bits) {
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
247 // here.
248 class WebSocketDeflateStreamWithDoNotTakeOverContextTest
249 : public WebSocketDeflateStreamTest {
250 public:
251 WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
252 ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() override {}
254 void SetUp() override {
255 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT, kWindowBits);
259 class WebSocketDeflateStreamWithClientWindowBitsTest
260 : public WebSocketDeflateStreamTest {
261 public:
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_);
282 protected:
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 {
290 public:
291 explicit ReadFramesStub(int result) : result_(result) {}
293 ReadFramesStub(int result, ScopedVector<WebSocketFrame>* frames_to_output)
294 : result_(result) {
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_);
304 return result_;
307 int result() const { return result_; }
308 const CompletionCallback callback() const { return callback_; }
309 ScopedVector<WebSocketFrame>* frames_passed() {
310 return frames_passed_;
313 private:
314 int result_;
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 {
324 public:
325 explicit WriteFramesStub(WebSocketDeflatePredictorMock* predictor,
326 int result)
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_);
335 return result_;
338 int result() const { return result_; }
339 const CompletionCallback callback() const { return callback_; }
340 ScopedVector<WebSocketFrame>* frames() { return &frames_; }
342 private:
343 int result_;
344 CompletionCallback callback_;
345 ScopedVector<WebSocketFrame> frames_;
346 WebSocketDeflatePredictorMock* predictor_;
349 TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) {
350 ScopedVector<WebSocketFrame> frames;
351 CompletionCallback callback;
353 InSequence s;
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,
364 kFinal,
365 "hello");
366 ReadFramesStub stub(OK, &frames_to_output);
367 ScopedVector<WebSocketFrame> frames;
370 InSequence s;
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));
391 InSequence s;
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());
400 checkpoint.Call(0);
402 AppendTo(stub.frames_passed(),
403 WebSocketFrameHeader::kOpCodeText,
404 kFinal,
405 "hello");
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));
422 InSequence s;
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());
431 checkpoint.Call(0);
433 AppendTo(stub.frames_passed(),
434 WebSocketFrameHeader::kOpCodeText,
435 kFinal,
436 "hello");
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,
445 kFinal | kReserved1,
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;
451 InSequence s;
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;
470 InSequence s;
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));
478 checkpoint.Call(0);
480 AppendTo(stub.frames_passed(),
481 WebSocketFrameHeader::kOpCodeText,
482 kFinal | kReserved1,
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,
500 kReserved1,
501 data1);
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;
509 InSequence s;
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,
521 kFinal,
522 data2);
524 checkpoint.Call(0);
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,
539 kFinal | kReserved1,
540 data);
541 ReadFramesStub stub(OK, &frames_to_output);
542 CompletionCallback callback;
543 ScopedVector<WebSocketFrame> frames;
546 InSequence s;
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,
561 kReserved1,
562 data1);
563 AppendTo(&frames_to_output,
564 WebSocketFrameHeader::kOpCodeContinuation,
565 kFinal,
566 data2);
567 ReadFramesStub stub(OK, &frames_to_output);
568 CompletionCallback callback;
569 ScopedVector<WebSocketFrame> frames;
572 InSequence s;
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,
588 kNoFlag);
589 AppendTo(&frames_to_output,
590 WebSocketFrameHeader::kOpCodeContinuation,
591 kFinal);
592 ReadFramesStub stub(OK, &frames_to_output);
593 CompletionCallback callback;
594 ScopedVector<WebSocketFrame> frames;
597 InSequence s;
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,
618 kReserved1,
619 std::string("\x02\x00", 1));
620 AppendTo(&frames_to_output,
621 WebSocketFrameHeader::kOpCodeContinuation,
622 kFinal);
623 ReadFramesStub stub(OK, &frames_to_output);
624 CompletionCallback callback;
625 ScopedVector<WebSocketFrame> frames;
628 InSequence s;
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,
646 kReserved1,
647 data);
648 AppendTo(&frames_to_output,
649 WebSocketFrameHeader::kOpCodeContinuation,
650 kFinal);
651 ReadFramesStub stub(OK, &frames_to_output);
652 CompletionCallback callback;
653 ScopedVector<WebSocketFrame> frames;
656 InSequence s;
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,
674 kReserved1,
675 data1);
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;
683 InSequence s;
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());
704 deflater.Finish();
706 ScopedVector<WebSocketFrame> frames_to_output;
707 AppendTo(&frames_to_output,
708 WebSocketFrameHeader::kOpCodeBinary,
709 kFinal | kReserved1,
710 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
712 ReadFramesStub stub(OK, &frames_to_output);
713 CompletionCallback callback;
714 ScopedVector<WebSocketFrame> frames;
716 InSequence s;
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());
746 deflater.Finish();
748 ScopedVector<WebSocketFrame> frames_to_output;
749 AppendTo(&frames_to_output,
750 WebSocketFrameHeader::kOpCodeBinary,
751 kReserved1,
752 ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
753 AppendTo(&frames_to_output,
754 WebSocketFrameHeader::kOpCodeBinary,
755 kFinal,
756 "");
758 ReadFramesStub stub(OK, &frames_to_output);
759 CompletionCallback callback;
760 ScopedVector<WebSocketFrame> frames;
762 InSequence s;
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,
789 kReserved1,
790 data1);
791 AppendTo(&frames_to_output,
792 WebSocketFrameHeader::kOpCodeContinuation,
793 kFinal | kReserved1,
794 data2);
795 ReadFramesStub stub(OK, &frames_to_output);
796 CompletionCallback callback;
797 ScopedVector<WebSocketFrame> frames;
800 InSequence s;
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,
813 kNoFlag,
814 "hello");
815 AppendTo(&frames_to_output,
816 WebSocketFrameHeader::kOpCodeContinuation,
817 kFinal | kReserved1,
818 "world");
819 ReadFramesStub stub(OK, &frames_to_output);
820 CompletionCallback callback;
821 ScopedVector<WebSocketFrame> frames;
824 InSequence s;
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,
836 kFinal | kReserved1,
837 std::string(
838 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
839 AppendTo(&frames_to_output,
840 WebSocketFrameHeader::kOpCodeText,
841 kFinal | kReserved1,
842 std::string("\x4a\x86\x33\x8d\x00\x00", 6));
843 ReadFramesStub stub(OK, &frames_to_output);
844 CompletionCallback callback;
845 ScopedVector<WebSocketFrame> frames;
848 InSequence s;
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,
868 kFinal,
869 "uncompressed1");
870 AppendTo(&frames_to_output,
871 WebSocketFrameHeader::kOpCodeText,
872 kFinal,
873 "uncompressed2");
874 ReadFramesStub stub(OK, &frames_to_output);
875 CompletionCallback callback;
876 ScopedVector<WebSocketFrame> frames;
879 InSequence s;
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,
900 kFinal | kReserved1,
901 std::string(
902 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
903 AppendTo(&frames_to_output,
904 WebSocketFrameHeader::kOpCodeText,
905 kFinal,
906 "uncompressed");
907 ReadFramesStub stub(OK, &frames_to_output);
908 CompletionCallback callback;
909 ScopedVector<WebSocketFrame> frames;
912 InSequence s;
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,
933 kFinal,
934 "uncompressed");
935 AppendTo(&frames_to_output,
936 WebSocketFrameHeader::kOpCodeText,
937 kFinal | kReserved1,
938 std::string(
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;
945 InSequence s;
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;
972 InSequence s;
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,
985 kReserved1,
986 std::string());
987 stub_vector[0]->callback().Run(OK);
988 AppendTo(stub_vector[1]->frames_passed(),
989 WebSocketFrameHeader::kOpCodeContinuation,
990 kFinal,
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;
1002 InSequence s;
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;
1012 InSequence s;
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);
1030 InSequence s;
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;
1051 InSequence s;
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));
1061 checkpoint.Call(0);
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;
1083 InSequence s;
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;
1108 InSequence s;
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);
1132 InSequence s;
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;
1158 InSequence s;
1159 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1160 .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call));
1162 ScopedVector<WebSocketFrame> total_compressed_frames;
1164 deflater.Initialize(kWindowBits);
1165 while (true) {
1166 bool is_final = (total_compressed_frames.size() >= 2);
1167 ScopedVector<WebSocketFrame> frames;
1168 std::string data;
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();
1180 if (is_final)
1181 break;
1183 deflater.Finish();
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;
1188 if (i > 0) {
1189 EXPECT_EQ(header.kOpCodeContinuation, header.opcode);
1190 EXPECT_FALSE(header.reserved1);
1191 } else {
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;
1214 InSequence s;
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;
1242 InSequence s;
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);
1278 InSequence s;
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);
1320 InSequence s;
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);
1339 InSequence s;
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());
1346 EXPECT_EQ(
1347 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17),
1348 ToString(frames_passed[0]));
1351 } // namespace
1353 } // namespace net