websocket_basic_stream_test.cc 41 KB

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