• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Tests for WebSocketBasicStream. Note that we do not attempt to verify that
6 // frame parsing itself functions correctly, as that is covered by the
7 // WebSocketFrameParser tests.
8 
9 #include "net/websockets/websocket_basic_stream.h"
10 
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <string.h>  // for memcpy() and memset().
14 
15 #include <iterator>
16 #include <utility>
17 
18 #include "base/big_endian.h"
19 #include "base/containers/span.h"
20 #include "base/strings/string_piece.h"
21 #include "base/time/time.h"
22 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/network_anonymization_key.h"
25 #include "net/base/privacy_mode.h"
26 #include "net/base/request_priority.h"
27 #include "net/base/test_completion_callback.h"
28 #include "net/dns/public/secure_dns_policy.h"
29 #include "net/socket/client_socket_handle.h"
30 #include "net/socket/client_socket_pool.h"
31 #include "net/socket/connect_job.h"
32 #include "net/socket/socket_tag.h"
33 #include "net/socket/socket_test_util.h"
34 #include "net/test/gtest_util.h"
35 #include "net/test/test_with_task_environment.h"
36 #include "net/traffic_annotation/network_traffic_annotation.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39 #include "third_party/abseil-cpp/absl/types/optional.h"
40 #include "url/scheme_host_port.h"
41 #include "url/url_constants.h"
42 
43 using net::test::IsError;
44 using net::test::IsOk;
45 
46 namespace net {
47 namespace {
48 
49 #define WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(name, value) \
50   const char k##name[] = value;                                  \
51   const size_t k##name##Size = std::size(k##name) - 1
52 
53 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(SampleFrame, "\x81\x06Sample");
54 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
55     PartialLargeFrame,
56     "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF"
57     "chromiunum ad pasco per loca insanis pullum manducat frumenti");
58 const size_t kLargeFrameHeaderSize = 10;
59 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MultipleFrames,
60                                             "\x81\x01X\x81\x01Y\x81\x01Z");
61 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFirstFrame, "\x01\x00");
62 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyMiddleFrame, "\x00\x00");
63 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalTextFrame, "\x81\x00");
64 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalContinuationFrame,
65                                             "\x80\x00");
66 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(ValidPong, "\x8A\x00");
67 // This frame encodes a payload length of 7 in two bytes, which is always
68 // invalid.
69 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(InvalidFrame,
70                                             "\x81\x7E\x00\x07Invalid");
71 // Control frames must have the FIN bit set. This one does not.
72 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(PingFrameWithoutFin, "\x09\x00");
73 // Control frames must have a payload of 125 bytes or less. This one has
74 // a payload of 126 bytes.
75 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
76     126BytePong,
77     "\x8a\x7e\x00\x7eZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
78     "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
79 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(CloseFrame,
80                                             "\x88\x09\x03\xe8occludo");
81 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(WriteFrame,
82                                             "\x81\x85\x00\x00\x00\x00Write");
83 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MaskedEmptyPong,
84                                             "\x8A\x80\x00\x00\x00\x00");
85 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}};
86 const WebSocketMaskingKey kNonNulMaskingKey = {
87     {'\x0d', '\x1b', '\x06', '\x17'}};
88 
89 // A masking key generator function which generates the identity mask,
90 // ie. "\0\0\0\0".
GenerateNulMaskingKey()91 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
92 
93 // A masking key generation function which generates a fixed masking key with no
94 // nul characters.
GenerateNonNulMaskingKey()95 WebSocketMaskingKey GenerateNonNulMaskingKey() { return kNonNulMaskingKey; }
96 
97 // A subclass of StaticSocketDataProvider modified to require that all data
98 // expected to be read or written actually is.
99 class StrictStaticSocketDataProvider : public StaticSocketDataProvider {
100  public:
StrictStaticSocketDataProvider(base::span<const MockRead> reads,base::span<const MockWrite> writes,bool strict_mode)101   StrictStaticSocketDataProvider(base::span<const MockRead> reads,
102                                  base::span<const MockWrite> writes,
103                                  bool strict_mode)
104       : StaticSocketDataProvider(reads, writes), strict_mode_(strict_mode) {}
105 
~StrictStaticSocketDataProvider()106   ~StrictStaticSocketDataProvider() override {
107     if (strict_mode_) {
108       EXPECT_EQ(read_count(), read_index());
109       EXPECT_EQ(write_count(), write_index());
110     }
111   }
112 
113  private:
114   const bool strict_mode_;
115 };
116 
117 // A fixture for tests which only perform normal socket operations.
118 class WebSocketBasicStreamSocketTest : public TestWithTaskEnvironment {
119  protected:
WebSocketBasicStreamSocketTest()120   WebSocketBasicStreamSocketTest()
121       : common_connect_job_params_(
122             &factory_,
123             /*host_resolver=*/nullptr,
124             /*http_auth_cache=*/nullptr,
125             /*http_auth_handler_factory=*/nullptr,
126             /*spdy_session_pool=*/nullptr,
127             /*quic_supported_versions=*/nullptr,
128             /*quic_stream_factory=*/nullptr,
129             /*proxy_delegate=*/nullptr,
130             /*http_user_agent_settings=*/nullptr,
131             /*ssl_client_context=*/nullptr,
132             /*socket_performance_watcher_factory=*/nullptr,
133             /*network_quality_estimator=*/nullptr,
134             /*net_log=*/nullptr,
135             /*websocket_endpoint_lock_manager=*/nullptr,
136             /*http_server_properties*/ nullptr,
137             /*alpn_protos=*/nullptr,
138             /*application_settings=*/nullptr,
139             /*ignore_certificate_errors=*/nullptr),
140         pool_(1, 1, &common_connect_job_params_),
141         generator_(&GenerateNulMaskingKey) {}
142 
~WebSocketBasicStreamSocketTest()143   ~WebSocketBasicStreamSocketTest() override {
144     // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
145     // should be destroyed first.
146     stream_.reset();
147   }
148 
MakeTransportSocket(base::span<const MockRead> reads,base::span<const MockWrite> writes)149   std::unique_ptr<ClientSocketHandle> MakeTransportSocket(
150       base::span<const MockRead> reads,
151       base::span<const MockWrite> writes) {
152     socket_data_ = std::make_unique<StrictStaticSocketDataProvider>(
153         reads, writes, expect_all_io_to_complete_);
154     socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
155     factory_.AddSocketDataProvider(socket_data_.get());
156 
157     auto transport_socket = std::make_unique<ClientSocketHandle>();
158     scoped_refptr<ClientSocketPool::SocketParams> null_params;
159     ClientSocketPool::GroupId group_id(
160         url::SchemeHostPort(url::kHttpScheme, "a", 80),
161         PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
162         SecureDnsPolicy::kAllow);
163     transport_socket->Init(
164         group_id, null_params, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
165         SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
166         CompletionOnceCallback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
167         NetLogWithSource());
168     return transport_socket;
169   }
170 
SetHttpReadBuffer(const char * data,size_t size)171   void SetHttpReadBuffer(const char* data, size_t size) {
172     http_read_buffer_ = base::MakeRefCounted<GrowableIOBuffer>();
173     http_read_buffer_->SetCapacity(size);
174     memcpy(http_read_buffer_->data(), data, size);
175     http_read_buffer_->set_offset(size);
176   }
177 
CreateStream(base::span<const MockRead> reads,base::span<const MockWrite> writes)178   void CreateStream(base::span<const MockRead> reads,
179                     base::span<const MockWrite> writes) {
180     stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
181         MakeTransportSocket(reads, writes), http_read_buffer_, sub_protocol_,
182         extensions_, net_log_, generator_);
183   }
184 
185   std::unique_ptr<SocketDataProvider> socket_data_;
186   MockClientSocketFactory factory_;
187   const CommonConnectJobParams common_connect_job_params_;
188   MockTransportClientSocketPool pool_;
189   std::vector<std::unique_ptr<WebSocketFrame>> frames_;
190   TestCompletionCallback cb_;
191   scoped_refptr<GrowableIOBuffer> http_read_buffer_;
192   std::string sub_protocol_;
193   std::string extensions_;
194   NetLogWithSource net_log_;
195   WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_;
196   bool expect_all_io_to_complete_ = true;
197   std::unique_ptr<WebSocketBasicStream> stream_;
198 };
199 
200 // A test fixture for the common case of tests that only perform a single read.
201 class WebSocketBasicStreamSocketSingleReadTest
202     : public WebSocketBasicStreamSocketTest {
203  protected:
CreateRead(const MockRead & read)204   void CreateRead(const MockRead& read) {
205     reads_[0] = read;
206     CreateStream(reads_, base::span<MockWrite>());
207   }
208 
209   MockRead reads_[1];
210 };
211 
212 // A test fixture for tests that perform chunked reads.
213 class WebSocketBasicStreamSocketChunkedReadTest
214     : public WebSocketBasicStreamSocketTest {
215  protected:
216   // Specify the behaviour if there aren't enough chunks to use all the data. If
217   // LAST_FRAME_BIG is specified, then the rest of the data will be
218   // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last
219   // frame will be no bigger than the rest of the frames (but it can be smaller,
220   // if not enough data remains).
221   enum LastFrameBehaviour {
222     LAST_FRAME_BIG,
223     LAST_FRAME_NOT_BIG
224   };
225 
226   // Prepares a read from |data| of |data_size|, split into |number_of_chunks|,
227   // each of |chunk_size| (except that the last chunk may be larger or
228   // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture),
229   // and errors cannot be simulated. Once data is exhausted, further reads will
230   // return 0 (ie. connection closed).
CreateChunkedRead(IoMode mode,const char data[],size_t data_size,int chunk_size,size_t number_of_chunks,LastFrameBehaviour last_frame_behaviour)231   void CreateChunkedRead(IoMode mode,
232                          const char data[],
233                          size_t data_size,
234                          int chunk_size,
235                          size_t number_of_chunks,
236                          LastFrameBehaviour last_frame_behaviour) {
237     reads_.clear();
238     const char* start = data;
239     for (size_t i = 0; i < number_of_chunks; ++i) {
240       int len = chunk_size;
241       const bool is_last_chunk = (i == number_of_chunks - 1);
242       if ((last_frame_behaviour == LAST_FRAME_BIG && is_last_chunk) ||
243           static_cast<int>(data + data_size - start) < len) {
244         len = static_cast<int>(data + data_size - start);
245       }
246       reads_.emplace_back(mode, start, len);
247       start += len;
248     }
249     CreateStream(reads_, base::span<MockWrite>());
250   }
251 
252   std::vector<MockRead> reads_;
253 };
254 
255 // Test fixture for write tests.
256 class WebSocketBasicStreamSocketWriteTest
257     : public WebSocketBasicStreamSocketTest {
258  protected:
259   // All write tests use the same frame, so it is easiest to create it during
260   // test creation.
SetUp()261   void SetUp() override { PrepareWriteFrame(); }
262 
263   // Creates a WebSocketFrame with a wire format matching kWriteFrame and adds
264   // it to |frames_|.
PrepareWriteFrame()265   void PrepareWriteFrame() {
266     auto frame =
267         std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodeText);
268     const size_t payload_size =
269         kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
270                            WebSocketFrameHeader::kMaskingKeyLength);
271     auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_size);
272     frame_buffers_.push_back(buffer);
273     memcpy(buffer->data(), kWriteFrame + kWriteFrameSize - payload_size,
274            payload_size);
275     frame->payload = buffer->data();
276     WebSocketFrameHeader& header = frame->header;
277     header.final = true;
278     header.masked = true;
279     header.payload_length = payload_size;
280     frames_.push_back(std::move(frame));
281   }
282 
283   // TODO(yoichio): Make this type std::vector<std::string>.
284   std::vector<scoped_refptr<IOBuffer>> frame_buffers_;
285 };
286 
287 // A test fixture for tests that perform read buffer size switching.
288 class WebSocketBasicStreamSwitchTest : public WebSocketBasicStreamSocketTest {
289  protected:
290   // This is used to specify the read start/end time.
MicrosecondsFromStart(int microseconds)291   base::TimeTicks MicrosecondsFromStart(int microseconds) {
292     static const base::TimeTicks kStartPoint =
293         base::TimeTicks::UnixEpoch() + base::Seconds(60);
294     return kStartPoint + base::Microseconds(microseconds);
295   }
296 
297   WebSocketBasicStream::BufferSizeManager buffer_size_manager_;
298 };
299 
TEST_F(WebSocketBasicStreamSocketTest,ConstructionWorks)300 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
301   CreateStream(base::span<MockRead>(), base::span<MockWrite>());
302 }
303 
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncReadWorks)304 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) {
305   CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize));
306   int result = stream_->ReadFrames(&frames_, cb_.callback());
307   EXPECT_THAT(result, IsOk());
308   ASSERT_EQ(1U, frames_.size());
309   EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
310   EXPECT_TRUE(frames_[0]->header.final);
311 }
312 
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncReadWorks)313 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) {
314   CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize));
315   int result = stream_->ReadFrames(&frames_, cb_.callback());
316   ASSERT_THAT(result, IsError(ERR_IO_PENDING));
317   EXPECT_THAT(cb_.WaitForResult(), IsOk());
318   ASSERT_EQ(1U, frames_.size());
319   EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
320   // Don't repeat all the tests from SyncReadWorks; just enough to be sure the
321   // frame was really read.
322 }
323 
324 // ReadFrames will not return a frame whose header has not been wholly received.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,HeaderFragmentedSync)325 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) {
326   CreateChunkedRead(
327       SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
328   int result = stream_->ReadFrames(&frames_, cb_.callback());
329   EXPECT_THAT(result, IsOk());
330   ASSERT_EQ(1U, frames_.size());
331   EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
332 }
333 
334 // The same behaviour applies to asynchronous reads.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,HeaderFragmentedAsync)335 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) {
336   CreateChunkedRead(
337       ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
338   int result = stream_->ReadFrames(&frames_, cb_.callback());
339   ASSERT_THAT(result, IsError(ERR_IO_PENDING));
340   EXPECT_THAT(cb_.WaitForResult(), IsOk());
341   ASSERT_EQ(1U, frames_.size());
342   EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
343 }
344 
345 // If it receives an incomplete header in a synchronous call, then has to wait
346 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING.
TEST_F(WebSocketBasicStreamSocketTest,HeaderFragmentedSyncAsync)347 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
348   MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
349                       MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
350   CreateStream(reads, base::span<MockWrite>());
351   int result = stream_->ReadFrames(&frames_, cb_.callback());
352   ASSERT_THAT(result, IsError(ERR_IO_PENDING));
353   EXPECT_THAT(cb_.WaitForResult(), IsOk());
354   ASSERT_EQ(1U, frames_.size());
355   EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
356 }
357 
358 // An extended header should also return ERR_IO_PENDING if it is not completely
359 // received.
TEST_F(WebSocketBasicStreamSocketTest,FragmentedLargeHeader)360 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
361   MockRead reads[] = {
362       MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
363       MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
364   CreateStream(reads, base::span<MockWrite>());
365   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
366               IsError(ERR_IO_PENDING));
367 }
368 
369 // A frame that does not arrive in a single read should be broken into separate
370 // frames.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,LargeFrameFirstChunk)371 TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) {
372   CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize));
373   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
374   ASSERT_EQ(1U, frames_.size());
375   EXPECT_FALSE(frames_[0]->header.final);
376   EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
377             static_cast<size_t>(frames_[0]->header.payload_length));
378 }
379 
380 // If only the header of a data frame arrives, we should receive a frame with a
381 // zero-size payload.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,HeaderOnlyChunk)382 TEST_F(WebSocketBasicStreamSocketSingleReadTest, HeaderOnlyChunk) {
383   CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize));
384 
385   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
386   ASSERT_EQ(1U, frames_.size());
387   EXPECT_EQ(nullptr, frames_[0]->payload);
388   EXPECT_EQ(0U, frames_[0]->header.payload_length);
389   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
390 }
391 
392 // If the header and the body of a data frame arrive seperately, we should see
393 // them as separate frames.
TEST_F(WebSocketBasicStreamSocketTest,HeaderBodySeparated)394 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) {
395   MockRead reads[] = {
396       MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
397       MockRead(ASYNC,
398                kPartialLargeFrame + kLargeFrameHeaderSize,
399                kPartialLargeFrameSize - kLargeFrameHeaderSize)};
400   CreateStream(reads, base::span<MockWrite>());
401   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
402   ASSERT_EQ(1U, frames_.size());
403   EXPECT_EQ(nullptr, frames_[0]->payload);
404   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
405   frames_.clear();
406   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
407               IsError(ERR_IO_PENDING));
408   EXPECT_THAT(cb_.WaitForResult(), IsOk());
409   ASSERT_EQ(1U, frames_.size());
410   EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
411             frames_[0]->header.payload_length);
412   EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
413             frames_[0]->header.opcode);
414 }
415 
416 // Every frame has a header with a correct payload_length field.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,LargeFrameTwoChunks)417 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) {
418   const size_t kChunkSize = 16;
419   CreateChunkedRead(ASYNC,
420                     kPartialLargeFrame,
421                     kPartialLargeFrameSize,
422                     kChunkSize,
423                     2,
424                     LAST_FRAME_NOT_BIG);
425   TestCompletionCallback cb[2];
426 
427   ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
428               IsError(ERR_IO_PENDING));
429   EXPECT_THAT(cb[0].WaitForResult(), IsOk());
430   ASSERT_EQ(1U, frames_.size());
431   EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize,
432             frames_[0]->header.payload_length);
433 
434   frames_.clear();
435   ASSERT_THAT(stream_->ReadFrames(&frames_, cb[1].callback()),
436               IsError(ERR_IO_PENDING));
437   EXPECT_THAT(cb[1].WaitForResult(), IsOk());
438   ASSERT_EQ(1U, frames_.size());
439   EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length);
440 }
441 
442 // Only the final frame of a fragmented message has |final| bit set.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,OnlyFinalChunkIsFinal)443 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) {
444   static const size_t kFirstChunkSize = 4;
445   CreateChunkedRead(ASYNC,
446                     kSampleFrame,
447                     kSampleFrameSize,
448                     kFirstChunkSize,
449                     2,
450                     LAST_FRAME_BIG);
451   TestCompletionCallback cb[2];
452 
453   ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
454               IsError(ERR_IO_PENDING));
455   EXPECT_THAT(cb[0].WaitForResult(), IsOk());
456   ASSERT_EQ(1U, frames_.size());
457   ASSERT_FALSE(frames_[0]->header.final);
458 
459   frames_.clear();
460   ASSERT_THAT(stream_->ReadFrames(&frames_, cb[1].callback()),
461               IsError(ERR_IO_PENDING));
462   EXPECT_THAT(cb[1].WaitForResult(), IsOk());
463   ASSERT_EQ(1U, frames_.size());
464   ASSERT_TRUE(frames_[0]->header.final);
465 }
466 
467 // All frames after the first have their opcode changed to Continuation.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,ContinuationOpCodeUsed)468 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ContinuationOpCodeUsed) {
469   const size_t kFirstChunkSize = 3;
470   const int kChunkCount = 3;
471   // The input data is one frame with opcode Text, which arrives in three
472   // separate chunks.
473   CreateChunkedRead(ASYNC,
474                     kSampleFrame,
475                     kSampleFrameSize,
476                     kFirstChunkSize,
477                     kChunkCount,
478                     LAST_FRAME_BIG);
479   TestCompletionCallback cb[kChunkCount];
480 
481   ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
482               IsError(ERR_IO_PENDING));
483   EXPECT_THAT(cb[0].WaitForResult(), IsOk());
484   ASSERT_EQ(1U, frames_.size());
485   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
486 
487   // This test uses a loop to verify that the opcode for every frames generated
488   // after the first is converted to Continuation.
489   for (int i = 1; i < kChunkCount; ++i) {
490     frames_.clear();
491     ASSERT_THAT(stream_->ReadFrames(&frames_, cb[i].callback()),
492                 IsError(ERR_IO_PENDING));
493     EXPECT_THAT(cb[i].WaitForResult(), IsOk());
494     ASSERT_EQ(1U, frames_.size());
495     EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
496               frames_[0]->header.opcode);
497   }
498 }
499 
500 // Multiple frames that arrive together should be parsed correctly.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,ThreeFramesTogether)501 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
502   CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
503 
504   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
505   ASSERT_EQ(3U, frames_.size());
506   EXPECT_TRUE(frames_[0]->header.final);
507   EXPECT_TRUE(frames_[1]->header.final);
508   EXPECT_TRUE(frames_[2]->header.final);
509 }
510 
511 // ERR_CONNECTION_CLOSED must be returned on close.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncClose)512 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
513   CreateRead(MockRead(SYNCHRONOUS, "", 0));
514 
515   EXPECT_EQ(ERR_CONNECTION_CLOSED,
516             stream_->ReadFrames(&frames_, cb_.callback()));
517 }
518 
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncClose)519 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
520   CreateRead(MockRead(ASYNC, "", 0));
521 
522   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
523               IsError(ERR_IO_PENDING));
524   EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
525 }
526 
527 // The result should be the same if the socket returns
528 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established
529 // connection; a Read of size 0 is the expected behaviour. The key point of this
530 // test is to confirm that ReadFrames() behaviour is identical in both cases.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncCloseWithErr)531 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) {
532   CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED));
533 
534   EXPECT_EQ(ERR_CONNECTION_CLOSED,
535             stream_->ReadFrames(&frames_, cb_.callback()));
536 }
537 
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncCloseWithErr)538 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
539   CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
540 
541   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
542               IsError(ERR_IO_PENDING));
543   EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
544 }
545 
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncErrorsPassedThrough)546 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) {
547   // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
548   // WebSocketBasicStream gives no special handling to.
549   CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES));
550 
551   EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
552             stream_->ReadFrames(&frames_, cb_.callback()));
553 }
554 
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncErrorsPassedThrough)555 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
556   CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
557 
558   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
559               IsError(ERR_IO_PENDING));
560   EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_INSUFFICIENT_RESOURCES));
561 }
562 
563 // If we get a frame followed by a close, we should receive them separately.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,CloseAfterFrame)564 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) {
565   // The chunk size equals the data size, so the second chunk is 0 size, closing
566   // the connection.
567   CreateChunkedRead(SYNCHRONOUS,
568                     kSampleFrame,
569                     kSampleFrameSize,
570                     kSampleFrameSize,
571                     2,
572                     LAST_FRAME_NOT_BIG);
573 
574   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
575   EXPECT_EQ(1U, frames_.size());
576   frames_.clear();
577   EXPECT_EQ(ERR_CONNECTION_CLOSED,
578             stream_->ReadFrames(&frames_, cb_.callback()));
579 }
580 
581 // Synchronous close after an async frame header is handled by a different code
582 // path.
TEST_F(WebSocketBasicStreamSocketTest,AsyncCloseAfterIncompleteHeader)583 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
584   MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
585                       MockRead(SYNCHRONOUS, "", 0)};
586   CreateStream(reads, base::span<MockWrite>());
587 
588   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
589               IsError(ERR_IO_PENDING));
590   EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
591 }
592 
593 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
594 // slightly different code path.
TEST_F(WebSocketBasicStreamSocketTest,AsyncErrCloseAfterIncompleteHeader)595 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
596   MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
597                       MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
598   CreateStream(reads, base::span<MockWrite>());
599 
600   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
601               IsError(ERR_IO_PENDING));
602   EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
603 }
604 
605 // An empty first frame is not ignored.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,EmptyFirstFrame)606 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) {
607   CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize));
608 
609   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
610   ASSERT_EQ(1U, frames_.size());
611   EXPECT_EQ(nullptr, frames_[0]->payload);
612   EXPECT_EQ(0U, frames_[0]->header.payload_length);
613 }
614 
615 // An empty frame in the middle of a message is ignored.
TEST_F(WebSocketBasicStreamSocketTest,EmptyMiddleFrame)616 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrame) {
617   MockRead reads[] = {
618       MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
619       MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
620       MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
621   CreateStream(reads, base::span<MockWrite>());
622 
623   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
624   EXPECT_EQ(1U, frames_.size());
625   frames_.clear();
626   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
627               IsError(ERR_IO_PENDING));
628 }
629 
630 // An empty frame in the middle of a message that arrives separately is still
631 // ignored.
TEST_F(WebSocketBasicStreamSocketTest,EmptyMiddleFrameAsync)632 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrameAsync) {
633   MockRead reads[] = {
634       MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
635       MockRead(ASYNC, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
636       // We include a pong message to verify the middle frame was actually
637       // processed.
638       MockRead(ASYNC, kValidPong, kValidPongSize)};
639   CreateStream(reads, base::span<MockWrite>());
640 
641   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
642   EXPECT_EQ(1U, frames_.size());
643   frames_.clear();
644   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
645               IsError(ERR_IO_PENDING));
646   EXPECT_THAT(cb_.WaitForResult(), IsOk());
647   ASSERT_EQ(1U, frames_.size());
648   EXPECT_EQ(WebSocketFrameHeader::kOpCodePong, frames_[0]->header.opcode);
649 }
650 
651 // An empty final frame is not ignored.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,EmptyFinalFrame)652 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) {
653   CreateRead(
654       MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize));
655 
656   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
657   ASSERT_EQ(1U, frames_.size());
658   EXPECT_EQ(nullptr, frames_[0]->payload);
659   EXPECT_EQ(0U, frames_[0]->header.payload_length);
660 }
661 
662 // An empty middle frame is ignored with a final frame present.
TEST_F(WebSocketBasicStreamSocketTest,ThreeFrameEmptyMessage)663 TEST_F(WebSocketBasicStreamSocketTest, ThreeFrameEmptyMessage) {
664   MockRead reads[] = {
665       MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
666       MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
667       MockRead(SYNCHRONOUS,
668                kEmptyFinalContinuationFrame,
669                kEmptyFinalContinuationFrameSize)};
670   CreateStream(reads, base::span<MockWrite>());
671 
672   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
673   ASSERT_EQ(1U, frames_.size());
674   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
675   frames_.clear();
676   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
677   ASSERT_EQ(1U, frames_.size());
678   EXPECT_TRUE(frames_[0]->header.final);
679 }
680 
681 // If there was a frame read at the same time as the response headers (and the
682 // handshake succeeded), then we should parse it.
TEST_F(WebSocketBasicStreamSocketTest,HttpReadBufferIsUsed)683 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
684   SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
685   CreateStream(base::span<MockRead>(), base::span<MockWrite>());
686 
687   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
688   ASSERT_EQ(1U, frames_.size());
689   ASSERT_TRUE(frames_[0]->payload);
690   EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
691 }
692 
693 // Check that a frame whose header partially arrived at the end of the response
694 // headers works correctly.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,PartialFrameHeaderInHttpResponse)695 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
696        PartialFrameHeaderInHttpResponse) {
697   SetHttpReadBuffer(kSampleFrame, 1);
698   CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1));
699 
700   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
701               IsError(ERR_IO_PENDING));
702   EXPECT_THAT(cb_.WaitForResult(), IsOk());
703   ASSERT_EQ(1U, frames_.size());
704   ASSERT_TRUE(frames_[0]->payload);
705   EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
706   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
707 }
708 
709 // Check that a control frame which partially arrives at the end of the response
710 // headers works correctly.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,PartialControlFrameInHttpResponse)711 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
712        PartialControlFrameInHttpResponse) {
713   const size_t kPartialFrameBytes = 3;
714   SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
715   CreateRead(MockRead(ASYNC,
716                       kCloseFrame + kPartialFrameBytes,
717                       kCloseFrameSize - kPartialFrameBytes));
718 
719   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
720               IsError(ERR_IO_PENDING));
721   EXPECT_THAT(cb_.WaitForResult(), IsOk());
722   ASSERT_EQ(1U, frames_.size());
723   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
724   EXPECT_EQ(kCloseFrameSize - 2, frames_[0]->header.payload_length);
725   EXPECT_EQ(std::string(frames_[0]->payload, kCloseFrameSize - 2),
726             std::string(kCloseFrame + 2, kCloseFrameSize - 2));
727 }
728 
729 // Check that a control frame which partially arrives at the end of the response
730 // headers works correctly. Synchronous version (unlikely in practice).
TEST_F(WebSocketBasicStreamSocketSingleReadTest,PartialControlFrameInHttpResponseSync)731 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
732        PartialControlFrameInHttpResponseSync) {
733   const size_t kPartialFrameBytes = 3;
734   SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
735   CreateRead(MockRead(SYNCHRONOUS,
736                       kCloseFrame + kPartialFrameBytes,
737                       kCloseFrameSize - kPartialFrameBytes));
738 
739   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
740   ASSERT_EQ(1U, frames_.size());
741   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
742 }
743 
744 // Check that an invalid frame results in an error.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncInvalidFrame)745 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
746   CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
747 
748   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
749             stream_->ReadFrames(&frames_, cb_.callback()));
750 }
751 
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncInvalidFrame)752 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
753   CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
754 
755   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
756               IsError(ERR_IO_PENDING));
757   EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_WS_PROTOCOL_ERROR));
758 }
759 
760 // A control frame without a FIN flag is invalid and should not be passed
761 // through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be
762 // fragmented."
TEST_F(WebSocketBasicStreamSocketSingleReadTest,ControlFrameWithoutFin)763 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) {
764   CreateRead(
765       MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize));
766 
767   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
768             stream_->ReadFrames(&frames_, cb_.callback()));
769   EXPECT_TRUE(frames_.empty());
770 }
771 
772 // A control frame over 125 characters is invalid. RFC6455 5.5 "All control
773 // frames MUST have a payload length of 125 bytes or less". Since we use a
774 // 125-byte buffer to assemble fragmented control frames, we need to detect this
775 // error before attempting to assemble the fragments.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,OverlongControlFrame)776 TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) {
777   CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize));
778 
779   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
780             stream_->ReadFrames(&frames_, cb_.callback()));
781   EXPECT_TRUE(frames_.empty());
782 }
783 
784 // A control frame over 125 characters should still be rejected if it is split
785 // into multiple chunks.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,SplitOverlongControlFrame)786 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) {
787   const size_t kFirstChunkSize = 16;
788   expect_all_io_to_complete_ = false;
789   CreateChunkedRead(SYNCHRONOUS,
790                     k126BytePong,
791                     k126BytePongSize,
792                     kFirstChunkSize,
793                     2,
794                     LAST_FRAME_BIG);
795 
796   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
797             stream_->ReadFrames(&frames_, cb_.callback()));
798   EXPECT_TRUE(frames_.empty());
799 }
800 
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,AsyncSplitOverlongControlFrame)801 TEST_F(WebSocketBasicStreamSocketChunkedReadTest,
802        AsyncSplitOverlongControlFrame) {
803   const size_t kFirstChunkSize = 16;
804   expect_all_io_to_complete_ = false;
805   CreateChunkedRead(ASYNC,
806                     k126BytePong,
807                     k126BytePongSize,
808                     kFirstChunkSize,
809                     2,
810                     LAST_FRAME_BIG);
811 
812   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
813               IsError(ERR_IO_PENDING));
814   EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_WS_PROTOCOL_ERROR));
815   // The caller should not call ReadFrames() again after receiving an error
816   // other than ERR_IO_PENDING.
817   EXPECT_TRUE(frames_.empty());
818 }
819 
820 // In the synchronous case, ReadFrames assembles the whole control frame before
821 // returning.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,SyncControlFrameAssembly)822 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) {
823   const size_t kChunkSize = 3;
824   CreateChunkedRead(
825       SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
826 
827   EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
828   ASSERT_EQ(1U, frames_.size());
829   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
830 }
831 
832 // In the asynchronous case, the callback is not called until the control frame
833 // has been completely assembled.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,AsyncControlFrameAssembly)834 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) {
835   const size_t kChunkSize = 3;
836   CreateChunkedRead(
837       ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
838 
839   ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
840               IsError(ERR_IO_PENDING));
841   EXPECT_THAT(cb_.WaitForResult(), IsOk());
842   ASSERT_EQ(1U, frames_.size());
843   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
844 }
845 
846 // A frame with a 1MB payload that has to be read in chunks.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,OneMegFrame)847 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OneMegFrame) {
848   // This should be equal to the definition of kSmallReadBufferFrame in
849   // websocket_basic_stream.cc.
850   const int kReadBufferSize = 1000;
851   const uint64_t kPayloadSize = 1 << 20;
852   const size_t kWireSize = kPayloadSize + kLargeFrameHeaderSize;
853   const size_t kExpectedFrameCount =
854       (kWireSize + kReadBufferSize - 1) / kReadBufferSize;
855   auto big_frame = std::make_unique<char[]>(kWireSize);
856   memcpy(big_frame.get(), "\x81\x7F", 2);
857   base::WriteBigEndian(big_frame.get() + 2, kPayloadSize);
858   memset(big_frame.get() + kLargeFrameHeaderSize, 'A', kPayloadSize);
859 
860   CreateChunkedRead(ASYNC,
861                     big_frame.get(),
862                     kWireSize,
863                     kReadBufferSize,
864                     kExpectedFrameCount,
865                     LAST_FRAME_BIG);
866 
867   for (size_t frame = 0; frame < kExpectedFrameCount; ++frame) {
868     frames_.clear();
869     ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
870                 IsError(ERR_IO_PENDING));
871     EXPECT_THAT(cb_.WaitForResult(), IsOk());
872     ASSERT_EQ(1U, frames_.size());
873     size_t expected_payload_size = kReadBufferSize;
874     if (frame == 0) {
875       expected_payload_size = kReadBufferSize - kLargeFrameHeaderSize;
876     } else if (frame == kExpectedFrameCount - 1) {
877       expected_payload_size =
878           kWireSize - kReadBufferSize * (kExpectedFrameCount - 1);
879     }
880     EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length);
881   }
882 }
883 
884 // A frame with reserved flag(s) set that arrives in chunks should only have the
885 // reserved flag(s) set on the first chunk when split.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,ReservedFlagCleared)886 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ReservedFlagCleared) {
887   static const char kReservedFlagFrame[] = "\x41\x05Hello";
888   const size_t kReservedFlagFrameSize = std::size(kReservedFlagFrame) - 1;
889   const size_t kChunkSize = 5;
890 
891   CreateChunkedRead(ASYNC,
892                     kReservedFlagFrame,
893                     kReservedFlagFrameSize,
894                     kChunkSize,
895                     2,
896                     LAST_FRAME_BIG);
897 
898   TestCompletionCallback cb[2];
899   ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
900               IsError(ERR_IO_PENDING));
901   EXPECT_THAT(cb[0].WaitForResult(), IsOk());
902   ASSERT_EQ(1U, frames_.size());
903   EXPECT_TRUE(frames_[0]->header.reserved1);
904 
905   frames_.clear();
906   ASSERT_THAT(stream_->ReadFrames(&frames_, cb[1].callback()),
907               IsError(ERR_IO_PENDING));
908   EXPECT_THAT(cb[1].WaitForResult(), IsOk());
909   ASSERT_EQ(1U, frames_.size());
910   EXPECT_FALSE(frames_[0]->header.reserved1);
911 }
912 
913 // Check that writing a frame all at once works.
TEST_F(WebSocketBasicStreamSocketWriteTest,WriteAtOnce)914 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) {
915   MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
916   CreateStream(base::span<MockRead>(), writes);
917 
918   EXPECT_THAT(stream_->WriteFrames(&frames_, cb_.callback()), IsOk());
919 }
920 
921 // Check that completely async writing works.
TEST_F(WebSocketBasicStreamSocketWriteTest,AsyncWriteAtOnce)922 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
923   MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
924   CreateStream(base::span<MockRead>(), writes);
925 
926   ASSERT_THAT(stream_->WriteFrames(&frames_, cb_.callback()),
927               IsError(ERR_IO_PENDING));
928   EXPECT_THAT(cb_.WaitForResult(), IsOk());
929 }
930 
931 // Check that writing a frame to an extremely full kernel buffer (so that it
932 // ends up being sent in bits) works. The WriteFrames() callback should not be
933 // called until all parts have been written.
TEST_F(WebSocketBasicStreamSocketWriteTest,WriteInBits)934 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) {
935   MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
936                         MockWrite(ASYNC, kWriteFrame + 4, 4),
937                         MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
938   CreateStream(base::span<MockRead>(), writes);
939 
940   ASSERT_THAT(stream_->WriteFrames(&frames_, cb_.callback()),
941               IsError(ERR_IO_PENDING));
942   EXPECT_THAT(cb_.WaitForResult(), IsOk());
943 }
944 
945 // Check that writing a Pong frame with a nullptr body works.
TEST_F(WebSocketBasicStreamSocketWriteTest,WriteNullptrPong)946 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteNullptrPong) {
947   MockWrite writes[] = {
948       MockWrite(SYNCHRONOUS, kMaskedEmptyPong, kMaskedEmptyPongSize)};
949   CreateStream(base::span<MockRead>(), writes);
950 
951   auto frame =
952       std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodePong);
953   WebSocketFrameHeader& header = frame->header;
954   header.final = true;
955   header.masked = true;
956   header.payload_length = 0;
957   std::vector<std::unique_ptr<WebSocketFrame>> frames;
958   frames.push_back(std::move(frame));
959   EXPECT_THAT(stream_->WriteFrames(&frames, cb_.callback()), IsOk());
960 }
961 
962 // Check that writing with a non-nullptr mask works correctly.
TEST_F(WebSocketBasicStreamSocketTest,WriteNonNulMask)963 TEST_F(WebSocketBasicStreamSocketTest, WriteNonNulMask) {
964   std::string masked_frame = std::string("\x81\x88");
965   masked_frame += std::string(kNonNulMaskingKey.key, 4);
966   masked_frame += "jiggered";
967   MockWrite writes[] = {
968       MockWrite(SYNCHRONOUS, masked_frame.data(), masked_frame.size())};
969   generator_ = &GenerateNonNulMaskingKey;
970   CreateStream(base::span<MockRead>(), writes);
971 
972   auto frame =
973       std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodeText);
974   const std::string unmasked_payload = "graphics";
975   const size_t payload_size = unmasked_payload.size();
976   auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_size);
977   memcpy(buffer->data(), unmasked_payload.data(), payload_size);
978   frame->payload = buffer->data();
979   WebSocketFrameHeader& header = frame->header;
980   header.final = true;
981   header.masked = true;
982   header.payload_length = payload_size;
983   frames_.push_back(std::move(frame));
984 
985   EXPECT_THAT(stream_->WriteFrames(&frames_, cb_.callback()), IsOk());
986 }
987 
TEST_F(WebSocketBasicStreamSocketTest,GetExtensionsWorks)988 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
989   extensions_ = "inflate-uuencode";
990   CreateStream(base::span<MockRead>(), base::span<MockWrite>());
991 
992   EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
993 }
994 
TEST_F(WebSocketBasicStreamSocketTest,GetSubProtocolWorks)995 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
996   sub_protocol_ = "cyberchat";
997   CreateStream(base::span<MockRead>(), base::span<MockWrite>());
998 
999   EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
1000 }
1001 
1002 // Check that the read buffer size initialization works correctly.
TEST_F(WebSocketBasicStreamSwitchTest,GetInitialReadBufferSize)1003 TEST_F(WebSocketBasicStreamSwitchTest, GetInitialReadBufferSize) {
1004   EXPECT_EQ(buffer_size_manager_.buffer_size(),
1005             WebSocketBasicStream::BufferSize::kSmall);
1006   buffer_size_manager_.OnRead(MicrosecondsFromStart(0));
1007   EXPECT_EQ(buffer_size_manager_.buffer_size(),
1008             WebSocketBasicStream::BufferSize::kSmall);
1009 }
1010 
1011 // Check that the case where the start time and the end time are the same.
TEST_F(WebSocketBasicStreamSwitchTest,ZeroSecondRead)1012 TEST_F(WebSocketBasicStreamSwitchTest, ZeroSecondRead) {
1013   buffer_size_manager_.set_window_for_test(1);
1014   buffer_size_manager_.OnRead(MicrosecondsFromStart(0));
1015   buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(0), 1000);
1016   EXPECT_EQ(buffer_size_manager_.buffer_size(),
1017             WebSocketBasicStream::BufferSize::kLarge);
1018 }
1019 
1020 // Check that the read buffer size is switched for high throughput connection.
TEST_F(WebSocketBasicStreamSwitchTest,CheckSwitch)1021 TEST_F(WebSocketBasicStreamSwitchTest, CheckSwitch) {
1022   buffer_size_manager_.set_window_for_test(4);
1023   // It tests the case where 4000 bytes data is read in 2000 ms. In this case,
1024   // the read buffer size should be switched to the large one.
1025   buffer_size_manager_.OnRead(MicrosecondsFromStart(0));
1026   buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(200), 1000);
1027   buffer_size_manager_.OnRead(MicrosecondsFromStart(800));
1028   buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(1000), 1000);
1029   buffer_size_manager_.OnRead(MicrosecondsFromStart(1300));
1030   buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(1500), 1000);
1031   buffer_size_manager_.OnRead(MicrosecondsFromStart(1800));
1032   buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(2000), 1000);
1033   EXPECT_EQ(buffer_size_manager_.buffer_size(),
1034             WebSocketBasicStream::BufferSize::kLarge);
1035 }
1036 
1037 }  // namespace
1038 }  // namespace net
1039