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