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.
4
5#include "net/websockets/websocket_deflate_stream.h"
6
7#include <stdint.h>
8#include <deque>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/bind.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/scoped_vector.h"
16#include "net/base/completion_callback.h"
17#include "net/base/io_buffer.h"
18#include "net/base/net_errors.h"
19#include "net/websockets/websocket_deflate_predictor.h"
20#include "net/websockets/websocket_deflater.h"
21#include "net/websockets/websocket_frame.h"
22#include "net/websockets/websocket_inflater.h"
23#include "net/websockets/websocket_stream.h"
24#include "net/websockets/websocket_test_util.h"
25#include "testing/gmock/include/gmock/gmock.h"
26#include "testing/gtest/include/gtest/gtest.h"
27
28namespace net {
29namespace {
30
31typedef ::testing::MockFunction<void(int)> MockCallback;  // NOLINT
32using ::testing::_;
33using ::testing::InSequence;
34using ::testing::Invoke;
35using ::testing::Return;
36
37typedef uint32_t FrameFlag;
38const FrameFlag kNoFlag = 0;
39const FrameFlag kFinal = 1;
40const FrameFlag kReserved1 = 2;
41// We don't define values for other flags because we don't need them.
42
43// The value must equal to the value of the corresponding
44// constant in websocket_deflate_stream.cc
45const size_t kChunkSize = 4 * 1024;
46const int kWindowBits = 15;
47
48scoped_refptr<IOBuffer> ToIOBuffer(const std::string& s) {
49  scoped_refptr<IOBuffer> buffer = new IOBuffer(s.size());
50  memcpy(buffer->data(), s.data(), s.size());
51  return buffer;
52}
53
54std::string ToString(IOBufferWithSize* buffer) {
55  return std::string(buffer->data(), buffer->size());
56}
57
58std::string ToString(const scoped_refptr<IOBufferWithSize>& buffer) {
59  return ToString(buffer.get());
60}
61
62std::string ToString(IOBuffer* buffer, size_t size) {
63  return std::string(buffer->data(), size);
64}
65
66std::string ToString(const scoped_refptr<IOBuffer>& buffer, size_t size) {
67  return ToString(buffer.get(), size);
68}
69
70std::string ToString(const WebSocketFrame* frame) {
71  return frame->data.get() ? ToString(frame->data, frame->header.payload_length)
72                           : "";
73}
74
75void AppendTo(ScopedVector<WebSocketFrame>* frames,
76              WebSocketFrameHeader::OpCode opcode,
77              FrameFlag flag,
78              const std::string& data) {
79  scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode));
80  frame->header.final = (flag & kFinal);
81  frame->header.reserved1 = (flag & kReserved1);
82  frame->data = ToIOBuffer(data);
83  frame->header.payload_length = data.size();
84  frames->push_back(frame.release());
85}
86
87void AppendTo(ScopedVector<WebSocketFrame>* frames,
88              WebSocketFrameHeader::OpCode opcode,
89              FrameFlag flag) {
90  scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode));
91  frame->header.final = (flag & kFinal);
92  frame->header.reserved1 = (flag & kReserved1);
93  frames->push_back(frame.release());
94}
95
96class MockWebSocketStream : public WebSocketStream {
97 public:
98  MOCK_METHOD2(ReadFrames, int(ScopedVector<WebSocketFrame>*,
99                               const CompletionCallback&));
100  MOCK_METHOD2(WriteFrames, int(ScopedVector<WebSocketFrame>*,
101                                const CompletionCallback&));
102  MOCK_METHOD0(Close, void());
103  MOCK_CONST_METHOD0(GetSubProtocol, std::string());
104  MOCK_CONST_METHOD0(GetExtensions, std::string());
105};
106
107// This mock class relies on some assumptions.
108//  - RecordInputDataFrame is called after the corresponding WriteFrames
109//    call.
110//  - RecordWrittenDataFrame is called before writing the frame.
111class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor {
112 public:
113  WebSocketDeflatePredictorMock() : result_(DEFLATE) {}
114  virtual ~WebSocketDeflatePredictorMock() {
115    // Verify whether all expectaions are consumed.
116    if (!frames_to_be_input_.empty()) {
117      ADD_FAILURE() << "There are missing frames to be input.";
118      return;
119    }
120    if (!frames_written_.empty()) {
121      ADD_FAILURE() << "There are extra written frames.";
122      return;
123    }
124  }
125
126  // WebSocketDeflatePredictor functions.
127  virtual Result Predict(const ScopedVector<WebSocketFrame>& frames,
128                         size_t frame_index) OVERRIDE {
129    return result_;
130  }
131  virtual void RecordInputDataFrame(const WebSocketFrame* frame) OVERRIDE {
132    if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
133      ADD_FAILURE() << "Control frames should not be recorded.";
134      return;
135    }
136    if (frame->header.reserved1) {
137      ADD_FAILURE() << "Input frame may not be compressed.";
138      return;
139    }
140    if (frames_to_be_input_.empty()) {
141      ADD_FAILURE() << "Unexpected input data frame";
142      return;
143    }
144    if (frame != frames_to_be_input_.front()) {
145      ADD_FAILURE() << "Input data frame does not match the expectation.";
146      return;
147    }
148    frames_to_be_input_.pop_front();
149  }
150  virtual void RecordWrittenDataFrame(const WebSocketFrame* frame) OVERRIDE {
151    if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
152      ADD_FAILURE() << "Control frames should not be recorded.";
153      return;
154    }
155    frames_written_.push_back(frame);
156  }
157
158  // Sets |result_| for the |Predict| return value.
159  void set_result(Result result) { result_ = result; }
160
161  // Adds |frame| as an expectation of future |RecordInputDataFrame| call.
162  void AddFrameToBeInput(const WebSocketFrame* frame) {
163    if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode))
164      return;
165    frames_to_be_input_.push_back(frame);
166  }
167  // Verifies that |frame| is recorded in order.
168  void VerifySentFrame(const WebSocketFrame* frame) {
169    if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode))
170      return;
171    if (frames_written_.empty()) {
172      ADD_FAILURE() << "There are missing frames to be written.";
173      return;
174    }
175    if (frame != frames_written_.front()) {
176      ADD_FAILURE() << "Written data frame does not match the expectation.";
177      return;
178    }
179    frames_written_.pop_front();
180  }
181  void AddFramesToBeInput(const ScopedVector<WebSocketFrame>& frames) {
182    for (size_t i = 0; i < frames.size(); ++i)
183      AddFrameToBeInput(frames[i]);
184  }
185  void VerifySentFrames(const ScopedVector<WebSocketFrame>& frames) {
186    for (size_t i = 0; i < frames.size(); ++i)
187      VerifySentFrame(frames[i]);
188  }
189  // Call this method in order to disable checks in the destructor when
190  // WriteFrames fails.
191  void Clear() {
192    frames_to_be_input_.clear();
193    frames_written_.clear();
194  }
195
196 private:
197  Result result_;
198  // Data frames which will be recorded by |RecordInputFrames|.
199  // Pushed by |AddFrameToBeInput| and popped and verified by
200  // |RecordInputFrames|.
201  std::deque<const WebSocketFrame*> frames_to_be_input_;
202  // Data frames recorded by |RecordWrittenFrames|.
203  // Pushed by |RecordWrittenFrames| and popped and verified by
204  // |VerifySentFrame|.
205  std::deque<const WebSocketFrame*> frames_written_;
206
207  DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock);
208};
209
210class WebSocketDeflateStreamTest : public ::testing::Test {
211 public:
212  WebSocketDeflateStreamTest()
213      : mock_stream_(NULL),
214        predictor_(NULL) {}
215  virtual ~WebSocketDeflateStreamTest() {}
216
217  virtual void SetUp() {
218    Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, kWindowBits);
219  }
220
221 protected:
222  // Initialize deflate_stream_ with the given parameters.
223  void Initialize(WebSocketDeflater::ContextTakeOverMode mode,
224                  int window_bits) {
225    mock_stream_ = new testing::StrictMock<MockWebSocketStream>;
226    predictor_ = new WebSocketDeflatePredictorMock;
227    deflate_stream_.reset(new WebSocketDeflateStream(
228        scoped_ptr<WebSocketStream>(mock_stream_),
229        mode,
230        window_bits,
231        scoped_ptr<WebSocketDeflatePredictor>(predictor_)));
232  }
233
234  scoped_ptr<WebSocketDeflateStream> deflate_stream_;
235  // Owned by |deflate_stream_|.
236  MockWebSocketStream* mock_stream_;
237  // Owned by |deflate_stream_|.
238  WebSocketDeflatePredictorMock* predictor_;
239};
240
241// Since WebSocketDeflater with DoNotTakeOverContext is well tested at
242// websocket_deflater_test.cc, we have only a few tests for this configuration
243// here.
244class WebSocketDeflateStreamWithDoNotTakeOverContextTest
245    : public WebSocketDeflateStreamTest {
246 public:
247  WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
248  virtual ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
249
250  virtual void SetUp() {
251    Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT, kWindowBits);
252  }
253};
254
255class WebSocketDeflateStreamWithClientWindowBitsTest
256    : public WebSocketDeflateStreamTest {
257 public:
258  WebSocketDeflateStreamWithClientWindowBitsTest() {}
259  virtual ~WebSocketDeflateStreamWithClientWindowBitsTest() {}
260
261  // Overridden to postpone the call to Initialize().
262  virtual void SetUp() {}
263
264  // This needs to be called explicitly from the tests.
265  void SetUpWithWindowBits(int window_bits) {
266    Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, window_bits);
267  }
268
269  // Add a frame which will be compressed to a smaller size if the window
270  // size is large enough.
271  void AddCompressibleFrameString() {
272    const std::string word = "Chromium";
273    const std::string payload = word + std::string(256, 'a') + word;
274    AppendTo(&frames_, WebSocketFrameHeader::kOpCodeText, kFinal, payload);
275    predictor_->AddFramesToBeInput(frames_);
276  }
277
278 protected:
279  ScopedVector<WebSocketFrame> frames_;
280};
281
282// ReadFrameStub is a stub for WebSocketStream::ReadFrames.
283// It returns |result_| and |frames_to_output_| to the caller and
284// saves parameters to |frames_passed_| and |callback_|.
285class ReadFramesStub {
286 public:
287  explicit ReadFramesStub(int result) : result_(result) {}
288
289  ReadFramesStub(int result, ScopedVector<WebSocketFrame>* frames_to_output)
290      : result_(result) {
291    frames_to_output_.swap(*frames_to_output);
292  }
293
294  int Call(ScopedVector<WebSocketFrame>* frames,
295           const CompletionCallback& callback) {
296    DCHECK(frames->empty());
297    frames_passed_ = frames;
298    callback_ = callback;
299    frames->swap(frames_to_output_);
300    return result_;
301  }
302
303  int result() const { return result_; }
304  const CompletionCallback callback() const { return callback_; }
305  ScopedVector<WebSocketFrame>* frames_passed() {
306    return frames_passed_;
307  }
308
309 private:
310  int result_;
311  CompletionCallback callback_;
312  ScopedVector<WebSocketFrame> frames_to_output_;
313  ScopedVector<WebSocketFrame>* frames_passed_;
314};
315
316// WriteFramesStub is a stub for WebSocketStream::WriteFrames.
317// It returns |result_| and |frames_| to the caller and
318// saves |callback| parameter to |callback_|.
319class WriteFramesStub {
320 public:
321  explicit WriteFramesStub(WebSocketDeflatePredictorMock* predictor,
322                           int result)
323      : result_(result), predictor_(predictor) {}
324
325  int Call(ScopedVector<WebSocketFrame>* frames,
326           const CompletionCallback& callback) {
327    frames_.insert(frames_.end(), frames->begin(), frames->end());
328    frames->weak_clear();
329    callback_ = callback;
330    predictor_->VerifySentFrames(frames_);
331    return result_;
332  }
333
334  int result() const { return result_; }
335  const CompletionCallback callback() const { return callback_; }
336  ScopedVector<WebSocketFrame>* frames() { return &frames_; }
337
338 private:
339  int result_;
340  CompletionCallback callback_;
341  ScopedVector<WebSocketFrame> frames_;
342  WebSocketDeflatePredictorMock* predictor_;
343};
344
345TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) {
346  ScopedVector<WebSocketFrame> frames;
347  CompletionCallback callback;
348  {
349    InSequence s;
350    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
351        .WillOnce(Return(ERR_FAILED));
352  }
353  EXPECT_EQ(ERR_FAILED, deflate_stream_->ReadFrames(&frames, callback));
354}
355
356TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameImmediately) {
357  ScopedVector<WebSocketFrame> frames_to_output;
358  AppendTo(&frames_to_output,
359           WebSocketFrameHeader::kOpCodeText,
360           kFinal,
361           "hello");
362  ReadFramesStub stub(OK, &frames_to_output);
363  ScopedVector<WebSocketFrame> frames;
364
365  {
366    InSequence s;
367    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
368        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
369  }
370  CompletionCallback callback;
371  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
372  ASSERT_EQ(1u, frames.size());
373  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
374  EXPECT_TRUE(frames[0]->header.final);
375  EXPECT_FALSE(frames[0]->header.reserved1);
376  EXPECT_EQ("hello", ToString(frames[0]));
377}
378
379TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) {
380  ReadFramesStub stub(ERR_IO_PENDING);
381  ScopedVector<WebSocketFrame> frames;
382  MockCallback mock_callback, checkpoint;
383  CompletionCallback callback =
384      base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
385
386  {
387    InSequence s;
388    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
389        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
390    EXPECT_CALL(checkpoint, Call(0));
391    EXPECT_CALL(mock_callback, Call(OK));
392  }
393  ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
394  ASSERT_EQ(0u, frames.size());
395
396  checkpoint.Call(0);
397
398  AppendTo(stub.frames_passed(),
399           WebSocketFrameHeader::kOpCodeText,
400           kFinal,
401           "hello");
402  stub.callback().Run(OK);
403  ASSERT_EQ(1u, frames.size());
404  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
405  EXPECT_TRUE(frames[0]->header.final);
406  EXPECT_FALSE(frames[0]->header.reserved1);
407  EXPECT_EQ("hello", ToString(frames[0]));
408}
409
410TEST_F(WebSocketDeflateStreamTest, ReadFailedAsync) {
411  ReadFramesStub stub(ERR_IO_PENDING);
412  ScopedVector<WebSocketFrame> frames;
413  MockCallback mock_callback, checkpoint;
414  CompletionCallback callback =
415      base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
416
417  {
418    InSequence s;
419    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
420        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
421    EXPECT_CALL(checkpoint, Call(0));
422    EXPECT_CALL(mock_callback, Call(ERR_FAILED));
423  }
424  ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
425  ASSERT_EQ(0u, frames.size());
426
427  checkpoint.Call(0);
428
429  AppendTo(stub.frames_passed(),
430           WebSocketFrameHeader::kOpCodeText,
431           kFinal,
432           "hello");
433  stub.callback().Run(ERR_FAILED);
434  ASSERT_EQ(0u, frames.size());
435}
436
437TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameImmediately) {
438  ScopedVector<WebSocketFrame> frames_to_output;
439  AppendTo(&frames_to_output,
440           WebSocketFrameHeader::kOpCodeText,
441           kFinal | kReserved1,
442           std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
443  ReadFramesStub stub(OK, &frames_to_output);
444  CompletionCallback callback;
445  ScopedVector<WebSocketFrame> frames;
446  {
447    InSequence s;
448    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
449        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
450  }
451  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
452  ASSERT_EQ(1u, frames.size());
453  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
454  EXPECT_TRUE(frames[0]->header.final);
455  EXPECT_FALSE(frames[0]->header.reserved1);
456  EXPECT_EQ("Hello", ToString(frames[0]));
457}
458
459TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameAsync) {
460  ReadFramesStub stub(ERR_IO_PENDING);
461  MockCallback mock_callback, checkpoint;
462  CompletionCallback callback =
463      base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
464  ScopedVector<WebSocketFrame> frames;
465  {
466    InSequence s;
467    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
468        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
469    EXPECT_CALL(checkpoint, Call(0));
470    EXPECT_CALL(mock_callback, Call(OK));
471  }
472  ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
473
474  checkpoint.Call(0);
475
476  AppendTo(stub.frames_passed(),
477           WebSocketFrameHeader::kOpCodeText,
478           kFinal | kReserved1,
479           std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
480  stub.callback().Run(OK);
481
482  ASSERT_EQ(1u, frames.size());
483  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
484  EXPECT_TRUE(frames[0]->header.final);
485  EXPECT_FALSE(frames[0]->header.reserved1);
486  EXPECT_EQ("Hello", ToString(frames[0]));
487}
488
489TEST_F(WebSocketDeflateStreamTest,
490       ReadCompressedFrameFragmentImmediatelyButInflaterReturnsPending) {
491  ScopedVector<WebSocketFrame> frames_to_output;
492  const std::string data1("\xf2", 1);
493  const std::string data2("\x48\xcd\xc9\xc9\x07\x00", 6);
494  AppendTo(&frames_to_output,
495           WebSocketFrameHeader::kOpCodeText,
496           kReserved1,
497           data1);
498  ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING);
499  MockCallback mock_callback, checkpoint;
500  CompletionCallback callback =
501      base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
502  ScopedVector<WebSocketFrame> frames;
503
504  {
505    InSequence s;
506    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
507        .WillOnce(Invoke(&stub1, &ReadFramesStub::Call))
508        .WillOnce(Invoke(&stub2, &ReadFramesStub::Call));
509    EXPECT_CALL(checkpoint, Call(0));
510    EXPECT_CALL(mock_callback, Call(OK));
511  }
512  ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
513  ASSERT_EQ(0u, frames.size());
514
515  AppendTo(stub2.frames_passed(),
516           WebSocketFrameHeader::kOpCodeText,
517           kFinal,
518           data2);
519
520  checkpoint.Call(0);
521  stub2.callback().Run(OK);
522
523  ASSERT_EQ(1u, frames.size());
524  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
525  EXPECT_TRUE(frames[0]->header.final);
526  EXPECT_FALSE(frames[0]->header.reserved1);
527  EXPECT_EQ("Hello", ToString(frames[0]));
528}
529
530TEST_F(WebSocketDeflateStreamTest, ReadInvalidCompressedPayload) {
531  const std::string data("\xf2\x48\xcdINVALID", 10);
532  ScopedVector<WebSocketFrame> frames_to_output;
533  AppendTo(&frames_to_output,
534           WebSocketFrameHeader::kOpCodeText,
535           kFinal | kReserved1,
536           data);
537  ReadFramesStub stub(OK, &frames_to_output);
538  CompletionCallback callback;
539  ScopedVector<WebSocketFrame> frames;
540
541  {
542    InSequence s;
543    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
544        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
545  }
546  ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
547            deflate_stream_->ReadFrames(&frames, callback));
548  ASSERT_EQ(0u, frames.size());
549}
550
551TEST_F(WebSocketDeflateStreamTest, MergeMultipleFramesInReadFrames) {
552  const std::string data1("\xf2\x48\xcd", 3);
553  const std::string data2("\xc9\xc9\x07\x00", 4);
554  ScopedVector<WebSocketFrame> frames_to_output;
555  AppendTo(&frames_to_output,
556           WebSocketFrameHeader::kOpCodeText,
557           kReserved1,
558           data1);
559  AppendTo(&frames_to_output,
560           WebSocketFrameHeader::kOpCodeContinuation,
561           kFinal,
562           data2);
563  ReadFramesStub stub(OK, &frames_to_output);
564  CompletionCallback callback;
565  ScopedVector<WebSocketFrame> frames;
566
567  {
568    InSequence s;
569    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
570        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
571  }
572  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
573  ASSERT_EQ(1u, frames.size());
574  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
575  EXPECT_TRUE(frames[0]->header.final);
576  EXPECT_FALSE(frames[0]->header.reserved1);
577  EXPECT_EQ("Hello", ToString(frames[0]));
578}
579
580TEST_F(WebSocketDeflateStreamTest, ReadUncompressedEmptyFrames) {
581  ScopedVector<WebSocketFrame> frames_to_output;
582  AppendTo(&frames_to_output,
583           WebSocketFrameHeader::kOpCodeText,
584           kNoFlag);
585  AppendTo(&frames_to_output,
586           WebSocketFrameHeader::kOpCodeContinuation,
587           kFinal);
588  ReadFramesStub stub(OK, &frames_to_output);
589  CompletionCallback callback;
590  ScopedVector<WebSocketFrame> frames;
591
592  {
593    InSequence s;
594    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
595        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
596  }
597  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
598  ASSERT_EQ(2u, frames.size());
599  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
600  EXPECT_FALSE(frames[0]->header.final);
601  EXPECT_FALSE(frames[0]->header.reserved1);
602  EXPECT_EQ("", ToString(frames[0]));
603  EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
604            frames[1]->header.opcode);
605  EXPECT_TRUE(frames[1]->header.final);
606  EXPECT_FALSE(frames[1]->header.reserved1);
607  EXPECT_EQ("", ToString(frames[1]));
608}
609
610TEST_F(WebSocketDeflateStreamTest, ReadCompressedEmptyFrames) {
611  ScopedVector<WebSocketFrame> frames_to_output;
612  AppendTo(&frames_to_output,
613           WebSocketFrameHeader::kOpCodeText,
614           kReserved1,
615           std::string("\x02\x00", 1));
616  AppendTo(&frames_to_output,
617           WebSocketFrameHeader::kOpCodeContinuation,
618           kFinal);
619  ReadFramesStub stub(OK, &frames_to_output);
620  CompletionCallback callback;
621  ScopedVector<WebSocketFrame> frames;
622
623  {
624    InSequence s;
625    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
626        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
627  }
628  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
629  ASSERT_EQ(1u, frames.size());
630  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
631  EXPECT_TRUE(frames[0]->header.final);
632  EXPECT_FALSE(frames[0]->header.reserved1);
633  EXPECT_EQ("", ToString(frames[0]));
634}
635
636TEST_F(WebSocketDeflateStreamTest,
637       ReadCompressedFrameFollowedByEmptyFrame) {
638  const std::string data("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
639  ScopedVector<WebSocketFrame> frames_to_output;
640  AppendTo(&frames_to_output,
641           WebSocketFrameHeader::kOpCodeText,
642           kReserved1,
643           data);
644  AppendTo(&frames_to_output,
645           WebSocketFrameHeader::kOpCodeContinuation,
646           kFinal);
647  ReadFramesStub stub(OK, &frames_to_output);
648  CompletionCallback callback;
649  ScopedVector<WebSocketFrame> frames;
650
651  {
652    InSequence s;
653    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
654        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
655  }
656  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
657  ASSERT_EQ(1u, frames.size());
658  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
659  EXPECT_TRUE(frames[0]->header.final);
660  EXPECT_FALSE(frames[0]->header.reserved1);
661  EXPECT_EQ("Hello", ToString(frames[0]));
662}
663
664TEST_F(WebSocketDeflateStreamTest, ReadControlFrameBetweenDataFrames) {
665  const std::string data1("\xf2\x48\xcd", 3);
666  const std::string data2("\xc9\xc9\x07\x00", 4);
667  ScopedVector<WebSocketFrame> frames_to_output;
668  AppendTo(&frames_to_output,
669           WebSocketFrameHeader::kOpCodeText,
670           kReserved1,
671           data1);
672  AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodePing, kFinal);
673  AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodeText, kFinal, data2);
674  ReadFramesStub stub(OK, &frames_to_output);
675  CompletionCallback callback;
676  ScopedVector<WebSocketFrame> frames;
677
678  {
679    InSequence s;
680    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
681        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
682  }
683  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
684  ASSERT_EQ(2u, frames.size());
685  EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames[0]->header.opcode);
686  EXPECT_TRUE(frames[0]->header.final);
687  EXPECT_FALSE(frames[0]->header.reserved1);
688  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
689  EXPECT_TRUE(frames[1]->header.final);
690  EXPECT_FALSE(frames[1]->header.reserved1);
691  EXPECT_EQ("Hello", ToString(frames[1]));
692}
693
694TEST_F(WebSocketDeflateStreamTest, SplitToMultipleFramesInReadFrames) {
695  WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
696  deflater.Initialize(kWindowBits);
697  const size_t kSize = kChunkSize * 3;
698  const std::string original_data(kSize, 'a');
699  deflater.AddBytes(original_data.data(), original_data.size());
700  deflater.Finish();
701
702  ScopedVector<WebSocketFrame> frames_to_output;
703  AppendTo(&frames_to_output,
704           WebSocketFrameHeader::kOpCodeBinary,
705           kFinal | kReserved1,
706           ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
707
708  ReadFramesStub stub(OK, &frames_to_output);
709  CompletionCallback callback;
710  ScopedVector<WebSocketFrame> frames;
711  {
712    InSequence s;
713    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
714        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
715  }
716
717  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
718  ASSERT_EQ(3u, frames.size());
719  EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode);
720  EXPECT_FALSE(frames[0]->header.final);
721  EXPECT_FALSE(frames[0]->header.reserved1);
722  EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length));
723  EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
724            frames[1]->header.opcode);
725  EXPECT_FALSE(frames[1]->header.final);
726  EXPECT_FALSE(frames[1]->header.reserved1);
727  EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[1]->header.payload_length));
728  EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
729            frames[2]->header.opcode);
730  EXPECT_TRUE(frames[2]->header.final);
731  EXPECT_FALSE(frames[2]->header.reserved1);
732  EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[2]->header.payload_length));
733  EXPECT_EQ(original_data,
734            ToString(frames[0]) + ToString(frames[1]) + ToString(frames[2]));
735}
736
737TEST_F(WebSocketDeflateStreamTest, InflaterInternalDataCanBeEmpty) {
738  WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
739  deflater.Initialize(kWindowBits);
740  const std::string original_data(kChunkSize, 'a');
741  deflater.AddBytes(original_data.data(), original_data.size());
742  deflater.Finish();
743
744  ScopedVector<WebSocketFrame> frames_to_output;
745  AppendTo(&frames_to_output,
746           WebSocketFrameHeader::kOpCodeBinary,
747           kReserved1,
748           ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
749  AppendTo(&frames_to_output,
750           WebSocketFrameHeader::kOpCodeBinary,
751           kFinal,
752           "");
753
754  ReadFramesStub stub(OK, &frames_to_output);
755  CompletionCallback callback;
756  ScopedVector<WebSocketFrame> frames;
757  {
758    InSequence s;
759    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
760        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
761  }
762
763  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
764  ASSERT_EQ(2u, frames.size());
765  EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode);
766  EXPECT_FALSE(frames[0]->header.final);
767  EXPECT_FALSE(frames[0]->header.reserved1);
768  EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length));
769
770  EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
771            frames[1]->header.opcode);
772  EXPECT_TRUE(frames[1]->header.final);
773  EXPECT_FALSE(frames[1]->header.reserved1);
774  EXPECT_EQ(0u, static_cast<size_t>(frames[1]->header.payload_length));
775  EXPECT_EQ(original_data, ToString(frames[0]) + ToString(frames[1]));
776}
777
778TEST_F(WebSocketDeflateStreamTest,
779       Reserved1TurnsOnDuringReadingCompressedContinuationFrame) {
780  const std::string data1("\xf2\x48\xcd", 3);
781  const std::string data2("\xc9\xc9\x07\x00", 4);
782  ScopedVector<WebSocketFrame> frames_to_output;
783  AppendTo(&frames_to_output,
784           WebSocketFrameHeader::kOpCodeText,
785           kReserved1,
786           data1);
787  AppendTo(&frames_to_output,
788           WebSocketFrameHeader::kOpCodeContinuation,
789           kFinal | kReserved1,
790           data2);
791  ReadFramesStub stub(OK, &frames_to_output);
792  CompletionCallback callback;
793  ScopedVector<WebSocketFrame> frames;
794
795  {
796    InSequence s;
797    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
798        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
799  }
800  ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
801            deflate_stream_->ReadFrames(&frames, callback));
802}
803
804TEST_F(WebSocketDeflateStreamTest,
805       Reserved1TurnsOnDuringReadingUncompressedContinuationFrame) {
806  ScopedVector<WebSocketFrame> frames_to_output;
807  AppendTo(&frames_to_output,
808           WebSocketFrameHeader::kOpCodeText,
809           kNoFlag,
810           "hello");
811  AppendTo(&frames_to_output,
812           WebSocketFrameHeader::kOpCodeContinuation,
813           kFinal | kReserved1,
814           "world");
815  ReadFramesStub stub(OK, &frames_to_output);
816  CompletionCallback callback;
817  ScopedVector<WebSocketFrame> frames;
818
819  {
820    InSequence s;
821    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
822        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
823  }
824  ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
825            deflate_stream_->ReadFrames(&frames, callback));
826}
827
828TEST_F(WebSocketDeflateStreamTest, ReadCompressedMessages) {
829  ScopedVector<WebSocketFrame> frames_to_output;
830  AppendTo(&frames_to_output,
831           WebSocketFrameHeader::kOpCodeText,
832           kFinal | kReserved1,
833           std::string(
834               "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
835  AppendTo(&frames_to_output,
836           WebSocketFrameHeader::kOpCodeText,
837           kFinal | kReserved1,
838           std::string("\x4a\x86\x33\x8d\x00\x00", 6));
839  ReadFramesStub stub(OK, &frames_to_output);
840  CompletionCallback callback;
841  ScopedVector<WebSocketFrame> frames;
842
843  {
844    InSequence s;
845    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
846        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
847  }
848  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
849  ASSERT_EQ(2u, frames.size());
850  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
851  EXPECT_TRUE(frames[0]->header.final);
852  EXPECT_FALSE(frames[0]->header.reserved1);
853  EXPECT_EQ("compressed1", ToString(frames[0]));
854  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
855  EXPECT_TRUE(frames[1]->header.final);
856  EXPECT_FALSE(frames[1]->header.reserved1);
857  EXPECT_EQ("compressed2", ToString(frames[1]));
858}
859
860TEST_F(WebSocketDeflateStreamTest, ReadUncompressedMessages) {
861  ScopedVector<WebSocketFrame> frames_to_output;
862  AppendTo(&frames_to_output,
863           WebSocketFrameHeader::kOpCodeText,
864           kFinal,
865           "uncompressed1");
866  AppendTo(&frames_to_output,
867           WebSocketFrameHeader::kOpCodeText,
868           kFinal,
869           "uncompressed2");
870  ReadFramesStub stub(OK, &frames_to_output);
871  CompletionCallback callback;
872  ScopedVector<WebSocketFrame> frames;
873
874  {
875    InSequence s;
876    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
877        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
878  }
879  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
880  ASSERT_EQ(2u, frames.size());
881  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
882  EXPECT_TRUE(frames[0]->header.final);
883  EXPECT_FALSE(frames[0]->header.reserved1);
884  EXPECT_EQ("uncompressed1", ToString(frames[0]));
885  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
886  EXPECT_TRUE(frames[1]->header.final);
887  EXPECT_FALSE(frames[1]->header.reserved1);
888  EXPECT_EQ("uncompressed2", ToString(frames[1]));
889}
890
891TEST_F(WebSocketDeflateStreamTest,
892       ReadCompressedMessageThenUncompressedMessage) {
893  ScopedVector<WebSocketFrame> frames_to_output;
894  AppendTo(&frames_to_output,
895           WebSocketFrameHeader::kOpCodeText,
896           kFinal | kReserved1,
897           std::string(
898               "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
899  AppendTo(&frames_to_output,
900           WebSocketFrameHeader::kOpCodeText,
901           kFinal,
902           "uncompressed");
903  ReadFramesStub stub(OK, &frames_to_output);
904  CompletionCallback callback;
905  ScopedVector<WebSocketFrame> frames;
906
907  {
908    InSequence s;
909    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
910        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
911  }
912  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
913  ASSERT_EQ(2u, frames.size());
914  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
915  EXPECT_TRUE(frames[0]->header.final);
916  EXPECT_FALSE(frames[0]->header.reserved1);
917  EXPECT_EQ("compressed", ToString(frames[0]));
918  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
919  EXPECT_TRUE(frames[1]->header.final);
920  EXPECT_FALSE(frames[1]->header.reserved1);
921  EXPECT_EQ("uncompressed", ToString(frames[1]));
922}
923
924TEST_F(WebSocketDeflateStreamTest,
925       ReadUncompressedMessageThenCompressedMessage) {
926  ScopedVector<WebSocketFrame> frames_to_output;
927  AppendTo(&frames_to_output,
928           WebSocketFrameHeader::kOpCodeText,
929           kFinal,
930           "uncompressed");
931  AppendTo(&frames_to_output,
932           WebSocketFrameHeader::kOpCodeText,
933           kFinal | kReserved1,
934           std::string(
935               "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
936  ReadFramesStub stub(OK, &frames_to_output);
937  CompletionCallback callback;
938  ScopedVector<WebSocketFrame> frames;
939
940  {
941    InSequence s;
942    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
943        .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
944  }
945  ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
946  ASSERT_EQ(2u, frames.size());
947  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
948  EXPECT_TRUE(frames[0]->header.final);
949  EXPECT_FALSE(frames[0]->header.reserved1);
950  EXPECT_EQ("uncompressed", ToString(frames[0]));
951  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
952  EXPECT_TRUE(frames[1]->header.final);
953  EXPECT_FALSE(frames[1]->header.reserved1);
954  EXPECT_EQ("compressed", ToString(frames[1]));
955}
956
957// This is a regression test for crbug.com/343506.
958TEST_F(WebSocketDeflateStreamTest, ReadEmptyAsyncFrame) {
959  ScopedVector<ReadFramesStub> stub_vector;
960  stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING));
961  stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING));
962  MockCallback mock_callback;
963  CompletionCallback callback =
964      base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
965  ScopedVector<WebSocketFrame> frames;
966
967  {
968    InSequence s;
969    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
970        .WillOnce(Invoke(stub_vector[0], &ReadFramesStub::Call));
971
972    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
973        .WillOnce(Invoke(stub_vector[1], &ReadFramesStub::Call));
974
975    EXPECT_CALL(mock_callback, Call(OK));
976  }
977
978  ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
979  AppendTo(stub_vector[0]->frames_passed(),
980           WebSocketFrameHeader::kOpCodeText,
981           kReserved1,
982           std::string());
983  stub_vector[0]->callback().Run(OK);
984  AppendTo(stub_vector[1]->frames_passed(),
985           WebSocketFrameHeader::kOpCodeContinuation,
986           kFinal,
987           std::string("\x02\x00"));
988  stub_vector[1]->callback().Run(OK);
989  ASSERT_EQ(1u, frames.size());
990  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
991  EXPECT_EQ("", ToString(frames[0]));
992}
993
994TEST_F(WebSocketDeflateStreamTest, WriteEmpty) {
995  ScopedVector<WebSocketFrame> frames;
996  CompletionCallback callback;
997  {
998    InSequence s;
999    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0);
1000  }
1001  EXPECT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1002}
1003
1004TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) {
1005  ScopedVector<WebSocketFrame> frames;
1006  CompletionCallback callback;
1007  {
1008    InSequence s;
1009    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1010        .WillOnce(Return(ERR_FAILED));
1011  }
1012
1013  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello");
1014  predictor_->AddFramesToBeInput(frames);
1015  EXPECT_EQ(ERR_FAILED, deflate_stream_->WriteFrames(&frames, callback));
1016  predictor_->Clear();
1017}
1018
1019TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) {
1020  ScopedVector<WebSocketFrame> frames;
1021  CompletionCallback callback;
1022  WriteFramesStub stub(predictor_, OK);
1023  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1024  predictor_->AddFramesToBeInput(frames);
1025  {
1026    InSequence s;
1027    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1028        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1029  }
1030  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1031  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1032  ASSERT_EQ(1u, frames_passed.size());
1033  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1034  EXPECT_TRUE(frames_passed[0]->header.final);
1035  EXPECT_TRUE(frames_passed[0]->header.reserved1);
1036  EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1037            ToString(frames_passed[0]));
1038}
1039
1040TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) {
1041  WriteFramesStub stub(predictor_, ERR_IO_PENDING);
1042  MockCallback mock_callback, checkpoint;
1043  CompletionCallback callback =
1044      base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
1045  ScopedVector<WebSocketFrame> frames;
1046  {
1047    InSequence s;
1048    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1049        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1050    EXPECT_CALL(checkpoint, Call(0));
1051    EXPECT_CALL(mock_callback, Call(OK));
1052  }
1053  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1054  predictor_->AddFramesToBeInput(frames);
1055  ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->WriteFrames(&frames, callback));
1056
1057  checkpoint.Call(0);
1058  stub.callback().Run(OK);
1059
1060  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1061  ASSERT_EQ(1u, frames_passed.size());
1062  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1063  EXPECT_TRUE(frames_passed[0]->header.final);
1064  EXPECT_TRUE(frames_passed[0]->header.reserved1);
1065  EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1066            ToString(frames_passed[0]));
1067}
1068
1069TEST_F(WebSocketDeflateStreamTest, WriteControlFrameBetweenDataFrames) {
1070  ScopedVector<WebSocketFrame> frames;
1071  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "Hel");
1072  AppendTo(&frames, WebSocketFrameHeader::kOpCodePing, kFinal);
1073  AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "lo");
1074  predictor_->AddFramesToBeInput(frames);
1075  WriteFramesStub stub(predictor_, OK);
1076  CompletionCallback callback;
1077
1078  {
1079    InSequence s;
1080    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1081        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1082  }
1083  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1084  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1085  ASSERT_EQ(2u, frames_passed.size());
1086  EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames_passed[0]->header.opcode);
1087  EXPECT_TRUE(frames_passed[0]->header.final);
1088  EXPECT_FALSE(frames_passed[0]->header.reserved1);
1089  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1090  EXPECT_TRUE(frames_passed[1]->header.final);
1091  EXPECT_TRUE(frames_passed[1]->header.reserved1);
1092  EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1093            ToString(frames_passed[1]));
1094}
1095
1096TEST_F(WebSocketDeflateStreamTest, WriteEmptyMessage) {
1097  ScopedVector<WebSocketFrame> frames;
1098  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal);
1099  predictor_->AddFramesToBeInput(frames);
1100  WriteFramesStub stub(predictor_, OK);
1101  CompletionCallback callback;
1102
1103  {
1104    InSequence s;
1105    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1106        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1107  }
1108  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1109  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1110  ASSERT_EQ(1u, frames_passed.size());
1111  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1112  EXPECT_TRUE(frames_passed[0]->header.final);
1113  EXPECT_TRUE(frames_passed[0]->header.reserved1);
1114  EXPECT_EQ(std::string("\x00", 1), ToString(frames_passed[0]));
1115}
1116
1117TEST_F(WebSocketDeflateStreamTest, WriteUncompressedMessage) {
1118  ScopedVector<WebSocketFrame> frames;
1119  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAA");
1120  AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AAA");
1121  predictor_->AddFramesToBeInput(frames);
1122  WriteFramesStub stub(predictor_, OK);
1123  CompletionCallback callback;
1124
1125  predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE);
1126
1127  {
1128    InSequence s;
1129    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1130        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1131  }
1132  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1133  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1134  ASSERT_EQ(2u, frames_passed.size());
1135  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1136  EXPECT_FALSE(frames_passed[0]->header.final);
1137  EXPECT_FALSE(frames_passed[0]->header.reserved1);
1138  EXPECT_EQ("AAAA", ToString(frames_passed[0]));
1139  EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1140            frames_passed[1]->header.opcode);
1141  EXPECT_TRUE(frames_passed[1]->header.final);
1142  EXPECT_FALSE(frames_passed[1]->header.reserved1);
1143  EXPECT_EQ("AAA", ToString(frames_passed[1]));
1144}
1145
1146TEST_F(WebSocketDeflateStreamTest, LargeDeflatedFramesShouldBeSplit) {
1147  WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
1148  LinearCongruentialGenerator lcg(133);
1149  WriteFramesStub stub(predictor_, OK);
1150  CompletionCallback callback;
1151  const size_t size = 1024;
1152
1153  {
1154    InSequence s;
1155    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1156        .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call));
1157  }
1158  ScopedVector<WebSocketFrame> total_compressed_frames;
1159
1160  deflater.Initialize(kWindowBits);
1161  while (true) {
1162    bool is_final = (total_compressed_frames.size() >= 2);
1163    ScopedVector<WebSocketFrame> frames;
1164    std::string data;
1165    for (size_t i = 0; i < size; ++i)
1166      data += static_cast<char>(lcg.Generate());
1167    deflater.AddBytes(data.data(), data.size());
1168    FrameFlag flag = is_final ? kFinal : kNoFlag;
1169    AppendTo(&frames, WebSocketFrameHeader::kOpCodeBinary, flag, data);
1170    predictor_->AddFramesToBeInput(frames);
1171    ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1172    total_compressed_frames.insert(total_compressed_frames.end(),
1173                                   stub.frames()->begin(),
1174                                   stub.frames()->end());
1175    stub.frames()->weak_clear();
1176    if (is_final)
1177      break;
1178  }
1179  deflater.Finish();
1180  std::string total_deflated;
1181  for (size_t i = 0; i < total_compressed_frames.size(); ++i) {
1182    WebSocketFrame* frame = total_compressed_frames[i];
1183    const WebSocketFrameHeader& header = frame->header;
1184    if (i > 0) {
1185      EXPECT_EQ(header.kOpCodeContinuation, header.opcode);
1186      EXPECT_FALSE(header.reserved1);
1187    } else {
1188      EXPECT_EQ(header.kOpCodeBinary, header.opcode);
1189      EXPECT_TRUE(header.reserved1);
1190    }
1191    const bool is_final_frame = (i + 1 == total_compressed_frames.size());
1192    EXPECT_EQ(is_final_frame, header.final);
1193    if (!is_final_frame)
1194      EXPECT_GT(header.payload_length, 0ul);
1195    total_deflated += ToString(frame);
1196  }
1197  EXPECT_EQ(total_deflated,
1198            ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
1199}
1200
1201TEST_F(WebSocketDeflateStreamTest, WriteMultipleMessages) {
1202  ScopedVector<WebSocketFrame> frames;
1203  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1204  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1205  predictor_->AddFramesToBeInput(frames);
1206  WriteFramesStub stub(predictor_, OK);
1207  CompletionCallback callback;
1208
1209  {
1210    InSequence s;
1211    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1212        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1213  }
1214  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1215  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1216  ASSERT_EQ(2u, frames_passed.size());
1217  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1218  EXPECT_TRUE(frames_passed[0]->header.final);
1219  EXPECT_TRUE(frames_passed[0]->header.reserved1);
1220  EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1221            ToString(frames_passed[0]));
1222  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1223  EXPECT_TRUE(frames_passed[1]->header.final);
1224  EXPECT_TRUE(frames_passed[1]->header.reserved1);
1225  EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed[1]));
1226}
1227
1228TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
1229       WriteMultipleMessages) {
1230  ScopedVector<WebSocketFrame> frames;
1231  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1232  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
1233  predictor_->AddFramesToBeInput(frames);
1234  WriteFramesStub stub(predictor_, OK);
1235  CompletionCallback callback;
1236
1237  {
1238    InSequence s;
1239    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1240        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1241  }
1242  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1243  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1244  ASSERT_EQ(2u, frames_passed.size());
1245  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1246  EXPECT_TRUE(frames_passed[0]->header.final);
1247  EXPECT_TRUE(frames_passed[0]->header.reserved1);
1248  EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1249            ToString(frames_passed[0]));
1250  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
1251  EXPECT_TRUE(frames_passed[1]->header.final);
1252  EXPECT_TRUE(frames_passed[1]->header.reserved1);
1253  EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
1254            ToString(frames_passed[1]));
1255}
1256
1257// In order to check the stream works correctly for multiple
1258// "PossiblyCompressedMessage"s, we test various messages at one test case.
1259TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
1260       WritePossiblyCompressMessages) {
1261  ScopedVector<WebSocketFrame> frames;
1262  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "He");
1263  AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "llo");
1264  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAAAAAAAA");
1265  AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AA");
1266  AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "XX");
1267  AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "YY");
1268  predictor_->AddFramesToBeInput(frames);
1269  WriteFramesStub stub(predictor_, OK);
1270  CompletionCallback callback;
1271  predictor_->set_result(WebSocketDeflatePredictor::TRY_DEFLATE);
1272
1273  {
1274    InSequence s;
1275    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
1276        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1277  }
1278  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
1279  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1280  ASSERT_EQ(5u, frames_passed.size());
1281
1282  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
1283  EXPECT_FALSE(frames_passed[0]->header.final);
1284  EXPECT_FALSE(frames_passed[0]->header.reserved1);
1285  EXPECT_EQ("He", ToString(frames_passed[0]));
1286  EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1287            frames_passed[1]->header.opcode);
1288  EXPECT_TRUE(frames_passed[1]->header.final);
1289  EXPECT_FALSE(frames_passed[1]->header.reserved1);
1290  EXPECT_EQ("llo", ToString(frames_passed[1]));
1291
1292  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[2]->header.opcode);
1293  EXPECT_TRUE(frames_passed[2]->header.final);
1294  EXPECT_TRUE(frames_passed[2]->header.reserved1);
1295  EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6),
1296            ToString(frames_passed[2]));
1297
1298  EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[3]->header.opcode);
1299  EXPECT_FALSE(frames_passed[3]->header.final);
1300  EXPECT_FALSE(frames_passed[3]->header.reserved1);
1301  EXPECT_EQ("XX", ToString(frames_passed[3]));
1302  EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
1303            frames_passed[4]->header.opcode);
1304  EXPECT_TRUE(frames_passed[4]->header.final);
1305  EXPECT_FALSE(frames_passed[4]->header.reserved1);
1306  EXPECT_EQ("YY", ToString(frames_passed[4]));
1307}
1308
1309// This is based on the similar test from websocket_deflater_test.cc
1310TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits8) {
1311  SetUpWithWindowBits(8);
1312  CompletionCallback callback;
1313  AddCompressibleFrameString();
1314  WriteFramesStub stub(predictor_, OK);
1315  {
1316    InSequence s;
1317    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1318        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1319  }
1320  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback));
1321  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1322  ASSERT_EQ(1u, frames_passed.size());
1323  EXPECT_EQ(std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x39\xa3"
1324                        "(?7\xb3\x34\x17\x00", 21),
1325            ToString(frames_passed[0]));
1326}
1327
1328// The same input with window_bits=10 returns smaller output.
1329TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits10) {
1330  SetUpWithWindowBits(10);
1331  CompletionCallback callback;
1332  AddCompressibleFrameString();
1333  WriteFramesStub stub(predictor_, OK);
1334  {
1335    InSequence s;
1336    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
1337        .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
1338  }
1339  ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback));
1340  const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
1341  ASSERT_EQ(1u, frames_passed.size());
1342  EXPECT_EQ(
1343      std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17),
1344      ToString(frames_passed[0]));
1345}
1346
1347}  // namespace
1348
1349}  // namespace net
1350