xref: /aosp_15_r20/external/cronet/net/websockets/websocket_deflate_stream_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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