blob: b735cc8269964e2655b4133b22d9b2eb12ff3d32 [file] [log] [blame]
[email protected]999bcaa2013-07-17 13:42:541// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/websockets/websocket_channel.h"
6
[email protected]4256dbb2014-03-24 15:39:367#include <limits.h>
ricea5858a5052016-01-06 04:57:388#include <stddef.h>
[email protected]c0d29c22013-07-26 20:40:419#include <string.h>
danakj9c5cab52016-04-16 00:54:3310
riceab1989b92017-06-20 12:48:5011#include <algorithm>
[email protected]999bcaa2013-07-17 13:42:5412#include <iostream>
yhirano592ff7f2015-12-07 08:45:1913#include <iterator>
[email protected]999bcaa2013-07-17 13:42:5414#include <string>
yhirano592ff7f2015-12-07 08:45:1915#include <utility>
[email protected]999bcaa2013-07-17 13:42:5416#include <vector>
17
18#include "base/bind.h"
19#include "base/bind_helpers.h"
20#include "base/callback.h"
Bence Békyf4f56e22018-07-17 02:00:0521#include "base/callback_helpers.h"
[email protected]c0d29c22013-07-26 20:40:4122#include "base/location.h"
[email protected]f485985e2013-10-24 13:47:4423#include "base/memory/weak_ptr.h"
fdoray92e35a72016-06-10 15:54:5524#include "base/run_loop.h"
skyostil4891b25b2015-06-11 11:43:4525#include "base/single_thread_task_runner.h"
Avi Drissman4365a4782018-12-28 19:26:2426#include "base/stl_util.h"
[email protected]999bcaa2013-07-17 13:42:5427#include "base/strings/string_piece.h"
gabf767595f2016-05-11 18:50:3528#include "base/threading/thread_task_runner_handle.h"
Bence Békyf4f56e22018-07-17 02:00:0529#include "net/base/completion_once_callback.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3730#include "net/base/ip_endpoint.h"
[email protected]999bcaa2013-07-17 13:42:5431#include "net/base/net_errors.h"
[email protected]3a266762013-10-23 08:15:1032#include "net/base/test_completion_callback.h"
Yutaka Hirano2f65eec2018-05-23 01:58:2233#include "net/http/http_request_headers.h"
[email protected]cd48ed12014-01-22 14:34:2234#include "net/http/http_response_headers.h"
mikecironef22f9812016-10-04 03:40:1935#include "net/log/net_log_with_source.h"
Bence Béky98447b12018-05-08 03:14:0136#include "net/test/test_with_scoped_task_environment.h"
[email protected]999bcaa2013-07-17 13:42:5437#include "net/url_request/url_request_context.h"
38#include "net/websockets/websocket_errors.h"
39#include "net/websockets/websocket_event_interface.h"
[email protected]cd48ed12014-01-22 14:34:2240#include "net/websockets/websocket_handshake_request_info.h"
41#include "net/websockets/websocket_handshake_response_info.h"
[email protected]999bcaa2013-07-17 13:42:5442#include "testing/gmock/include/gmock/gmock.h"
43#include "testing/gtest/include/gtest/gtest.h"
[email protected]15fbdb42013-07-20 00:09:3844#include "url/gurl.h"
mkwst4997ce82015-07-25 12:00:0545#include "url/origin.h"
[email protected]999bcaa2013-07-17 13:42:5446
[email protected]c0d29c22013-07-26 20:40:4147// Hacky macros to construct the body of a Close message from a code and a
48// string, while ensuring the result is a compile-time constant string.
49// Use like CLOSE_DATA(NORMAL_CLOSURE, "Explanation String")
50#define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string
51#define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8"
52#define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9"
[email protected]2f5d9f62013-09-26 12:14:2853#define WEBSOCKET_CLOSE_CODE_AS_STRING_PROTOCOL_ERROR "\x03\xea"
[email protected]ea56b982014-01-27 03:21:0354#define WEBSOCKET_CLOSE_CODE_AS_STRING_ABNORMAL_CLOSURE "\x03\xee"
[email protected]c0d29c22013-07-26 20:40:4155#define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3"
56
[email protected]999bcaa2013-07-17 13:42:5457namespace net {
58
Adam Rice6f75c0f2018-06-04 08:00:0559class WebSocketBasicHandshakeStream;
60class WebSocketHttp2HandshakeStream;
61
[email protected]2f5d9f62013-09-26 12:14:2862// Printing helpers to allow GoogleMock to print frames. These are explicitly
63// designed to look like the static initialisation format we use in these
64// tests. They have to live in the net namespace in order to be found by
[email protected]999bcaa2013-07-17 13:42:5465// GoogleMock; a nested anonymous namespace will not work.
66
67std::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) {
[email protected]2f5d9f62013-09-26 12:14:2868 return os << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
[email protected]999bcaa2013-07-17 13:42:5469 << header.opcode << ", "
[email protected]2f5d9f62013-09-26 12:14:2870 << (header.masked ? "MASKED" : "NOT_MASKED");
[email protected]999bcaa2013-07-17 13:42:5471}
72
[email protected]2f5d9f62013-09-26 12:14:2873std::ostream& operator<<(std::ostream& os, const WebSocketFrame& frame) {
74 os << "{" << frame.header << ", ";
dchengb206dc412014-08-26 19:46:2375 if (frame.data.get()) {
[email protected]2f5d9f62013-09-26 12:14:2876 return os << "\"" << base::StringPiece(frame.data->data(),
77 frame.header.payload_length)
78 << "\"}";
[email protected]999bcaa2013-07-17 13:42:5479 }
[email protected]2f5d9f62013-09-26 12:14:2880 return os << "NULL}";
[email protected]c0d29c22013-07-26 20:40:4181}
82
yhirano592ff7f2015-12-07 08:45:1983std::ostream& operator<<(
84 std::ostream& os,
danakj9c5cab52016-04-16 00:54:3385 const std::vector<std::unique_ptr<WebSocketFrame>>& frames) {
[email protected]c0d29c22013-07-26 20:40:4186 os << "{";
87 bool first = true;
yhirano592ff7f2015-12-07 08:45:1988 for (const auto& frame : frames) {
[email protected]c0d29c22013-07-26 20:40:4189 if (!first) {
90 os << ",\n";
91 } else {
92 first = false;
93 }
yhirano592ff7f2015-12-07 08:45:1994 os << *frame;
[email protected]c0d29c22013-07-26 20:40:4195 }
96 return os << "}";
97}
98
yhirano592ff7f2015-12-07 08:45:1999std::ostream& operator<<(
100 std::ostream& os,
danakj9c5cab52016-04-16 00:54:33101 const std::vector<std::unique_ptr<WebSocketFrame>>* vector) {
[email protected]c0d29c22013-07-26 20:40:41102 return os << '&' << *vector;
[email protected]999bcaa2013-07-17 13:42:54103}
104
105namespace {
106
[email protected]3a266762013-10-23 08:15:10107using ::base::TimeDelta;
108
[email protected]999bcaa2013-07-17 13:42:54109using ::testing::AnyNumber;
[email protected]f485985e2013-10-24 13:47:44110using ::testing::DefaultValue;
[email protected]999bcaa2013-07-17 13:42:54111using ::testing::InSequence;
112using ::testing::MockFunction;
[email protected]a62449522014-06-05 11:11:15113using ::testing::NotNull;
[email protected]999bcaa2013-07-17 13:42:54114using ::testing::Return;
[email protected]c0d29c22013-07-26 20:40:41115using ::testing::SaveArg;
[email protected]999bcaa2013-07-17 13:42:54116using ::testing::StrictMock;
117using ::testing::_;
118
[email protected]c0d29c22013-07-26 20:40:41119// A selection of characters that have traditionally been mangled in some
120// environment or other, for testing 8-bit cleanliness.
[email protected]2f5d9f62013-09-26 12:14:28121const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
[email protected]c0d29c22013-07-26 20:40:41122 '\0', // nul
123 '\x7F', // DEL
124 '\x80', '\xFF', // NOT VALID UTF-8
125 '\x1A', // Control-Z, EOF on DOS
126 '\x03', // Control-C
127 '\x04', // EOT, special for Unix terms
128 '\x1B', // ESC, often special
129 '\b', // backspace
130 '\'', // single-quote, special in PHP
131};
Avi Drissman4365a4782018-12-28 19:26:24132const size_t kBinaryBlobSize = base::size(kBinaryBlob);
[email protected]c0d29c22013-07-26 20:40:41133
134// The amount of quota a new connection gets by default.
135// TODO(ricea): If kDefaultSendQuotaHighWaterMark changes, then this value will
136// need to be updated.
137const size_t kDefaultInitialQuota = 1 << 17;
138// The amount of bytes we need to send after the initial connection to trigger a
139// quota refresh. TODO(ricea): Change this if kDefaultSendQuotaHighWaterMark or
140// kDefaultSendQuotaLowWaterMark change.
141const size_t kDefaultQuotaRefreshTrigger = (1 << 16) + 1;
142
tyoshinod4d1d302014-11-07 04:31:16143const int kVeryBigTimeoutMillis = 60 * 60 * 24 * 1000;
144
[email protected]3a266762013-10-23 08:15:10145// TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world
146// in that time! I would like my tests to run a bit quicker.
147const int kVeryTinyTimeoutMillis = 1;
148
[email protected]4256dbb2014-03-24 15:39:36149// Enough quota to pass any test.
tfarina8a2c66c22015-10-13 19:14:49150const int64_t kPlentyOfQuota = INT_MAX;
[email protected]4256dbb2014-03-24 15:39:36151
Yutaka Hirano4165de92018-04-10 11:46:49152using ChannelState = WebSocketChannel::ChannelState;
153constexpr ChannelState CHANNEL_ALIVE = WebSocketChannel::CHANNEL_ALIVE;
154constexpr ChannelState CHANNEL_DELETED = WebSocketChannel::CHANNEL_DELETED;
[email protected]f485985e2013-10-24 13:47:44155
156// This typedef mainly exists to avoid having to repeat the "NOLINT" incantation
157// all over the place.
[email protected]4256dbb2014-03-24 15:39:36158typedef StrictMock< MockFunction<void(int)> > Checkpoint; // NOLINT
[email protected]f485985e2013-10-24 13:47:44159
[email protected]999bcaa2013-07-17 13:42:54160// This mock is for testing expectations about how the EventInterface is used.
161class MockWebSocketEventInterface : public WebSocketEventInterface {
162 public:
Chris Watkins28c2fdd2017-11-30 06:06:52163 MockWebSocketEventInterface() = default;
[email protected]cd48ed12014-01-22 14:34:22164
Yutaka Hirano4165de92018-04-10 11:46:49165 void OnDataFrame(bool fin,
166 WebSocketMessageType type,
167 scoped_refptr<IOBuffer> buffer,
168 size_t buffer_size) override {
darin0da77e922016-10-04 17:31:23169 const char* data = buffer ? buffer->data() : nullptr;
170 return OnDataFrameVector(fin, type,
171 std::vector<char>(data, data + buffer_size));
172 }
173
yhirano4a593832016-10-24 18:58:22174 MOCK_METHOD1(OnCreateURLRequest, void(URLRequest*));
tyoshinoc06da562015-03-06 06:02:42175 MOCK_METHOD2(OnAddChannelResponse,
Yutaka Hirano4165de92018-04-10 11:46:49176 void(const std::string&,
177 const std::string&)); // NOLINT
darin0da77e922016-10-04 17:31:23178 MOCK_METHOD3(OnDataFrameVector,
Yutaka Hirano4165de92018-04-10 11:46:49179 void(bool,
180 WebSocketMessageType,
181 const std::vector<char>&)); // NOLINT
Yoichi Osatob088adc2019-06-06 05:52:19182 MOCK_METHOD1(OnSendFlowControlQuotaAdded, void(int64_t)); // NOLINT
Yutaka Hirano4165de92018-04-10 11:46:49183 MOCK_METHOD0(OnClosingHandshake, void(void)); // NOLINT
184 MOCK_METHOD1(OnFailChannel, void(const std::string&)); // NOLINT
[email protected]86ec55502014-02-10 13:16:16185 MOCK_METHOD3(OnDropChannel,
Yutaka Hirano4165de92018-04-10 11:46:49186 void(bool, uint16_t, const std::string&)); // NOLINT
[email protected]cd48ed12014-01-22 14:34:22187
Yutaka Hirano4165de92018-04-10 11:46:49188 // We can't use GMock with std::unique_ptr.
189 void OnStartOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33190 std::unique_ptr<WebSocketHandshakeRequestInfo>) override {
[email protected]cd48ed12014-01-22 14:34:22191 OnStartOpeningHandshakeCalled();
[email protected]cd48ed12014-01-22 14:34:22192 }
Yutaka Hirano4165de92018-04-10 11:46:49193 void OnFinishOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33194 std::unique_ptr<WebSocketHandshakeResponseInfo>) override {
[email protected]cd48ed12014-01-22 14:34:22195 OnFinishOpeningHandshakeCalled();
[email protected]cd48ed12014-01-22 14:34:22196 }
Yutaka Hirano4165de92018-04-10 11:46:49197 void OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33198 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
[email protected]a62449522014-06-05 11:11:15199 const GURL& url,
Emily Starkd9df3d32019-04-29 17:54:57200 int net_error,
[email protected]a62449522014-06-05 11:11:15201 const SSLInfo& ssl_info,
mostynbba063d6032014-10-09 11:01:13202 bool fatal) override {
[email protected]a62449522014-06-05 11:11:15203 OnSSLCertificateErrorCalled(
204 ssl_error_callbacks.get(), url, ssl_info, fatal);
[email protected]a62449522014-06-05 11:11:15205 }
Emily Starkf2c9bbd2019-04-09 17:08:58206 int OnAuthRequired(const AuthChallengeInfo& auth_info,
Yutaka Hirano70fa25912018-06-06 05:26:54207 scoped_refptr<HttpResponseHeaders> response_headers,
Tsuyoshi Horo01faed62019-02-20 22:11:37208 const IPEndPoint& remote_endpoint,
Yutaka Hirano70fa25912018-06-06 05:26:54209 base::OnceCallback<void(const AuthCredentials*)> callback,
210 base::Optional<AuthCredentials>* credentials) override {
211 return OnAuthRequiredCalled(std::move(auth_info),
Tsuyoshi Horo01faed62019-02-20 22:11:37212 std::move(response_headers), remote_endpoint,
Yutaka Hirano70fa25912018-06-06 05:26:54213 credentials);
214 }
[email protected]cd48ed12014-01-22 14:34:22215
216 MOCK_METHOD0(OnStartOpeningHandshakeCalled, void()); // NOLINT
217 MOCK_METHOD0(OnFinishOpeningHandshakeCalled, void()); // NOLINT
[email protected]a62449522014-06-05 11:11:15218 MOCK_METHOD4(
219 OnSSLCertificateErrorCalled,
220 void(SSLErrorCallbacks*, const GURL&, const SSLInfo&, bool)); // NOLINT
Yutaka Hirano70fa25912018-06-06 05:26:54221 MOCK_METHOD4(OnAuthRequiredCalled,
Emily Starkf2c9bbd2019-04-09 17:08:58222 int(const AuthChallengeInfo&,
Yutaka Hirano70fa25912018-06-06 05:26:54223 scoped_refptr<HttpResponseHeaders>,
Tsuyoshi Horo01faed62019-02-20 22:11:37224 const IPEndPoint&,
Yutaka Hirano70fa25912018-06-06 05:26:54225 base::Optional<AuthCredentials>*));
[email protected]999bcaa2013-07-17 13:42:54226};
227
228// This fake EventInterface is for tests which need a WebSocketEventInterface
229// implementation but are not verifying how it is used.
230class FakeWebSocketEventInterface : public WebSocketEventInterface {
yhirano4a593832016-10-24 18:58:22231 void OnCreateURLRequest(URLRequest* request) override {}
Yutaka Hirano4165de92018-04-10 11:46:49232 void OnAddChannelResponse(const std::string& selected_protocol,
233 const std::string& extensions) override {}
234 void OnDataFrame(bool fin,
235 WebSocketMessageType type,
236 scoped_refptr<IOBuffer> data,
237 size_t data_size) override {}
Yoichi Osatob088adc2019-06-06 05:52:19238 void OnSendFlowControlQuotaAdded(int64_t quota) override {}
Yutaka Hirano4165de92018-04-10 11:46:49239 void OnClosingHandshake() override {}
240 void OnFailChannel(const std::string& message) override {}
241 void OnDropChannel(bool was_clean,
242 uint16_t code,
243 const std::string& reason) override {}
244 void OnStartOpeningHandshake(
245 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {}
246 void OnFinishOpeningHandshake(
247 std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {}
248 void OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33249 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
[email protected]a62449522014-06-05 11:11:15250 const GURL& url,
Emily Starkd9df3d32019-04-29 17:54:57251 int net_error,
[email protected]a62449522014-06-05 11:11:15252 const SSLInfo& ssl_info,
Yutaka Hirano4165de92018-04-10 11:46:49253 bool fatal) override {}
Emily Starkf2c9bbd2019-04-09 17:08:58254 int OnAuthRequired(const AuthChallengeInfo& auth_info,
Yutaka Hirano70fa25912018-06-06 05:26:54255 scoped_refptr<HttpResponseHeaders> response_headers,
Tsuyoshi Horo01faed62019-02-20 22:11:37256 const IPEndPoint& remote_endpoint,
Yutaka Hirano70fa25912018-06-06 05:26:54257 base::OnceCallback<void(const AuthCredentials*)> callback,
258 base::Optional<AuthCredentials>* credentials) override {
259 *credentials = base::nullopt;
260 return OK;
261 }
[email protected]999bcaa2013-07-17 13:42:54262};
263
264// This fake WebSocketStream is for tests that require a WebSocketStream but are
265// not testing the way it is used. It has minimal functionality to return
266// the |protocol| and |extensions| that it was constructed with.
267class FakeWebSocketStream : public WebSocketStream {
268 public:
269 // Constructs with empty protocol and extensions.
Chris Watkins28c2fdd2017-11-30 06:06:52270 FakeWebSocketStream() = default;
[email protected]999bcaa2013-07-17 13:42:54271
272 // Constructs with specified protocol and extensions.
273 FakeWebSocketStream(const std::string& protocol,
274 const std::string& extensions)
275 : protocol_(protocol), extensions_(extensions) {}
276
danakj9c5cab52016-04-16 00:54:33277 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05278 CompletionOnceCallback callback) override {
[email protected]999bcaa2013-07-17 13:42:54279 return ERR_IO_PENDING;
280 }
281
danakj9c5cab52016-04-16 00:54:33282 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05283 CompletionOnceCallback callback) override {
[email protected]999bcaa2013-07-17 13:42:54284 return ERR_IO_PENDING;
285 }
286
dchengb03027d2014-10-21 12:00:20287 void Close() override {}
[email protected]999bcaa2013-07-17 13:42:54288
289 // Returns the string passed to the constructor.
dchengb03027d2014-10-21 12:00:20290 std::string GetSubProtocol() const override { return protocol_; }
[email protected]999bcaa2013-07-17 13:42:54291
292 // Returns the string passed to the constructor.
dchengb03027d2014-10-21 12:00:20293 std::string GetExtensions() const override { return extensions_; }
[email protected]999bcaa2013-07-17 13:42:54294
295 private:
296 // The string to return from GetSubProtocol().
297 std::string protocol_;
298
299 // The string to return from GetExtensions().
300 std::string extensions_;
301};
302
303// To make the static initialisers easier to read, we use enums rather than
304// bools.
[email protected]ea56b982014-01-27 03:21:03305enum IsFinal { NOT_FINAL_FRAME, FINAL_FRAME };
[email protected]999bcaa2013-07-17 13:42:54306
[email protected]ea56b982014-01-27 03:21:03307enum IsMasked { NOT_MASKED, MASKED };
[email protected]999bcaa2013-07-17 13:42:54308
[email protected]2f5d9f62013-09-26 12:14:28309// This is used to initialise a WebSocketFrame but is statically initialisable.
310struct InitFrame {
311 IsFinal final;
312 // Reserved fields omitted for now. Add them if you need them.
313 WebSocketFrameHeader::OpCode opcode;
314 IsMasked masked;
[email protected]999bcaa2013-07-17 13:42:54315
danakj9c5cab52016-04-16 00:54:33316 // Will be used to create the IOBuffer member. Can be null for null data. Is a
[email protected]2f5d9f62013-09-26 12:14:28317 // nul-terminated string for ease-of-use. |header.payload_length| is
318 // initialised from |strlen(data)|. This means it is not 8-bit clean, but this
319 // is not an issue for test data.
[email protected]999bcaa2013-07-17 13:42:54320 const char* const data;
321};
322
[email protected]c0d29c22013-07-26 20:40:41323// For GoogleMock
[email protected]2f5d9f62013-09-26 12:14:28324std::ostream& operator<<(std::ostream& os, const InitFrame& frame) {
325 os << "{" << (frame.final == FINAL_FRAME ? "FINAL_FRAME" : "NOT_FINAL_FRAME")
326 << ", " << frame.opcode << ", "
327 << (frame.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", ";
328 if (frame.data) {
329 return os << "\"" << frame.data << "\"}";
[email protected]c0d29c22013-07-26 20:40:41330 }
[email protected]2f5d9f62013-09-26 12:14:28331 return os << "NULL}";
[email protected]c0d29c22013-07-26 20:40:41332}
333
334template <size_t N>
[email protected]2f5d9f62013-09-26 12:14:28335std::ostream& operator<<(std::ostream& os, const InitFrame (&frames)[N]) {
[email protected]c0d29c22013-07-26 20:40:41336 os << "{";
337 bool first = true;
338 for (size_t i = 0; i < N; ++i) {
339 if (!first) {
340 os << ",\n";
341 } else {
342 first = false;
343 }
[email protected]2f5d9f62013-09-26 12:14:28344 os << frames[i];
[email protected]c0d29c22013-07-26 20:40:41345 }
346 return os << "}";
347}
348
[email protected]2f5d9f62013-09-26 12:14:28349// Convert a const array of InitFrame structs to the format used at
[email protected]999bcaa2013-07-17 13:42:54350// runtime. Templated on the size of the array to save typing.
351template <size_t N>
danakj9c5cab52016-04-16 00:54:33352std::vector<std::unique_ptr<WebSocketFrame>> CreateFrameVector(
353 const InitFrame (&source_frames)[N]) {
354 std::vector<std::unique_ptr<WebSocketFrame>> result_frames;
[email protected]2f5d9f62013-09-26 12:14:28355 result_frames.reserve(N);
[email protected]999bcaa2013-07-17 13:42:54356 for (size_t i = 0; i < N; ++i) {
[email protected]2f5d9f62013-09-26 12:14:28357 const InitFrame& source_frame = source_frames[i];
Bence Béky65623972018-03-05 15:31:56358 auto result_frame = std::make_unique<WebSocketFrame>(source_frame.opcode);
[email protected]2f5d9f62013-09-26 12:14:28359 size_t frame_length = source_frame.data ? strlen(source_frame.data) : 0;
360 WebSocketFrameHeader& result_header = result_frame->header;
361 result_header.final = (source_frame.final == FINAL_FRAME);
362 result_header.masked = (source_frame.masked == MASKED);
363 result_header.payload_length = frame_length;
364 if (source_frame.data) {
Bence Béky65623972018-03-05 15:31:56365 result_frame->data = base::MakeRefCounted<IOBuffer>(frame_length);
[email protected]2f5d9f62013-09-26 12:14:28366 memcpy(result_frame->data->data(), source_frame.data, frame_length);
[email protected]999bcaa2013-07-17 13:42:54367 }
dchengc7eeda422015-12-26 03:56:48368 result_frames.push_back(std::move(result_frame));
[email protected]999bcaa2013-07-17 13:42:54369 }
yhirano592ff7f2015-12-07 08:45:19370 return result_frames;
[email protected]999bcaa2013-07-17 13:42:54371}
372
373// A GoogleMock action which can be used to respond to call to ReadFrames with
[email protected]2f5d9f62013-09-26 12:14:28374// some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames));
375// |frames| is an array of InitFrame. |frames| needs to be passed by pointer
376// because otherwise it will be treated as a pointer and the array size
377// information will be lost.
378ACTION_P(ReturnFrames, source_frames) {
379 *arg0 = CreateFrameVector(*source_frames);
[email protected]999bcaa2013-07-17 13:42:54380 return OK;
381}
382
[email protected]c0d29c22013-07-26 20:40:41383// The implementation of a GoogleMock matcher which can be used to compare a
danakj9c5cab52016-04-16 00:54:33384// std::vector<std::unique_ptr<WebSocketFrame>>* against an expectation defined
385// as an
yhirano592ff7f2015-12-07 08:45:19386// array of InitFrame objects. Although it is possible to compose built-in
387// GoogleMock matchers to check the contents of a WebSocketFrame, the results
388// are so unreadable that it is better to use this matcher.
[email protected]c0d29c22013-07-26 20:40:41389template <size_t N>
yhirano592ff7f2015-12-07 08:45:19390class EqualsFramesMatcher : public ::testing::MatcherInterface<
danakj9c5cab52016-04-16 00:54:33391 std::vector<std::unique_ptr<WebSocketFrame>>*> {
[email protected]c0d29c22013-07-26 20:40:41392 public:
riceab1989b92017-06-20 12:48:50393 explicit EqualsFramesMatcher(const InitFrame (*expect_frames)[N])
[email protected]2f5d9f62013-09-26 12:14:28394 : expect_frames_(expect_frames) {}
[email protected]c0d29c22013-07-26 20:40:41395
yhirano592ff7f2015-12-07 08:45:19396 virtual bool MatchAndExplain(
danakj9c5cab52016-04-16 00:54:33397 std::vector<std::unique_ptr<WebSocketFrame>>* actual_frames,
yhirano592ff7f2015-12-07 08:45:19398 ::testing::MatchResultListener* listener) const {
[email protected]2f5d9f62013-09-26 12:14:28399 if (actual_frames->size() != N) {
400 *listener << "the vector size is " << actual_frames->size();
[email protected]c0d29c22013-07-26 20:40:41401 return false;
402 }
403 for (size_t i = 0; i < N; ++i) {
[email protected]2f5d9f62013-09-26 12:14:28404 const WebSocketFrame& actual_frame = *(*actual_frames)[i];
405 const InitFrame& expected_frame = (*expect_frames_)[i];
406 if (actual_frame.header.final != (expected_frame.final == FINAL_FRAME)) {
407 *listener << "the frame is marked as "
408 << (actual_frame.header.final ? "" : "not ") << "final";
[email protected]c0d29c22013-07-26 20:40:41409 return false;
410 }
[email protected]2f5d9f62013-09-26 12:14:28411 if (actual_frame.header.opcode != expected_frame.opcode) {
412 *listener << "the opcode is " << actual_frame.header.opcode;
[email protected]c0d29c22013-07-26 20:40:41413 return false;
414 }
[email protected]2f5d9f62013-09-26 12:14:28415 if (actual_frame.header.masked != (expected_frame.masked == MASKED)) {
416 *listener << "the frame is "
417 << (actual_frame.header.masked ? "masked" : "not masked");
[email protected]c0d29c22013-07-26 20:40:41418 return false;
419 }
[email protected]2f5d9f62013-09-26 12:14:28420 const size_t expected_length =
421 expected_frame.data ? strlen(expected_frame.data) : 0;
422 if (actual_frame.header.payload_length != expected_length) {
423 *listener << "the payload length is "
424 << actual_frame.header.payload_length;
425 return false;
426 }
427 if (expected_length != 0 &&
428 memcmp(actual_frame.data->data(),
429 expected_frame.data,
430 actual_frame.header.payload_length) != 0) {
[email protected]c0d29c22013-07-26 20:40:41431 *listener << "the data content differs";
432 return false;
433 }
434 }
435 return true;
436 }
437
438 virtual void DescribeTo(std::ostream* os) const {
[email protected]2f5d9f62013-09-26 12:14:28439 *os << "matches " << *expect_frames_;
[email protected]c0d29c22013-07-26 20:40:41440 }
441
442 virtual void DescribeNegationTo(std::ostream* os) const {
[email protected]2f5d9f62013-09-26 12:14:28443 *os << "does not match " << *expect_frames_;
[email protected]c0d29c22013-07-26 20:40:41444 }
445
446 private:
[email protected]2f5d9f62013-09-26 12:14:28447 const InitFrame (*expect_frames_)[N];
[email protected]c0d29c22013-07-26 20:40:41448};
449
[email protected]2f5d9f62013-09-26 12:14:28450// The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames
[email protected]c0d29c22013-07-26 20:40:41451// action, this can take the array by reference.
452template <size_t N>
danakj9c5cab52016-04-16 00:54:33453::testing::Matcher<std::vector<std::unique_ptr<WebSocketFrame>>*> EqualsFrames(
454 const InitFrame (&frames)[N]) {
[email protected]2f5d9f62013-09-26 12:14:28455 return ::testing::MakeMatcher(new EqualsFramesMatcher<N>(&frames));
[email protected]c0d29c22013-07-26 20:40:41456}
457
[email protected]3a266762013-10-23 08:15:10458// A GoogleMock action to run a Closure.
459ACTION_P(InvokeClosure, closure) { closure.Run(); }
460
[email protected]999bcaa2013-07-17 13:42:54461// A FakeWebSocketStream whose ReadFrames() function returns data.
462class ReadableFakeWebSocketStream : public FakeWebSocketStream {
463 public:
[email protected]ea56b982014-01-27 03:21:03464 enum IsSync { SYNC, ASYNC };
[email protected]999bcaa2013-07-17 13:42:54465
466 // After constructing the object, call PrepareReadFrames() once for each
467 // time you wish it to return from the test.
468 ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {}
469
470 // Check that all the prepared responses have been consumed.
dchengb03027d2014-10-21 12:00:20471 ~ReadableFakeWebSocketStream() override {
[email protected]999bcaa2013-07-17 13:42:54472 CHECK(index_ >= responses_.size());
473 CHECK(!read_frames_pending_);
474 }
475
[email protected]2f5d9f62013-09-26 12:14:28476 // Prepares a fake response. Fake responses will be returned from ReadFrames()
477 // in the same order they were prepared with PrepareReadFrames() and
478 // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
[email protected]999bcaa2013-07-17 13:42:54479 // return ERR_IO_PENDING and the callback will be scheduled to run on the
480 // message loop. This requires the test case to run the message loop. If
481 // |async| is SYNC, the response will be returned synchronously. |error| is
482 // returned directly from ReadFrames() in the synchronous case, or passed to
[email protected]2f5d9f62013-09-26 12:14:28483 // the callback in the asynchronous case. |frames| will be converted to a
danakj9c5cab52016-04-16 00:54:33484 // std::vector<std::unique_ptr<WebSocketFrame>> and copied to the pointer that
485 // was
yhirano592ff7f2015-12-07 08:45:19486 // passed to ReadFrames().
[email protected]999bcaa2013-07-17 13:42:54487 template <size_t N>
488 void PrepareReadFrames(IsSync async,
489 int error,
[email protected]2f5d9f62013-09-26 12:14:28490 const InitFrame (&frames)[N]) {
ricea2deef682016-09-09 08:04:07491 responses_.push_back(
Jeremy Roman0579ed62017-08-29 15:56:19492 std::make_unique<Response>(async, error, CreateFrameVector(frames)));
[email protected]999bcaa2013-07-17 13:42:54493 }
494
[email protected]c0d29c22013-07-26 20:40:41495 // An alternate version of PrepareReadFrames for when we need to construct
496 // the frames manually.
danakj9c5cab52016-04-16 00:54:33497 void PrepareRawReadFrames(
498 IsSync async,
499 int error,
500 std::vector<std::unique_ptr<WebSocketFrame>> frames) {
yhirano592ff7f2015-12-07 08:45:19501 responses_.push_back(
Jeremy Roman0579ed62017-08-29 15:56:19502 std::make_unique<Response>(async, error, std::move(frames)));
[email protected]c0d29c22013-07-26 20:40:41503 }
504
[email protected]999bcaa2013-07-17 13:42:54505 // Prepares a fake error response (ie. there is no data).
506 void PrepareReadFramesError(IsSync async, int error) {
Jeremy Roman0579ed62017-08-29 15:56:19507 responses_.push_back(std::make_unique<Response>(
ricea2deef682016-09-09 08:04:07508 async, error, std::vector<std::unique_ptr<WebSocketFrame>>()));
[email protected]999bcaa2013-07-17 13:42:54509 }
510
danakj9c5cab52016-04-16 00:54:33511 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05512 CompletionOnceCallback callback) override {
[email protected]999bcaa2013-07-17 13:42:54513 CHECK(!read_frames_pending_);
514 if (index_ >= responses_.size())
515 return ERR_IO_PENDING;
516 if (responses_[index_]->async == ASYNC) {
517 read_frames_pending_ = true;
skyostil4891b25b2015-06-11 11:43:45518 base::ThreadTaskRunnerHandle::Get()->PostTask(
Bence Békyf4f56e22018-07-17 02:00:05519 FROM_HERE,
520 base::BindOnce(&ReadableFakeWebSocketStream::DoCallback,
521 base::Unretained(this), frames, std::move(callback)));
[email protected]999bcaa2013-07-17 13:42:54522 return ERR_IO_PENDING;
523 } else {
[email protected]2f5d9f62013-09-26 12:14:28524 frames->swap(responses_[index_]->frames);
[email protected]999bcaa2013-07-17 13:42:54525 return responses_[index_++]->error;
526 }
527 }
528
529 private:
danakj9c5cab52016-04-16 00:54:33530 void DoCallback(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05531 CompletionOnceCallback callback) {
[email protected]999bcaa2013-07-17 13:42:54532 read_frames_pending_ = false;
[email protected]2f5d9f62013-09-26 12:14:28533 frames->swap(responses_[index_]->frames);
Bence Békyf4f56e22018-07-17 02:00:05534 std::move(callback).Run(responses_[index_++]->error);
[email protected]999bcaa2013-07-17 13:42:54535 return;
536 }
537
538 struct Response {
yhirano592ff7f2015-12-07 08:45:19539 Response(IsSync async,
540 int error,
danakj9c5cab52016-04-16 00:54:33541 std::vector<std::unique_ptr<WebSocketFrame>> frames)
yhirano592ff7f2015-12-07 08:45:19542 : async(async), error(error), frames(std::move(frames)) {}
[email protected]999bcaa2013-07-17 13:42:54543
544 IsSync async;
545 int error;
danakj9c5cab52016-04-16 00:54:33546 std::vector<std::unique_ptr<WebSocketFrame>> frames;
[email protected]999bcaa2013-07-17 13:42:54547
548 private:
[email protected]2f5d9f62013-09-26 12:14:28549 // Bad things will happen if we attempt to copy or assign |frames|.
[email protected]999bcaa2013-07-17 13:42:54550 DISALLOW_COPY_AND_ASSIGN(Response);
551 };
danakj9c5cab52016-04-16 00:54:33552 std::vector<std::unique_ptr<Response>> responses_;
[email protected]999bcaa2013-07-17 13:42:54553
554 // The index into the responses_ array of the next response to be returned.
555 size_t index_;
556
557 // True when an async response from ReadFrames() is pending. This only applies
558 // to "real" async responses. Once all the prepared responses have been
559 // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is
560 // not set to true.
561 bool read_frames_pending_;
562};
563
564// A FakeWebSocketStream where writes always complete successfully and
565// synchronously.
566class WriteableFakeWebSocketStream : public FakeWebSocketStream {
567 public:
danakj9c5cab52016-04-16 00:54:33568 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05569 CompletionOnceCallback callback) override {
[email protected]999bcaa2013-07-17 13:42:54570 return OK;
571 }
572};
573
574// A FakeWebSocketStream where writes always fail.
575class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
576 public:
danakj9c5cab52016-04-16 00:54:33577 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05578 CompletionOnceCallback callback) override {
[email protected]999bcaa2013-07-17 13:42:54579 return ERR_CONNECTION_RESET;
580 }
581};
582
583// A FakeWebSocketStream which echoes any frames written back. Clears the
584// "masked" header bit, but makes no other checks for validity. Tests using this
585// must run the MessageLoop to receive the callback(s). If a message with opcode
586// Close is echoed, then an ERR_CONNECTION_CLOSED is returned in the next
587// callback. The test must do something to cause WriteFrames() to be called,
588// otherwise the ReadFrames() callback will never be called.
589class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
590 public:
danakj9c5cab52016-04-16 00:54:33591 EchoeyFakeWebSocketStream() : read_frames_(nullptr), done_(false) {}
[email protected]999bcaa2013-07-17 13:42:54592
danakj9c5cab52016-04-16 00:54:33593 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05594 CompletionOnceCallback callback) override {
yhirano592ff7f2015-12-07 08:45:19595 stored_frames_.insert(stored_frames_.end(),
596 std::make_move_iterator(frames->begin()),
597 std::make_move_iterator(frames->end()));
598 frames->clear();
[email protected]999bcaa2013-07-17 13:42:54599 // Users of WebSocketStream will not expect the ReadFrames() callback to be
600 // called from within WriteFrames(), so post it to the message loop instead.
[email protected]999bcaa2013-07-17 13:42:54601 PostCallback();
602 return OK;
603 }
604
danakj9c5cab52016-04-16 00:54:33605 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05606 CompletionOnceCallback callback) override {
607 read_callback_ = std::move(callback);
[email protected]2f5d9f62013-09-26 12:14:28608 read_frames_ = frames;
[email protected]999bcaa2013-07-17 13:42:54609 if (done_)
610 PostCallback();
611 return ERR_IO_PENDING;
612 }
613
614 private:
615 void PostCallback() {
skyostil4891b25b2015-06-11 11:43:45616 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49617 FROM_HERE, base::BindOnce(&EchoeyFakeWebSocketStream::DoCallback,
618 base::Unretained(this)));
[email protected]999bcaa2013-07-17 13:42:54619 }
620
621 void DoCallback() {
622 if (done_) {
Bence Békyf4f56e22018-07-17 02:00:05623 std::move(read_callback_).Run(ERR_CONNECTION_CLOSED);
[email protected]2f5d9f62013-09-26 12:14:28624 } else if (!stored_frames_.empty()) {
625 done_ = MoveFrames(read_frames_);
danakj9c5cab52016-04-16 00:54:33626 read_frames_ = nullptr;
Bence Békyf4f56e22018-07-17 02:00:05627 std::move(read_callback_).Run(OK);
[email protected]999bcaa2013-07-17 13:42:54628 }
629 }
630
[email protected]2f5d9f62013-09-26 12:14:28631 // Copy the frames stored in stored_frames_ to |out|, while clearing the
[email protected]999bcaa2013-07-17 13:42:54632 // "masked" header bit. Returns true if a Close Frame was seen, false
633 // otherwise.
danakj9c5cab52016-04-16 00:54:33634 bool MoveFrames(std::vector<std::unique_ptr<WebSocketFrame>>* out) {
[email protected]999bcaa2013-07-17 13:42:54635 bool seen_close = false;
yhirano592ff7f2015-12-07 08:45:19636 *out = std::move(stored_frames_);
637 for (const auto& frame : *out) {
638 WebSocketFrameHeader& header = frame->header;
[email protected]2f5d9f62013-09-26 12:14:28639 header.masked = false;
640 if (header.opcode == WebSocketFrameHeader::kOpCodeClose)
641 seen_close = true;
[email protected]999bcaa2013-07-17 13:42:54642 }
643 return seen_close;
644 }
645
danakj9c5cab52016-04-16 00:54:33646 std::vector<std::unique_ptr<WebSocketFrame>> stored_frames_;
Bence Békyf4f56e22018-07-17 02:00:05647 CompletionOnceCallback read_callback_;
[email protected]999bcaa2013-07-17 13:42:54648 // Owned by the caller of ReadFrames().
danakj9c5cab52016-04-16 00:54:33649 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames_;
[email protected]999bcaa2013-07-17 13:42:54650 // True if we should close the connection.
651 bool done_;
652};
653
[email protected]c0d29c22013-07-26 20:40:41654// A FakeWebSocketStream where writes trigger a connection reset.
655// This differs from UnWriteableFakeWebSocketStream in that it is asynchronous
656// and triggers ReadFrames to return a reset as well. Tests using this need to
[email protected]f485985e2013-10-24 13:47:44657// run the message loop. There are two tricky parts here:
658// 1. Calling the write callback may call Close(), after which the read callback
659// should not be called.
660// 2. Calling either callback may delete the stream altogether.
[email protected]c0d29c22013-07-26 20:40:41661class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
662 public:
Jeremy Romand54000b22019-07-08 18:40:16663 ResetOnWriteFakeWebSocketStream() : closed_(false) {}
[email protected]f485985e2013-10-24 13:47:44664
danakj9c5cab52016-04-16 00:54:33665 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05666 CompletionOnceCallback callback) override {
skyostil4891b25b2015-06-11 11:43:45667 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]f485985e2013-10-24 13:47:44668 FROM_HERE,
Bence Békyf4f56e22018-07-17 02:00:05669 base::BindOnce(
670 &ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
671 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
672 ERR_CONNECTION_RESET));
skyostil4891b25b2015-06-11 11:43:45673 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]f485985e2013-10-24 13:47:44674 FROM_HERE,
Bence Békyf4f56e22018-07-17 02:00:05675 base::BindOnce(
676 &ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
677 weak_ptr_factory_.GetWeakPtr(), std::move(read_callback_),
678 ERR_CONNECTION_RESET));
[email protected]c0d29c22013-07-26 20:40:41679 return ERR_IO_PENDING;
680 }
681
danakj9c5cab52016-04-16 00:54:33682 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
Bence Békyf4f56e22018-07-17 02:00:05683 CompletionOnceCallback callback) override {
684 read_callback_ = std::move(callback);
[email protected]c0d29c22013-07-26 20:40:41685 return ERR_IO_PENDING;
686 }
687
dchengb03027d2014-10-21 12:00:20688 void Close() override { closed_ = true; }
[email protected]f485985e2013-10-24 13:47:44689
[email protected]c0d29c22013-07-26 20:40:41690 private:
Bence Békyf4f56e22018-07-17 02:00:05691 void CallCallbackUnlessClosed(CompletionOnceCallback callback, int value) {
[email protected]f485985e2013-10-24 13:47:44692 if (!closed_)
Bence Békyf4f56e22018-07-17 02:00:05693 std::move(callback).Run(value);
[email protected]f485985e2013-10-24 13:47:44694 }
695
Bence Békyf4f56e22018-07-17 02:00:05696 CompletionOnceCallback read_callback_;
[email protected]f485985e2013-10-24 13:47:44697 bool closed_;
698 // An IO error can result in the socket being deleted, so we use weak pointers
699 // to ensure correct behaviour in that case.
Jeremy Romand54000b22019-07-08 18:40:16700 base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_{this};
[email protected]c0d29c22013-07-26 20:40:41701};
702
[email protected]999bcaa2013-07-17 13:42:54703// This mock is for verifying that WebSocket protocol semantics are obeyed (to
704// the extent that they are implemented in WebSocketCommon).
705class MockWebSocketStream : public WebSocketStream {
706 public:
Bence Békyf4f56e22018-07-17 02:00:05707 // GMock cannot save or forward move-only types like CompletionOnceCallback,
708 // therefore they have to be converted into a copyable type like
709 // CompletionRepeatingCallback.
710 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
711 CompletionOnceCallback callback) {
712 return ReadFramesInternal(
713 frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
714 : CompletionRepeatingCallback());
715 }
716 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
717 CompletionOnceCallback callback) {
718 return WriteFramesInternal(
719 frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
720 : CompletionRepeatingCallback());
721 }
722
723 MOCK_METHOD2(ReadFramesInternal,
724 int(std::vector<std::unique_ptr<WebSocketFrame>>*,
725 const CompletionRepeatingCallback&));
726 MOCK_METHOD2(WriteFramesInternal,
727 int(std::vector<std::unique_ptr<WebSocketFrame>>*,
728 const CompletionRepeatingCallback&));
729
[email protected]999bcaa2013-07-17 13:42:54730 MOCK_METHOD0(Close, void());
731 MOCK_CONST_METHOD0(GetSubProtocol, std::string());
732 MOCK_CONST_METHOD0(GetExtensions, std::string());
733 MOCK_METHOD0(AsWebSocketStream, WebSocketStream*());
[email protected]999bcaa2013-07-17 13:42:54734};
735
tyoshinoccfcfde2016-07-21 14:06:55736class MockWebSocketStreamRequest : public WebSocketStreamRequest {
737 public:
Adam Rice6f75c0f2018-06-04 08:00:05738 MOCK_METHOD1(OnBasicHandshakeStreamCreated,
739 void(WebSocketBasicHandshakeStream* handshake_stream));
740 MOCK_METHOD1(OnHttp2HandshakeStreamCreated,
741 void(WebSocketHttp2HandshakeStream* handshake_stream));
tyoshinoccfcfde2016-07-21 14:06:55742 MOCK_METHOD1(OnFailure, void(const std::string& message));
743};
744
745struct WebSocketStreamCreationCallbackArgumentSaver {
danakj9c5cab52016-04-16 00:54:33746 std::unique_ptr<WebSocketStreamRequest> Create(
[email protected]999bcaa2013-07-17 13:42:54747 const GURL& socket_url,
Bence Béky68506d852018-12-07 16:18:12748 const std::vector<std::string>& requested_subprotocols,
mkwst4997ce82015-07-25 12:00:05749 const url::Origin& origin,
Mike Westb85da8ed2017-08-10 14:16:46750 const GURL& site_for_cookies,
Yutaka Hirano2f65eec2018-05-23 01:58:22751 const HttpRequestHeaders& additional_headers,
[email protected]999bcaa2013-07-17 13:42:54752 URLRequestContext* url_request_context,
tfarina42834112016-09-22 13:38:20753 const NetLogWithSource& net_log,
danakj9c5cab52016-04-16 00:54:33754 std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
[email protected]999bcaa2013-07-17 13:42:54755 this->socket_url = socket_url;
[email protected]999bcaa2013-07-17 13:42:54756 this->origin = origin;
Mike Westb85da8ed2017-08-10 14:16:46757 this->site_for_cookies = site_for_cookies;
[email protected]999bcaa2013-07-17 13:42:54758 this->url_request_context = url_request_context;
dchengc7eeda422015-12-26 03:56:48759 this->connect_delegate = std::move(connect_delegate);
Bence Béky8f9d7d3952017-10-09 19:58:04760 return std::make_unique<MockWebSocketStreamRequest>();
[email protected]999bcaa2013-07-17 13:42:54761 }
762
763 GURL socket_url;
mkwst4997ce82015-07-25 12:00:05764 url::Origin origin;
Mike Westb85da8ed2017-08-10 14:16:46765 GURL site_for_cookies;
[email protected]999bcaa2013-07-17 13:42:54766 URLRequestContext* url_request_context;
danakj9c5cab52016-04-16 00:54:33767 std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate;
[email protected]999bcaa2013-07-17 13:42:54768};
769
darin0da77e922016-10-04 17:31:23770std::vector<char> AsVector(const base::StringPiece& s) {
[email protected]999bcaa2013-07-17 13:42:54771 return std::vector<char>(s.begin(), s.end());
772}
773
darin0da77e922016-10-04 17:31:23774// Converts a base::StringPiece to a IOBuffer. For test purposes, it is
775// convenient to be able to specify data as a string, but the
776// WebSocketEventInterface requires the IOBuffer type.
777scoped_refptr<IOBuffer> AsIOBuffer(const base::StringPiece& s) {
Bence Béky65623972018-03-05 15:31:56778 auto buffer = base::MakeRefCounted<IOBuffer>(s.size());
darin0da77e922016-10-04 17:31:23779 std::copy(s.begin(), s.end(), buffer->data());
780 return buffer;
781}
782
[email protected]a62449522014-06-05 11:11:15783class FakeSSLErrorCallbacks
784 : public WebSocketEventInterface::SSLErrorCallbacks {
785 public:
dchengb03027d2014-10-21 12:00:20786 void CancelSSLRequest(int error, const SSLInfo* ssl_info) override {}
787 void ContinueSSLRequest() override {}
[email protected]a62449522014-06-05 11:11:15788};
789
[email protected]999bcaa2013-07-17 13:42:54790// Base class for all test fixtures.
Gabriel Charette694c3c332019-08-19 14:53:05791class WebSocketChannelTest : public TestWithTaskEnvironment {
[email protected]999bcaa2013-07-17 13:42:54792 protected:
Bence Béky65623972018-03-05 15:31:56793 WebSocketChannelTest() : stream_(std::make_unique<FakeWebSocketStream>()) {}
[email protected]999bcaa2013-07-17 13:42:54794
795 // Creates a new WebSocketChannel and connects it, using the settings stored
796 // in |connect_data_|.
797 void CreateChannelAndConnect() {
Bence Béky65623972018-03-05 15:31:56798 channel_ = std::make_unique<WebSocketChannel>(
799 CreateEventInterface(), &connect_data_.url_request_context);
[email protected]999bcaa2013-07-17 13:42:54800 channel_->SendAddChannelRequestForTesting(
alladacef397d2016-06-29 17:52:23801 connect_data_.socket_url, connect_data_.requested_subprotocols,
Yutaka Hirano2f65eec2018-05-23 01:58:22802 connect_data_.origin, connect_data_.site_for_cookies,
803 HttpRequestHeaders(),
tyoshinoccfcfde2016-07-21 14:06:55804 base::Bind(&WebSocketStreamCreationCallbackArgumentSaver::Create,
805 base::Unretained(&connect_data_.argument_saver)));
[email protected]999bcaa2013-07-17 13:42:54806 }
807
808 // Same as CreateChannelAndConnect(), but calls the on_success callback as
809 // well. This method is virtual so that subclasses can also set the stream.
810 virtual void CreateChannelAndConnectSuccessfully() {
811 CreateChannelAndConnect();
tyoshinoccfcfde2016-07-21 14:06:55812 connect_data_.argument_saver.connect_delegate->OnSuccess(
813 std::move(stream_));
Yutaka Hiranodfa67e52019-07-29 03:13:26814 // Most tests aren't concerned with flow control from the renderer, so allow
815 // MAX_INT quota units.
816 base::IgnoreResult(channel_->AddReceiveFlowControlQuota(kPlentyOfQuota));
[email protected]999bcaa2013-07-17 13:42:54817 }
818
819 // Returns a WebSocketEventInterface to be passed to the WebSocketChannel.
820 // This implementation returns a newly-created fake. Subclasses may return a
821 // mock instead.
danakj9c5cab52016-04-16 00:54:33822 virtual std::unique_ptr<WebSocketEventInterface> CreateEventInterface() {
Bence Béky8f9d7d3952017-10-09 19:58:04823 return std::make_unique<FakeWebSocketEventInterface>();
[email protected]999bcaa2013-07-17 13:42:54824 }
825
826 // This method serves no other purpose than to provide a nice syntax for
827 // assigning to stream_. class T must be a subclass of WebSocketStream or you
828 // will have unpleasant compile errors.
829 template <class T>
danakj9c5cab52016-04-16 00:54:33830 void set_stream(std::unique_ptr<T> stream) {
dchengc7eeda422015-12-26 03:56:48831 stream_ = std::move(stream);
[email protected]999bcaa2013-07-17 13:42:54832 }
833
834 // A struct containing the data that will be used to connect the channel.
[email protected]72dd6fda2013-10-17 16:21:11835 // Grouped for readability.
[email protected]999bcaa2013-07-17 13:42:54836 struct ConnectData {
tyoshino8572d572016-07-13 06:29:48837 ConnectData()
838 : socket_url("ws://ws/"),
Daniel Cheng88186bd52017-10-20 08:14:46839 origin(url::Origin::Create(GURL("http://ws"))),
Mike Westb85da8ed2017-08-10 14:16:46840 site_for_cookies("http://ws/") {}
[email protected]53deacb2013-11-22 14:02:43841
[email protected]999bcaa2013-07-17 13:42:54842 // URLRequestContext object.
843 URLRequestContext url_request_context;
[email protected]72dd6fda2013-10-17 16:21:11844
845 // URL to (pretend to) connect to.
846 GURL socket_url;
847 // Requested protocols for the request.
848 std::vector<std::string> requested_subprotocols;
849 // Origin of the request
mkwst4997ce82015-07-25 12:00:05850 url::Origin origin;
tyoshino8572d572016-07-13 06:29:48851 // First party for cookies for the request.
Mike Westb85da8ed2017-08-10 14:16:46852 GURL site_for_cookies;
[email protected]72dd6fda2013-10-17 16:21:11853
tyoshinoccfcfde2016-07-21 14:06:55854 WebSocketStreamCreationCallbackArgumentSaver argument_saver;
[email protected]999bcaa2013-07-17 13:42:54855 };
856 ConnectData connect_data_;
857
858 // The channel we are testing. Not initialised until SetChannel() is called.
danakj9c5cab52016-04-16 00:54:33859 std::unique_ptr<WebSocketChannel> channel_;
[email protected]999bcaa2013-07-17 13:42:54860
861 // A mock or fake stream for tests that need one.
danakj9c5cab52016-04-16 00:54:33862 std::unique_ptr<WebSocketStream> stream_;
[email protected]999bcaa2013-07-17 13:42:54863};
864
[email protected]f485985e2013-10-24 13:47:44865// enum of WebSocketEventInterface calls. These are intended to be or'd together
866// in order to instruct WebSocketChannelDeletingTest when it should fail.
867enum EventInterfaceCall {
868 EVENT_ON_ADD_CHANNEL_RESPONSE = 0x1,
869 EVENT_ON_DATA_FRAME = 0x2,
870 EVENT_ON_FLOW_CONTROL = 0x4,
871 EVENT_ON_CLOSING_HANDSHAKE = 0x8,
[email protected]96868202014-01-09 10:38:04872 EVENT_ON_FAIL_CHANNEL = 0x10,
873 EVENT_ON_DROP_CHANNEL = 0x20,
[email protected]cd48ed12014-01-22 14:34:22874 EVENT_ON_START_OPENING_HANDSHAKE = 0x40,
875 EVENT_ON_FINISH_OPENING_HANDSHAKE = 0x80,
[email protected]a62449522014-06-05 11:11:15876 EVENT_ON_SSL_CERTIFICATE_ERROR = 0x100,
[email protected]f485985e2013-10-24 13:47:44877};
878
[email protected]999bcaa2013-07-17 13:42:54879// Base class for tests which verify that EventInterface methods are called
880// appropriately.
881class WebSocketChannelEventInterfaceTest : public WebSocketChannelTest {
882 protected:
883 WebSocketChannelEventInterfaceTest()
Bence Béky65623972018-03-05 15:31:56884 : event_interface_(
885 std::make_unique<StrictMock<MockWebSocketEventInterface>>()) {
[email protected]f485985e2013-10-24 13:47:44886 }
887
dcheng67be2b1f2014-10-27 21:47:29888 ~WebSocketChannelEventInterfaceTest() override {
[email protected]f485985e2013-10-24 13:47:44889 }
[email protected]999bcaa2013-07-17 13:42:54890
891 // Tests using this fixture must set expectations on the event_interface_ mock
892 // object before calling CreateChannelAndConnect() or
893 // CreateChannelAndConnectSuccessfully(). This will only work once per test
894 // case, but once should be enough.
danakj9c5cab52016-04-16 00:54:33895 std::unique_ptr<WebSocketEventInterface> CreateEventInterface() override {
Bence Béky65623972018-03-05 15:31:56896 return std::move(event_interface_);
[email protected]999bcaa2013-07-17 13:42:54897 }
898
danakj9c5cab52016-04-16 00:54:33899 std::unique_ptr<MockWebSocketEventInterface> event_interface_;
[email protected]999bcaa2013-07-17 13:42:54900};
901
902// Base class for tests which verify that WebSocketStream methods are called
903// appropriately by using a MockWebSocketStream.
904class WebSocketChannelStreamTest : public WebSocketChannelTest {
905 protected:
906 WebSocketChannelStreamTest()
Bence Béky65623972018-03-05 15:31:56907 : mock_stream_(std::make_unique<StrictMock<MockWebSocketStream>>()) {}
[email protected]999bcaa2013-07-17 13:42:54908
dchengb03027d2014-10-21 12:00:20909 void CreateChannelAndConnectSuccessfully() override {
dchengc7eeda422015-12-26 03:56:48910 set_stream(std::move(mock_stream_));
[email protected]999bcaa2013-07-17 13:42:54911 WebSocketChannelTest::CreateChannelAndConnectSuccessfully();
912 }
913
danakj9c5cab52016-04-16 00:54:33914 std::unique_ptr<MockWebSocketStream> mock_stream_;
[email protected]999bcaa2013-07-17 13:42:54915};
916
[email protected]48cc6922014-02-10 14:20:48917// Fixture for tests which test UTF-8 validation of sent Text frames via the
918// EventInterface.
919class WebSocketChannelSendUtf8Test
920 : public WebSocketChannelEventInterfaceTest {
921 public:
dcheng67be2b1f2014-10-27 21:47:29922 void SetUp() override {
Bence Béky8f9d7d3952017-10-09 19:58:04923 set_stream(std::make_unique<WriteableFakeWebSocketStream>());
[email protected]48cc6922014-02-10 14:20:48924 // For the purpose of the tests using this fixture, it doesn't matter
925 // whether these methods are called or not.
tyoshinoc06da562015-03-06 06:02:42926 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _))
[email protected]48cc6922014-02-10 14:20:48927 .Times(AnyNumber());
Yoichi Osatob088adc2019-06-06 05:52:19928 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_))
[email protected]48cc6922014-02-10 14:20:48929 .Times(AnyNumber());
930 }
931};
932
[email protected]4256dbb2014-03-24 15:39:36933// Fixture for tests which test use of receive quota from the renderer.
934class WebSocketChannelFlowControlTest
935 : public WebSocketChannelEventInterfaceTest {
936 protected:
937 // Tests using this fixture should use CreateChannelAndConnectWithQuota()
938 // instead of CreateChannelAndConnectSuccessfully().
tfarina8a2c66c22015-10-13 19:14:49939 void CreateChannelAndConnectWithQuota(int64_t quota) {
[email protected]4256dbb2014-03-24 15:39:36940 CreateChannelAndConnect();
tyoshinoccfcfde2016-07-21 14:06:55941 connect_data_.argument_saver.connect_delegate->OnSuccess(
942 std::move(stream_));
Yutaka Hiranodfa67e52019-07-29 03:13:26943 base::IgnoreResult(channel_->AddReceiveFlowControlQuota(quota));
[email protected]4256dbb2014-03-24 15:39:36944 }
945
946 virtual void CreateChannelAndConnectSuccesfully() { NOTREACHED(); }
947};
948
[email protected]48cc6922014-02-10 14:20:48949// Fixture for tests which test UTF-8 validation of received Text frames using a
950// mock WebSocketStream.
951class WebSocketChannelReceiveUtf8Test : public WebSocketChannelStreamTest {
952 public:
dcheng67be2b1f2014-10-27 21:47:29953 void SetUp() override {
[email protected]48cc6922014-02-10 14:20:48954 // For the purpose of the tests using this fixture, it doesn't matter
955 // whether these methods are called or not.
956 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
957 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
958 }
959};
960
tyoshinoccfcfde2016-07-21 14:06:55961// Simple test that everything that should be passed to the stream creation
962// callback is passed to the argument saver.
[email protected]969dde72013-11-13 15:59:14963TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) {
[email protected]72dd6fda2013-10-17 16:21:11964 connect_data_.socket_url = GURL("ws://example.com/test");
Daniel Cheng88186bd52017-10-20 08:14:46965 connect_data_.origin = url::Origin::Create(GURL("http://example.com"));
Mike Westb85da8ed2017-08-10 14:16:46966 connect_data_.site_for_cookies = GURL("http://example.com/");
[email protected]999bcaa2013-07-17 13:42:54967 connect_data_.requested_subprotocols.push_back("Sinbad");
968
969 CreateChannelAndConnect();
970
tyoshinoccfcfde2016-07-21 14:06:55971 const WebSocketStreamCreationCallbackArgumentSaver& actual =
972 connect_data_.argument_saver;
[email protected]72dd6fda2013-10-17 16:21:11973
974 EXPECT_EQ(&connect_data_.url_request_context, actual.url_request_context);
975
976 EXPECT_EQ(connect_data_.socket_url, actual.socket_url);
mkwst4997ce82015-07-25 12:00:05977 EXPECT_EQ(connect_data_.origin.Serialize(), actual.origin.Serialize());
Mike Westb85da8ed2017-08-10 14:16:46978 EXPECT_EQ(connect_data_.site_for_cookies, actual.site_for_cookies);
[email protected]999bcaa2013-07-17 13:42:54979}
980
981TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) {
982 // false means success.
tyoshinoc06da562015-03-06 06:02:42983 EXPECT_CALL(*event_interface_, OnAddChannelResponse("", ""));
Yoichi Osatob088adc2019-06-06 05:52:19984 // OnSendFlowControlQuotaAdded is always called immediately after connect to
985 // provide initial quota to the renderer.
986 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:54987
988 CreateChannelAndConnect();
989
tyoshinoccfcfde2016-07-21 14:06:55990 connect_data_.argument_saver.connect_delegate->OnSuccess(std::move(stream_));
[email protected]999bcaa2013-07-17 13:42:54991}
992
993TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) {
[email protected]96868202014-01-09 10:38:04994 EXPECT_CALL(*event_interface_, OnFailChannel("hello"));
[email protected]999bcaa2013-07-17 13:42:54995
996 CreateChannelAndConnect();
997
tyoshinoccfcfde2016-07-21 14:06:55998 connect_data_.argument_saver.connect_delegate->OnFailure("hello");
[email protected]999bcaa2013-07-17 13:42:54999}
1000
[email protected]53deacb2013-11-22 14:02:431001TEST_F(WebSocketChannelEventInterfaceTest, NonWebSocketSchemeRejected) {
tyoshinoc06da562015-03-06 06:02:421002 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid scheme"));
[email protected]53deacb2013-11-22 14:02:431003 connect_data_.socket_url = GURL("http://www.google.com/");
1004 CreateChannelAndConnect();
1005}
1006
[email protected]999bcaa2013-07-17 13:42:541007TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
tyoshinoc06da562015-03-06 06:02:421008 EXPECT_CALL(*event_interface_, OnAddChannelResponse("Bob", ""));
Yoichi Osatob088adc2019-06-06 05:52:191009 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541010
1011 CreateChannelAndConnect();
1012
tyoshinoccfcfde2016-07-21 14:06:551013 connect_data_.argument_saver.connect_delegate->OnSuccess(
Jeremy Roman0579ed62017-08-29 15:56:191014 std::make_unique<FakeWebSocketStream>("Bob", ""));
[email protected]999bcaa2013-07-17 13:42:541015}
1016
[email protected]6c5d9f62014-01-27 15:05:211017TEST_F(WebSocketChannelEventInterfaceTest, ExtensionsPassed) {
1018 EXPECT_CALL(*event_interface_,
tyoshinoc06da562015-03-06 06:02:421019 OnAddChannelResponse("", "extension1, extension2"));
Yoichi Osatob088adc2019-06-06 05:52:191020 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]6c5d9f62014-01-27 15:05:211021
1022 CreateChannelAndConnect();
1023
tyoshinoccfcfde2016-07-21 14:06:551024 connect_data_.argument_saver.connect_delegate->OnSuccess(
Jeremy Roman0579ed62017-08-29 15:56:191025 std::make_unique<FakeWebSocketStream>("", "extension1, extension2"));
[email protected]6c5d9f62014-01-27 15:05:211026}
1027
[email protected]999bcaa2013-07-17 13:42:541028// The first frames from the server can arrive together with the handshake, in
1029// which case they will be available as soon as ReadFrames() is called the first
1030// time.
1031TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
Bence Béky65623972018-03-05 15:31:561032 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281033 static const InitFrame frames[] = {
1034 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1035 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481036 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541037 {
1038 InSequence s;
tyoshinoc06da562015-03-06 06:02:421039 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191040 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
darin0da77e922016-10-04 17:31:231041 EXPECT_CALL(*event_interface_,
1042 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1043 AsVector("HELLO")));
[email protected]999bcaa2013-07-17 13:42:541044 }
1045
1046 CreateChannelAndConnectSuccessfully();
1047}
1048
1049// A remote server could accept the handshake, but then immediately send a
1050// Close frame.
1051TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) {
Bence Béky65623972018-03-05 15:31:561052 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281053 static const InitFrame frames[] = {
1054 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1055 NOT_MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
1056 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
[email protected]999bcaa2013-07-17 13:42:541057 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1058 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481059 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541060 {
1061 InSequence s;
tyoshinoc06da562015-03-06 06:02:421062 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191063 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541064 EXPECT_CALL(*event_interface_, OnClosingHandshake());
[email protected]86ec55502014-02-10 13:16:161065 EXPECT_CALL(
1066 *event_interface_,
1067 OnDropChannel(
1068 true, kWebSocketErrorInternalServerError, "Internal Server Error"));
[email protected]999bcaa2013-07-17 13:42:541069 }
1070
1071 CreateChannelAndConnectSuccessfully();
1072}
1073
1074// A remote server could close the connection immediately after sending the
1075// handshake response (most likely a bug in the server).
1076TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) {
Bence Béky65623972018-03-05 15:31:561077 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]999bcaa2013-07-17 13:42:541078 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1079 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481080 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541081 {
1082 InSequence s;
tyoshinoc06da562015-03-06 06:02:421083 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191084 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541085 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161086 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541087 }
1088
1089 CreateChannelAndConnectSuccessfully();
1090}
1091
1092TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
Bence Béky65623972018-03-05 15:31:561093 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281094 static const InitFrame frames[] = {
1095 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
[email protected]999bcaa2013-07-17 13:42:541096 // We use this checkpoint object to verify that the callback isn't called
1097 // until we expect it to be.
[email protected]f485985e2013-10-24 13:47:441098 Checkpoint checkpoint;
[email protected]2f5d9f62013-09-26 12:14:281099 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481100 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541101 {
1102 InSequence s;
tyoshinoc06da562015-03-06 06:02:421103 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191104 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541105 EXPECT_CALL(checkpoint, Call(1));
darin0da77e922016-10-04 17:31:231106 EXPECT_CALL(*event_interface_,
1107 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1108 AsVector("HELLO")));
[email protected]999bcaa2013-07-17 13:42:541109 EXPECT_CALL(checkpoint, Call(2));
1110 }
1111
1112 CreateChannelAndConnectSuccessfully();
1113 checkpoint.Call(1);
fdoray92e35a72016-06-10 15:54:551114 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541115 checkpoint.Call(2);
1116}
1117
1118// Extra data can arrive while a read is being processed, resulting in the next
1119// read completing synchronously.
1120TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
Bence Béky65623972018-03-05 15:31:561121 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281122 static const InitFrame frames1[] = {
1123 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1124 static const InitFrame frames2[] = {
1125 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "WORLD"}};
1126 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1127 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames2);
dchengc7eeda422015-12-26 03:56:481128 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541129 {
1130 InSequence s;
tyoshinoc06da562015-03-06 06:02:421131 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191132 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
darin0da77e922016-10-04 17:31:231133 EXPECT_CALL(*event_interface_,
1134 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1135 AsVector("HELLO")));
1136 EXPECT_CALL(*event_interface_,
1137 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1138 AsVector("WORLD")));
[email protected]999bcaa2013-07-17 13:42:541139 }
1140
1141 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551142 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541143}
1144
[email protected]2f5d9f62013-09-26 12:14:281145// Data frames are delivered the same regardless of how many reads they arrive
1146// as.
1147TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) {
Bence Béky65623972018-03-05 15:31:561148 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281149 // Here we have one message which arrived in five frames split across three
1150 // reads. It may have been reframed on arrival, but this class doesn't care
1151 // about that.
1152 static const InitFrame frames1[] = {
1153 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "THREE"},
1154 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1155 NOT_MASKED, " "}};
1156 static const InitFrame frames2[] = {
1157 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1158 NOT_MASKED, "SMALL"}};
1159 static const InitFrame frames3[] = {
1160 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1161 NOT_MASKED, " "},
1162 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1163 NOT_MASKED, "FRAMES"}};
1164 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1165 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1166 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
dchengc7eeda422015-12-26 03:56:481167 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541168 {
1169 InSequence s;
tyoshinoc06da562015-03-06 06:02:421170 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191171 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541172 EXPECT_CALL(*event_interface_,
darin0da77e922016-10-04 17:31:231173 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1174 AsVector("THREE")));
[email protected]999bcaa2013-07-17 13:42:541175 EXPECT_CALL(
1176 *event_interface_,
darin0da77e922016-10-04 17:31:231177 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1178 AsVector(" ")));
1179 EXPECT_CALL(
1180 *event_interface_,
1181 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1182 AsVector("SMALL")));
1183 EXPECT_CALL(
1184 *event_interface_,
1185 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1186 AsVector(" ")));
1187 EXPECT_CALL(
1188 *event_interface_,
1189 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
1190 AsVector("FRAMES")));
[email protected]999bcaa2013-07-17 13:42:541191 }
1192
1193 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551194 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541195}
1196
danakj9c5cab52016-04-16 00:54:331197// A message can consist of one frame with null payload.
[email protected]00f4daf2013-11-12 13:56:411198TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) {
Bence Béky65623972018-03-05 15:31:561199 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]00f4daf2013-11-12 13:56:411200 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:331201 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411202 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481203 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421204 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191205 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]00f4daf2013-11-12 13:56:411206 EXPECT_CALL(
1207 *event_interface_,
darin0da77e922016-10-04 17:31:231208 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
[email protected]00f4daf2013-11-12 13:56:411209 CreateChannelAndConnectSuccessfully();
1210}
1211
[email protected]999bcaa2013-07-17 13:42:541212// Connection closed by the remote host without a closing handshake.
1213TEST_F(WebSocketChannelEventInterfaceTest, AsyncAbnormalClosure) {
Bence Béky65623972018-03-05 15:31:561214 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]999bcaa2013-07-17 13:42:541215 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1216 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481217 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541218 {
1219 InSequence s;
tyoshinoc06da562015-03-06 06:02:421220 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191221 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541222 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161223 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541224 }
1225
1226 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551227 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541228}
1229
1230// A connection reset should produce the same event as an unexpected closure.
1231TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) {
Bence Béky65623972018-03-05 15:31:561232 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]999bcaa2013-07-17 13:42:541233 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1234 ERR_CONNECTION_RESET);
dchengc7eeda422015-12-26 03:56:481235 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541236 {
1237 InSequence s;
tyoshinoc06da562015-03-06 06:02:421238 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191239 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541240 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161241 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541242 }
1243
1244 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551245 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541246}
1247
[email protected]999bcaa2013-07-17 13:42:541248// RFC6455 5.1 "A client MUST close a connection if it detects a masked frame."
1249TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
Bence Béky65623972018-03-05 15:31:561250 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281251 static const InitFrame frames[] = {
1252 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
[email protected]999bcaa2013-07-17 13:42:541253
[email protected]2f5d9f62013-09-26 12:14:281254 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481255 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541256 {
1257 InSequence s;
tyoshinoc06da562015-03-06 06:02:421258 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191259 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]ea56b982014-01-27 03:21:031260 EXPECT_CALL(
1261 *event_interface_,
1262 OnFailChannel(
1263 "A server must not mask any frames that it sends to the client."));
[email protected]999bcaa2013-07-17 13:42:541264 }
1265
1266 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551267 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541268}
1269
1270// RFC6455 5.2 "If an unknown opcode is received, the receiving endpoint MUST
1271// _Fail the WebSocket Connection_."
1272TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) {
Bence Béky65623972018-03-05 15:31:561273 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281274 static const InitFrame frames[] = {{FINAL_FRAME, 4, NOT_MASKED, "HELLO"}};
[email protected]999bcaa2013-07-17 13:42:541275
[email protected]2f5d9f62013-09-26 12:14:281276 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481277 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541278 {
1279 InSequence s;
tyoshinoc06da562015-03-06 06:02:421280 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191281 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541282 EXPECT_CALL(*event_interface_,
[email protected]ea56b982014-01-27 03:21:031283 OnFailChannel("Unrecognized frame opcode: 4"));
[email protected]999bcaa2013-07-17 13:42:541284 }
1285
1286 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551287 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541288}
1289
1290// RFC6455 5.4 "Control frames ... MAY be injected in the middle of a
1291// fragmented message."
1292TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
Bence Béky65623972018-03-05 15:31:561293 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]999bcaa2013-07-17 13:42:541294 // We have one message of type Text split into two frames. In the middle is a
1295 // control message of type Pong.
[email protected]2f5d9f62013-09-26 12:14:281296 static const InitFrame frames1[] = {
1297 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1298 NOT_MASKED, "SPLIT "}};
1299 static const InitFrame frames2[] = {
1300 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
1301 static const InitFrame frames3[] = {
1302 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1303 NOT_MASKED, "MESSAGE"}};
1304 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1305 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1306 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
dchengc7eeda422015-12-26 03:56:481307 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541308 {
1309 InSequence s;
tyoshinoc06da562015-03-06 06:02:421310 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191311 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
darin0da77e922016-10-04 17:31:231312 EXPECT_CALL(*event_interface_,
1313 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1314 AsVector("SPLIT ")));
[email protected]999bcaa2013-07-17 13:42:541315 EXPECT_CALL(
1316 *event_interface_,
darin0da77e922016-10-04 17:31:231317 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
1318 AsVector("MESSAGE")));
[email protected]999bcaa2013-07-17 13:42:541319 }
1320
1321 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551322 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541323}
1324
[email protected]00f4daf2013-11-12 13:56:411325// It seems redundant to repeat the entirety of the above test, so just test a
danakj9c5cab52016-04-16 00:54:331326// Pong with null data.
[email protected]00f4daf2013-11-12 13:56:411327TEST_F(WebSocketChannelEventInterfaceTest, PongWithNullData) {
Bence Béky65623972018-03-05 15:31:561328 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]00f4daf2013-11-12 13:56:411329 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:331330 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411331 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481332 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421333 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191334 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]00f4daf2013-11-12 13:56:411335
1336 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551337 base::RunLoop().RunUntilIdle();
[email protected]00f4daf2013-11-12 13:56:411338}
1339
[email protected]2f5d9f62013-09-26 12:14:281340// If a frame has an invalid header, then the connection is closed and
1341// subsequent frames must not trigger events.
1342TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) {
Bence Béky65623972018-03-05 15:31:561343 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281344 static const InitFrame frames[] = {
1345 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"},
1346 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, " WORLD"}};
[email protected]c0d29c22013-07-26 20:40:411347
[email protected]2f5d9f62013-09-26 12:14:281348 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481349 set_stream(std::move(stream));
[email protected]c0d29c22013-07-26 20:40:411350 {
1351 InSequence s;
tyoshinoc06da562015-03-06 06:02:421352 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191353 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]ea56b982014-01-27 03:21:031354 EXPECT_CALL(
1355 *event_interface_,
1356 OnFailChannel(
1357 "A server must not mask any frames that it sends to the client."));
[email protected]c0d29c22013-07-26 20:40:411358 }
1359
1360 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551361 base::RunLoop().RunUntilIdle();
[email protected]c0d29c22013-07-26 20:40:411362}
1363
[email protected]999bcaa2013-07-17 13:42:541364// If the renderer sends lots of small writes, we don't want to update the quota
1365// for each one.
1366TEST_F(WebSocketChannelEventInterfaceTest, SmallWriteDoesntUpdateQuota) {
Bence Béky8f9d7d3952017-10-09 19:58:041367 set_stream(std::make_unique<WriteableFakeWebSocketStream>());
[email protected]999bcaa2013-07-17 13:42:541368 {
1369 InSequence s;
tyoshinoc06da562015-03-06 06:02:421370 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191371 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541372 }
1373
1374 CreateChannelAndConnectSuccessfully();
darin0da77e922016-10-04 17:31:231375 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsIOBuffer("B"),
1376 1U);
[email protected]999bcaa2013-07-17 13:42:541377}
1378
ricea10bf0e12015-12-14 11:18:291379// If we send enough to go below |send_quota_low_water_mark_| we should get our
[email protected]999bcaa2013-07-17 13:42:541380// quota refreshed.
1381TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) {
Bence Béky8f9d7d3952017-10-09 19:58:041382 set_stream(std::make_unique<WriteableFakeWebSocketStream>());
[email protected]999bcaa2013-07-17 13:42:541383 // We use this checkpoint object to verify that the quota update comes after
1384 // the write.
[email protected]f485985e2013-10-24 13:47:441385 Checkpoint checkpoint;
[email protected]999bcaa2013-07-17 13:42:541386 {
1387 InSequence s;
tyoshinoc06da562015-03-06 06:02:421388 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191389 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541390 EXPECT_CALL(checkpoint, Call(1));
Yoichi Osatob088adc2019-06-06 05:52:191391 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541392 EXPECT_CALL(checkpoint, Call(2));
1393 }
1394
1395 CreateChannelAndConnectSuccessfully();
1396 checkpoint.Call(1);
darin0da77e922016-10-04 17:31:231397 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1398 AsIOBuffer(std::string(kDefaultInitialQuota, 'B')),
1399 kDefaultInitialQuota);
[email protected]999bcaa2013-07-17 13:42:541400 checkpoint.Call(2);
1401}
1402
1403// Verify that our quota actually is refreshed when we are told it is.
1404TEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) {
Bence Béky8f9d7d3952017-10-09 19:58:041405 set_stream(std::make_unique<WriteableFakeWebSocketStream>());
[email protected]f485985e2013-10-24 13:47:441406 Checkpoint checkpoint;
[email protected]999bcaa2013-07-17 13:42:541407 {
1408 InSequence s;
tyoshinoc06da562015-03-06 06:02:421409 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191410 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541411 EXPECT_CALL(checkpoint, Call(1));
Yoichi Osatob088adc2019-06-06 05:52:191412 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541413 EXPECT_CALL(checkpoint, Call(2));
1414 // If quota was not really refreshed, we would get an OnDropChannel()
1415 // message.
Yoichi Osatob088adc2019-06-06 05:52:191416 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541417 EXPECT_CALL(checkpoint, Call(3));
1418 }
1419
1420 CreateChannelAndConnectSuccessfully();
1421 checkpoint.Call(1);
darin0da77e922016-10-04 17:31:231422 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1423 AsIOBuffer(std::string(kDefaultQuotaRefreshTrigger, 'D')),
1424 kDefaultQuotaRefreshTrigger);
[email protected]999bcaa2013-07-17 13:42:541425 checkpoint.Call(2);
1426 // We should have received more quota at this point.
darin0da77e922016-10-04 17:31:231427 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1428 AsIOBuffer(std::string(kDefaultQuotaRefreshTrigger, 'E')),
1429 kDefaultQuotaRefreshTrigger);
[email protected]999bcaa2013-07-17 13:42:541430 checkpoint.Call(3);
1431}
1432
1433// If we send more than the available quota then the connection will be closed
1434// with an error.
1435TEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) {
Bence Béky8f9d7d3952017-10-09 19:58:041436 set_stream(std::make_unique<WriteableFakeWebSocketStream>());
[email protected]999bcaa2013-07-17 13:42:541437 {
1438 InSequence s;
tyoshinoc06da562015-03-06 06:02:421439 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191440 EXPECT_CALL(*event_interface_,
1441 OnSendFlowControlQuotaAdded(kDefaultInitialQuota));
[email protected]ea56b982014-01-27 03:21:031442 EXPECT_CALL(*event_interface_, OnFailChannel("Send quota exceeded"));
[email protected]999bcaa2013-07-17 13:42:541443 }
1444
1445 CreateChannelAndConnectSuccessfully();
darin0da77e922016-10-04 17:31:231446 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1447 AsIOBuffer(std::string(kDefaultInitialQuota + 1, 'C')),
1448 kDefaultInitialQuota + 1);
[email protected]999bcaa2013-07-17 13:42:541449}
1450
1451// If a write fails, the channel is dropped.
1452TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) {
Bence Béky8f9d7d3952017-10-09 19:58:041453 set_stream(std::make_unique<UnWriteableFakeWebSocketStream>());
[email protected]f485985e2013-10-24 13:47:441454 Checkpoint checkpoint;
[email protected]999bcaa2013-07-17 13:42:541455 {
1456 InSequence s;
tyoshinoc06da562015-03-06 06:02:421457 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191458 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541459 EXPECT_CALL(checkpoint, Call(1));
1460 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161461 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541462 EXPECT_CALL(checkpoint, Call(2));
1463 }
1464
1465 CreateChannelAndConnectSuccessfully();
1466 checkpoint.Call(1);
1467
darin0da77e922016-10-04 17:31:231468 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsIOBuffer("H"),
1469 1U);
[email protected]999bcaa2013-07-17 13:42:541470 checkpoint.Call(2);
1471}
1472
1473// OnDropChannel() is called exactly once when StartClosingHandshake() is used.
1474TEST_F(WebSocketChannelEventInterfaceTest, SendCloseDropsChannel) {
Bence Béky8f9d7d3952017-10-09 19:58:041475 set_stream(std::make_unique<EchoeyFakeWebSocketStream>());
[email protected]999bcaa2013-07-17 13:42:541476 {
1477 InSequence s;
tyoshinoc06da562015-03-06 06:02:421478 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191479 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]999bcaa2013-07-17 13:42:541480 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161481 OnDropChannel(true, kWebSocketNormalClosure, "Fred"));
[email protected]999bcaa2013-07-17 13:42:541482 }
1483
1484 CreateChannelAndConnectSuccessfully();
1485
yhiranod2727df2016-04-11 05:32:491486 ASSERT_EQ(CHANNEL_ALIVE,
1487 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Fred"));
fdoray92e35a72016-06-10 15:54:551488 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541489}
1490
[email protected]6dfd8b32014-02-05 11:24:491491// StartClosingHandshake() also works before connection completes, and calls
1492// OnDropChannel.
1493TEST_F(WebSocketChannelEventInterfaceTest, CloseDuringConnection) {
1494 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161495 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""));
[email protected]6dfd8b32014-02-05 11:24:491496
1497 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:491498 ASSERT_EQ(CHANNEL_DELETED,
1499 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Joe"));
[email protected]6dfd8b32014-02-05 11:24:491500}
1501
[email protected]c0d29c22013-07-26 20:40:411502// OnDropChannel() is only called once when a write() on the socket triggers a
1503// connection reset.
1504TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
Bence Béky8f9d7d3952017-10-09 19:58:041505 set_stream(std::make_unique<ResetOnWriteFakeWebSocketStream>());
tyoshinoc06da562015-03-06 06:02:421506 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191507 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]c0d29c22013-07-26 20:40:411508
1509 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161510 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""))
[email protected]c0d29c22013-07-26 20:40:411511 .Times(1);
1512
1513 CreateChannelAndConnectSuccessfully();
1514
darin0da77e922016-10-04 17:31:231515 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1516 AsIOBuffer("yt?"), 3U);
fdoray92e35a72016-06-10 15:54:551517 base::RunLoop().RunUntilIdle();
[email protected]c0d29c22013-07-26 20:40:411518}
1519
1520// When the remote server sends a Close frame with an empty payload,
1521// WebSocketChannel should report code 1005, kWebSocketErrorNoStatusReceived.
1522TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
Bence Béky65623972018-03-05 15:31:561523 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281524 static const InitFrame frames[] = {
1525 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
1526 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
[email protected]c0d29c22013-07-26 20:40:411527 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1528 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481529 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421530 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191531 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]c0d29c22013-07-26 20:40:411532 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1533 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161534 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
[email protected]c0d29c22013-07-26 20:40:411535
1536 CreateChannelAndConnectSuccessfully();
1537}
1538
danakj9c5cab52016-04-16 00:54:331539// A version of the above test with null payload.
[email protected]00f4daf2013-11-12 13:56:411540TEST_F(WebSocketChannelEventInterfaceTest,
1541 CloseWithNullPayloadGivesStatus1005) {
Bence Béky65623972018-03-05 15:31:561542 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]00f4daf2013-11-12 13:56:411543 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:331544 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411545 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1546 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1547 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481548 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421549 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191550 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]00f4daf2013-11-12 13:56:411551 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1552 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161553 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
[email protected]00f4daf2013-11-12 13:56:411554
1555 CreateChannelAndConnectSuccessfully();
1556}
1557
[email protected]ea56b982014-01-27 03:21:031558// If ReadFrames() returns ERR_WS_PROTOCOL_ERROR, then the connection must be
1559// failed.
[email protected]2f5d9f62013-09-26 12:14:281560TEST_F(WebSocketChannelEventInterfaceTest, SyncProtocolErrorGivesStatus1002) {
Bence Béky65623972018-03-05 15:31:561561 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281562 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1563 ERR_WS_PROTOCOL_ERROR);
dchengc7eeda422015-12-26 03:56:481564 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421565 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191566 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]2f5d9f62013-09-26 12:14:281567
[email protected]ea56b982014-01-27 03:21:031568 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
[email protected]2f5d9f62013-09-26 12:14:281569
1570 CreateChannelAndConnectSuccessfully();
1571}
1572
1573// Async version of above test.
1574TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) {
Bence Béky65623972018-03-05 15:31:561575 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]2f5d9f62013-09-26 12:14:281576 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1577 ERR_WS_PROTOCOL_ERROR);
dchengc7eeda422015-12-26 03:56:481578 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421579 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191580 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]2f5d9f62013-09-26 12:14:281581
[email protected]ea56b982014-01-27 03:21:031582 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
[email protected]2f5d9f62013-09-26 12:14:281583
1584 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551585 base::RunLoop().RunUntilIdle();
[email protected]2f5d9f62013-09-26 12:14:281586}
1587
[email protected]cd48ed12014-01-22 14:34:221588TEST_F(WebSocketChannelEventInterfaceTest, StartHandshakeRequest) {
1589 {
1590 InSequence s;
tyoshinoc06da562015-03-06 06:02:421591 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191592 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]cd48ed12014-01-22 14:34:221593 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
1594 }
1595
1596 CreateChannelAndConnectSuccessfully();
1597
Bence Béky65623972018-03-05 15:31:561598 auto request_info = std::make_unique<WebSocketHandshakeRequestInfo>(
1599 GURL("ws://www.example.com/"), base::Time());
tyoshinoccfcfde2016-07-21 14:06:551600 connect_data_.argument_saver.connect_delegate->OnStartOpeningHandshake(
dchengc7eeda422015-12-26 03:56:481601 std::move(request_info));
[email protected]cd48ed12014-01-22 14:34:221602
fdoray92e35a72016-06-10 15:54:551603 base::RunLoop().RunUntilIdle();
[email protected]cd48ed12014-01-22 14:34:221604}
1605
1606TEST_F(WebSocketChannelEventInterfaceTest, FinishHandshakeRequest) {
1607 {
1608 InSequence s;
tyoshinoc06da562015-03-06 06:02:421609 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191610 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]cd48ed12014-01-22 14:34:221611 EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
1612 }
1613
1614 CreateChannelAndConnectSuccessfully();
1615
Yutaka Hirano208d4dce2018-05-24 09:22:121616 auto response_headers =
1617 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
Bence Béky65623972018-03-05 15:31:561618 auto response_info = std::make_unique<WebSocketHandshakeResponseInfo>(
Tsuyoshi Horo01faed62019-02-20 22:11:371619 GURL("ws://www.example.com/"), response_headers, IPEndPoint(),
Yutaka Hirano36c94952018-05-30 21:33:331620 base::Time());
tyoshinoccfcfde2016-07-21 14:06:551621 connect_data_.argument_saver.connect_delegate->OnFinishOpeningHandshake(
dchengc7eeda422015-12-26 03:56:481622 std::move(response_info));
fdoray92e35a72016-06-10 15:54:551623 base::RunLoop().RunUntilIdle();
[email protected]cd48ed12014-01-22 14:34:221624}
1625
1626TEST_F(WebSocketChannelEventInterfaceTest, FailJustAfterHandshake) {
1627 {
1628 InSequence s;
1629 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
1630 EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
1631 EXPECT_CALL(*event_interface_, OnFailChannel("bye"));
1632 }
1633
1634 CreateChannelAndConnect();
1635
1636 WebSocketStream::ConnectDelegate* connect_delegate =
tyoshinoccfcfde2016-07-21 14:06:551637 connect_data_.argument_saver.connect_delegate.get();
[email protected]cd48ed12014-01-22 14:34:221638 GURL url("ws://www.example.com/");
Bence Béky65623972018-03-05 15:31:561639 auto request_info =
1640 std::make_unique<WebSocketHandshakeRequestInfo>(url, base::Time());
Yutaka Hirano208d4dce2018-05-24 09:22:121641 auto response_headers =
1642 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
Bence Béky65623972018-03-05 15:31:561643 auto response_info = std::make_unique<WebSocketHandshakeResponseInfo>(
Tsuyoshi Horo01faed62019-02-20 22:11:371644 url, response_headers, IPEndPoint(), base::Time());
dchengc7eeda422015-12-26 03:56:481645 connect_delegate->OnStartOpeningHandshake(std::move(request_info));
1646 connect_delegate->OnFinishOpeningHandshake(std::move(response_info));
[email protected]cd48ed12014-01-22 14:34:221647
1648 connect_delegate->OnFailure("bye");
fdoray92e35a72016-06-10 15:54:551649 base::RunLoop().RunUntilIdle();
[email protected]cd48ed12014-01-22 14:34:221650}
1651
[email protected]ea56b982014-01-27 03:21:031652// Any frame after close is invalid. This test uses a Text frame. See also
1653// test "PingAfterCloseIfRejected".
1654TEST_F(WebSocketChannelEventInterfaceTest, DataAfterCloseIsRejected) {
Bence Béky65623972018-03-05 15:31:561655 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]ea56b982014-01-27 03:21:031656 static const InitFrame frames[] = {
1657 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1658 CLOSE_DATA(NORMAL_CLOSURE, "OK")},
1659 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "Payload"}};
1660 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481661 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421662 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191663 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]ea56b982014-01-27 03:21:031664
1665 {
1666 InSequence s;
1667 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1668 EXPECT_CALL(*event_interface_,
1669 OnFailChannel("Data frame received after close"));
1670 }
1671
1672 CreateChannelAndConnectSuccessfully();
1673}
1674
1675// A Close frame with a one-byte payload elicits a specific console error
1676// message.
1677TEST_F(WebSocketChannelEventInterfaceTest, OneByteClosePayloadMessage) {
Bence Béky65623972018-03-05 15:31:561678 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]ea56b982014-01-27 03:21:031679 static const InitFrame frames[] = {
1680 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, "\x03"}};
1681 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481682 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421683 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191684 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]ea56b982014-01-27 03:21:031685 EXPECT_CALL(
1686 *event_interface_,
1687 OnFailChannel(
1688 "Received a broken close frame containing an invalid size body."));
1689
1690 CreateChannelAndConnectSuccessfully();
1691}
1692
1693// A Close frame with a reserved status code also elicits a specific console
1694// error message.
1695TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadReservedStatusMessage) {
Bence Béky65623972018-03-05 15:31:561696 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]ea56b982014-01-27 03:21:031697 static const InitFrame frames[] = {
1698 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1699 NOT_MASKED, CLOSE_DATA(ABNORMAL_CLOSURE, "Not valid on wire")}};
1700 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481701 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421702 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191703 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]ea56b982014-01-27 03:21:031704 EXPECT_CALL(
1705 *event_interface_,
1706 OnFailChannel(
1707 "Received a broken close frame containing a reserved status code."));
1708
1709 CreateChannelAndConnectSuccessfully();
1710}
1711
1712// A Close frame with invalid UTF-8 also elicits a specific console error
1713// message.
1714TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadInvalidReason) {
Bence Béky65623972018-03-05 15:31:561715 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]ea56b982014-01-27 03:21:031716 static const InitFrame frames[] = {
1717 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1718 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
1719 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481720 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421721 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191722 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]ea56b982014-01-27 03:21:031723 EXPECT_CALL(
1724 *event_interface_,
1725 OnFailChannel(
1726 "Received a broken close frame containing invalid UTF-8."));
1727
1728 CreateChannelAndConnectSuccessfully();
1729}
1730
[email protected]658d7672014-02-26 13:11:351731// The reserved bits must all be clear on received frames. Extensions should
1732// clear the bits when they are set correctly before passing on the frame.
1733TEST_F(WebSocketChannelEventInterfaceTest, ReservedBitsMustNotBeSet) {
Bence Béky65623972018-03-05 15:31:561734 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]658d7672014-02-26 13:11:351735 static const InitFrame frames[] = {
1736 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1737 NOT_MASKED, "sakana"}};
1738 // It is not worth adding support for reserved bits to InitFrame just for this
1739 // one test, so set the bit manually.
danakj9c5cab52016-04-16 00:54:331740 std::vector<std::unique_ptr<WebSocketFrame>> raw_frames =
yhirano592ff7f2015-12-07 08:45:191741 CreateFrameVector(frames);
[email protected]658d7672014-02-26 13:11:351742 raw_frames[0]->header.reserved1 = true;
yhirano592ff7f2015-12-07 08:45:191743 stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
1744 std::move(raw_frames));
dchengc7eeda422015-12-26 03:56:481745 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421746 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191747 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]c46c2612014-02-28 17:08:021748 EXPECT_CALL(*event_interface_,
1749 OnFailChannel(
1750 "One or more reserved bits are on: reserved1 = 1, "
1751 "reserved2 = 0, reserved3 = 0"));
[email protected]658d7672014-02-26 13:11:351752
1753 CreateChannelAndConnectSuccessfully();
1754}
1755
[email protected]3a266762013-10-23 08:15:101756// The closing handshake times out and sends an OnDropChannel event if no
1757// response to the client Close message is received.
1758TEST_F(WebSocketChannelEventInterfaceTest,
1759 ClientInitiatedClosingHandshakeTimesOut) {
Bence Béky65623972018-03-05 15:31:561760 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]3a266762013-10-23 08:15:101761 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1762 ERR_IO_PENDING);
dchengc7eeda422015-12-26 03:56:481763 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421764 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191765 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]3a266762013-10-23 08:15:101766 // This checkpoint object verifies that the OnDropChannel message comes after
1767 // the timeout.
[email protected]f485985e2013-10-24 13:47:441768 Checkpoint checkpoint;
[email protected]3a266762013-10-23 08:15:101769 TestClosure completion;
1770 {
1771 InSequence s;
1772 EXPECT_CALL(checkpoint, Call(1));
1773 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161774 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _))
Yutaka Hirano4165de92018-04-10 11:46:491775 .WillOnce(InvokeClosure(completion.closure()));
[email protected]3a266762013-10-23 08:15:101776 }
1777 CreateChannelAndConnectSuccessfully();
1778 // OneShotTimer is not very friendly to testing; there is no apparent way to
1779 // set an expectation on it. Instead the tests need to infer that the timeout
1780 // was fired by the behaviour of the WebSocketChannel object.
1781 channel_->SetClosingHandshakeTimeoutForTesting(
1782 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
tyoshinod4d1d302014-11-07 04:31:161783 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
1784 TimeDelta::FromMilliseconds(kVeryBigTimeoutMillis));
yhiranod2727df2016-04-11 05:32:491785 ASSERT_EQ(CHANNEL_ALIVE,
1786 channel_->StartClosingHandshake(kWebSocketNormalClosure, ""));
[email protected]3a266762013-10-23 08:15:101787 checkpoint.Call(1);
1788 completion.WaitForResult();
1789}
1790
1791// The closing handshake times out and sends an OnDropChannel event if a Close
1792// message is received but the connection isn't closed by the remote host.
1793TEST_F(WebSocketChannelEventInterfaceTest,
1794 ServerInitiatedClosingHandshakeTimesOut) {
Bence Béky65623972018-03-05 15:31:561795 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]3a266762013-10-23 08:15:101796 static const InitFrame frames[] = {
1797 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1798 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
1799 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481800 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421801 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191802 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]f485985e2013-10-24 13:47:441803 Checkpoint checkpoint;
[email protected]3a266762013-10-23 08:15:101804 TestClosure completion;
1805 {
1806 InSequence s;
1807 EXPECT_CALL(checkpoint, Call(1));
1808 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1809 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161810 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _))
Yutaka Hirano4165de92018-04-10 11:46:491811 .WillOnce(InvokeClosure(completion.closure()));
[email protected]3a266762013-10-23 08:15:101812 }
1813 CreateChannelAndConnectSuccessfully();
1814 channel_->SetClosingHandshakeTimeoutForTesting(
tyoshinod4d1d302014-11-07 04:31:161815 TimeDelta::FromMilliseconds(kVeryBigTimeoutMillis));
1816 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
[email protected]3a266762013-10-23 08:15:101817 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
1818 checkpoint.Call(1);
1819 completion.WaitForResult();
1820}
1821
[email protected]4256dbb2014-03-24 15:39:361822// If for some reason the connect succeeds before the renderer sends us quota,
1823// we shouldn't call ReadFrames() immediately.
1824// TODO(ricea): Actually we should call ReadFrames() with a small limit so we
1825// can still handle control frames. This should be done once we have any API to
1826// expose quota to the lower levels.
1827TEST_F(WebSocketChannelStreamTest, FlowControlLate) {
1828 Checkpoint checkpoint;
1829 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
1830 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
1831 {
1832 InSequence s;
1833 EXPECT_CALL(checkpoint, Call(1));
Bence Békyf4f56e22018-07-17 02:00:051834 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]4256dbb2014-03-24 15:39:361835 .WillOnce(Return(ERR_IO_PENDING));
1836 EXPECT_CALL(checkpoint, Call(2));
1837 }
1838
dchengc7eeda422015-12-26 03:56:481839 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:361840 CreateChannelAndConnect();
tyoshinoccfcfde2016-07-21 14:06:551841 connect_data_.argument_saver.connect_delegate->OnSuccess(std::move(stream_));
[email protected]4256dbb2014-03-24 15:39:361842 checkpoint.Call(1);
Yoichi Osatocf55e6da2019-05-30 00:17:421843 ASSERT_EQ(CHANNEL_ALIVE,
1844 channel_->AddReceiveFlowControlQuota(kPlentyOfQuota));
[email protected]4256dbb2014-03-24 15:39:361845 checkpoint.Call(2);
1846}
1847
1848// We should stop calling ReadFrames() when all quota is used.
1849TEST_F(WebSocketChannelStreamTest, FlowControlStopsReadFrames) {
1850 static const InitFrame frames[] = {
1851 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
1852
1853 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
1854 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:051855 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]4256dbb2014-03-24 15:39:361856 .WillOnce(ReturnFrames(&frames));
1857
dchengc7eeda422015-12-26 03:56:481858 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:361859 CreateChannelAndConnect();
tyoshinoccfcfde2016-07-21 14:06:551860 connect_data_.argument_saver.connect_delegate->OnSuccess(std::move(stream_));
Yutaka Hiranodfa67e52019-07-29 03:13:261861 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(4));
[email protected]4256dbb2014-03-24 15:39:361862}
1863
1864// Providing extra quota causes ReadFrames() to be called again.
1865TEST_F(WebSocketChannelStreamTest, FlowControlStartsWithMoreQuota) {
1866 static const InitFrame frames[] = {
1867 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
1868 Checkpoint checkpoint;
1869
1870 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
1871 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
1872 {
1873 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:051874 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]4256dbb2014-03-24 15:39:361875 .WillOnce(ReturnFrames(&frames));
1876 EXPECT_CALL(checkpoint, Call(1));
Bence Békyf4f56e22018-07-17 02:00:051877 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]4256dbb2014-03-24 15:39:361878 .WillOnce(Return(ERR_IO_PENDING));
1879 }
1880
dchengc7eeda422015-12-26 03:56:481881 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:361882 CreateChannelAndConnect();
tyoshinoccfcfde2016-07-21 14:06:551883 connect_data_.argument_saver.connect_delegate->OnSuccess(std::move(stream_));
Yutaka Hiranodfa67e52019-07-29 03:13:261884 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(4));
[email protected]4256dbb2014-03-24 15:39:361885 checkpoint.Call(1);
Yoichi Osatocf55e6da2019-05-30 00:17:421886 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(4));
[email protected]4256dbb2014-03-24 15:39:361887}
1888
1889// ReadFrames() isn't called again until all pending data has been passed to
1890// the renderer.
1891TEST_F(WebSocketChannelStreamTest, ReadFramesNotCalledUntilQuotaAvailable) {
1892 static const InitFrame frames[] = {
1893 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
1894 Checkpoint checkpoint;
1895
1896 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
1897 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
1898 {
1899 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:051900 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]4256dbb2014-03-24 15:39:361901 .WillOnce(ReturnFrames(&frames));
1902 EXPECT_CALL(checkpoint, Call(1));
1903 EXPECT_CALL(checkpoint, Call(2));
Bence Békyf4f56e22018-07-17 02:00:051904 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]4256dbb2014-03-24 15:39:361905 .WillOnce(Return(ERR_IO_PENDING));
1906 }
1907
dchengc7eeda422015-12-26 03:56:481908 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:361909 CreateChannelAndConnect();
tyoshinoccfcfde2016-07-21 14:06:551910 connect_data_.argument_saver.connect_delegate->OnSuccess(std::move(stream_));
Yutaka Hiranodfa67e52019-07-29 03:13:261911 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(2));
[email protected]4256dbb2014-03-24 15:39:361912 checkpoint.Call(1);
Yoichi Osatocf55e6da2019-05-30 00:17:421913 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(2));
[email protected]4256dbb2014-03-24 15:39:361914 checkpoint.Call(2);
Yoichi Osatocf55e6da2019-05-30 00:17:421915 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(2));
[email protected]4256dbb2014-03-24 15:39:361916}
1917
1918// A message that needs to be split into frames to fit within quota should
1919// maintain correct semantics.
1920TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitSync) {
Bence Béky65623972018-03-05 15:31:561921 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]4256dbb2014-03-24 15:39:361922 static const InitFrame frames[] = {
1923 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
1924 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481925 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:361926 {
1927 InSequence s;
tyoshinoc06da562015-03-06 06:02:421928 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191929 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
darin0da77e922016-10-04 17:31:231930 EXPECT_CALL(*event_interface_,
1931 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1932 AsVector("FO")));
[email protected]4256dbb2014-03-24 15:39:361933 EXPECT_CALL(
1934 *event_interface_,
darin0da77e922016-10-04 17:31:231935 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1936 AsVector("U")));
[email protected]4256dbb2014-03-24 15:39:361937 EXPECT_CALL(
1938 *event_interface_,
darin0da77e922016-10-04 17:31:231939 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
1940 AsVector("R")));
[email protected]4256dbb2014-03-24 15:39:361941 }
1942
1943 CreateChannelAndConnectWithQuota(2);
Yoichi Osatocf55e6da2019-05-30 00:17:421944 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(1));
1945 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(1));
[email protected]4256dbb2014-03-24 15:39:361946}
1947
1948// The code path for async messages is slightly different, so test it
1949// separately.
1950TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitAsync) {
Bence Béky65623972018-03-05 15:31:561951 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]4256dbb2014-03-24 15:39:361952 static const InitFrame frames[] = {
1953 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
1954 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481955 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:361956 Checkpoint checkpoint;
1957 {
1958 InSequence s;
tyoshinoc06da562015-03-06 06:02:421959 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:191960 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]4256dbb2014-03-24 15:39:361961 EXPECT_CALL(checkpoint, Call(1));
darin0da77e922016-10-04 17:31:231962 EXPECT_CALL(*event_interface_,
1963 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1964 AsVector("FO")));
[email protected]4256dbb2014-03-24 15:39:361965 EXPECT_CALL(checkpoint, Call(2));
1966 EXPECT_CALL(
1967 *event_interface_,
darin0da77e922016-10-04 17:31:231968 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1969 AsVector("U")));
[email protected]4256dbb2014-03-24 15:39:361970 EXPECT_CALL(checkpoint, Call(3));
1971 EXPECT_CALL(
1972 *event_interface_,
darin0da77e922016-10-04 17:31:231973 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
1974 AsVector("R")));
[email protected]4256dbb2014-03-24 15:39:361975 }
1976
1977 CreateChannelAndConnectWithQuota(2);
1978 checkpoint.Call(1);
fdoray92e35a72016-06-10 15:54:551979 base::RunLoop().RunUntilIdle();
[email protected]4256dbb2014-03-24 15:39:361980 checkpoint.Call(2);
Yoichi Osatocf55e6da2019-05-30 00:17:421981 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(1));
[email protected]4256dbb2014-03-24 15:39:361982 checkpoint.Call(3);
Yoichi Osatocf55e6da2019-05-30 00:17:421983 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(1));
[email protected]4256dbb2014-03-24 15:39:361984}
1985
1986// A message split into multiple frames which is further split due to quota
1987// restrictions should stil be correct.
1988// TODO(ricea): The message ends up split into more frames than are strictly
1989// necessary. The complexity/performance tradeoffs here need further
1990// examination.
1991TEST_F(WebSocketChannelFlowControlTest, MultipleFrameSplit) {
Bence Béky65623972018-03-05 15:31:561992 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]4256dbb2014-03-24 15:39:361993 static const InitFrame frames[] = {
1994 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1995 NOT_MASKED, "FIRST FRAME IS 25 BYTES. "},
1996 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1997 NOT_MASKED, "SECOND FRAME IS 26 BYTES. "},
1998 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1999 NOT_MASKED, "FINAL FRAME IS 24 BYTES."}};
2000 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482001 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:362002 {
2003 InSequence s;
tyoshinoc06da562015-03-06 06:02:422004 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192005 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]4256dbb2014-03-24 15:39:362006 EXPECT_CALL(*event_interface_,
darin0da77e922016-10-04 17:31:232007 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
2008 AsVector("FIRST FRAME IS")));
2009 EXPECT_CALL(
2010 *event_interface_,
2011 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
2012 AsVector(" 25 BYTES. ")));
2013 EXPECT_CALL(
2014 *event_interface_,
2015 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
2016 AsVector("SECOND FRAME IS 26 BYTES. ")));
2017 EXPECT_CALL(
2018 *event_interface_,
2019 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
2020 AsVector("FINAL ")));
2021 EXPECT_CALL(
2022 *event_interface_,
2023 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
2024 AsVector("FRAME IS 24 BYTES.")));
[email protected]4256dbb2014-03-24 15:39:362025 }
2026 CreateChannelAndConnectWithQuota(14);
Yoichi Osatocf55e6da2019-05-30 00:17:422027 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(43));
2028 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(32));
[email protected]4256dbb2014-03-24 15:39:362029}
2030
2031// An empty message handled when we are out of quota must not be delivered
2032// out-of-order with respect to other messages.
2033TEST_F(WebSocketChannelFlowControlTest, EmptyMessageNoQuota) {
Bence Béky65623972018-03-05 15:31:562034 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]4256dbb2014-03-24 15:39:362035 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:332036 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2037 "FIRST MESSAGE"},
2038 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr},
2039 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2040 "THIRD MESSAGE"}};
[email protected]4256dbb2014-03-24 15:39:362041 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482042 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:362043 {
2044 InSequence s;
tyoshinoc06da562015-03-06 06:02:422045 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192046 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
[email protected]4256dbb2014-03-24 15:39:362047 EXPECT_CALL(*event_interface_,
darin0da77e922016-10-04 17:31:232048 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
2049 AsVector("FIRST ")));
2050 EXPECT_CALL(
2051 *event_interface_,
2052 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
2053 AsVector("MESSAGE")));
[email protected]4256dbb2014-03-24 15:39:362054 EXPECT_CALL(*event_interface_,
darin0da77e922016-10-04 17:31:232055 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
2056 AsVector("")));
[email protected]4256dbb2014-03-24 15:39:362057 EXPECT_CALL(*event_interface_,
darin0da77e922016-10-04 17:31:232058 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
2059 AsVector("THIRD MESSAGE")));
[email protected]4256dbb2014-03-24 15:39:362060 }
2061
2062 CreateChannelAndConnectWithQuota(6);
Yoichi Osatocf55e6da2019-05-30 00:17:422063 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(128));
yhiranod2727df2016-04-11 05:32:492064}
2065
2066// A close frame should not overtake data frames.
2067TEST_F(WebSocketChannelFlowControlTest, CloseFrameShouldNotOvertakeDataFrames) {
Bence Béky65623972018-03-05 15:31:562068 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
yhiranod2727df2016-04-11 05:32:492069 static const InitFrame frames[] = {
2070 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2071 "FIRST "},
2072 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED,
2073 "MESSAGE"},
2074 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2075 "SECOND "},
2076 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
2077 CLOSE_DATA(NORMAL_CLOSURE, "GOOD BYE")},
2078 };
2079 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2080 set_stream(std::move(stream));
2081 Checkpoint checkpoint;
2082 InSequence s;
2083 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192084 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
yhiranod2727df2016-04-11 05:32:492085 EXPECT_CALL(*event_interface_,
darin0da77e922016-10-04 17:31:232086 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
2087 AsVector("FIRST ")));
yhiranod2727df2016-04-11 05:32:492088 EXPECT_CALL(checkpoint, Call(1));
yhiranod2727df2016-04-11 05:32:492089 EXPECT_CALL(
2090 *event_interface_,
darin0da77e922016-10-04 17:31:232091 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
2092 AsVector("MESSAG")));
2093 EXPECT_CALL(checkpoint, Call(2));
yhiranod2727df2016-04-11 05:32:492094 EXPECT_CALL(*event_interface_,
darin0da77e922016-10-04 17:31:232095 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
2096 AsVector("E")));
2097 EXPECT_CALL(*event_interface_,
2098 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
2099 AsVector("SECON")));
2100 EXPECT_CALL(checkpoint, Call(3));
2101 EXPECT_CALL(
2102 *event_interface_,
2103 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
2104 AsVector("D ")));
yhiranod2727df2016-04-11 05:32:492105 EXPECT_CALL(*event_interface_, OnClosingHandshake());
2106 EXPECT_CALL(checkpoint, Call(4));
2107
2108 CreateChannelAndConnectWithQuota(6);
2109 checkpoint.Call(1);
Yoichi Osatocf55e6da2019-05-30 00:17:422110 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(6));
yhiranod2727df2016-04-11 05:32:492111 checkpoint.Call(2);
Yoichi Osatocf55e6da2019-05-30 00:17:422112 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(6));
yhiranod2727df2016-04-11 05:32:492113 checkpoint.Call(3);
Yoichi Osatocf55e6da2019-05-30 00:17:422114 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(6));
yhiranod2727df2016-04-11 05:32:492115 checkpoint.Call(4);
[email protected]4256dbb2014-03-24 15:39:362116}
2117
landellcce7ad62017-04-28 12:07:382118// SendFlowControl calls should not trigger multiple close respond frames.
2119TEST_F(WebSocketChannelFlowControlTest, DoNotSendMultipleCloseRespondFrames) {
Bence Béky65623972018-03-05 15:31:562120 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
landellcce7ad62017-04-28 12:07:382121 static constexpr InitFrame frames[] = {
2122 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2123 "FIRST SECOND"},
2124 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
2125 CLOSE_DATA(NORMAL_CLOSURE, "GOOD BYE")},
2126 };
2127 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2128 set_stream(std::move(stream));
2129 Checkpoint checkpoint;
2130 InSequence s;
2131 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192132 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
landellcce7ad62017-04-28 12:07:382133 EXPECT_CALL(*event_interface_,
2134 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
2135 AsVector("FIRST ")));
2136 EXPECT_CALL(checkpoint, Call(1));
2137 EXPECT_CALL(*event_interface_,
2138 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
2139 AsVector("SECOND")));
2140 EXPECT_CALL(*event_interface_, OnClosingHandshake());
2141 EXPECT_CALL(checkpoint, Call(2));
2142
2143 CreateChannelAndConnectWithQuota(6);
2144 checkpoint.Call(1);
Yoichi Osatocf55e6da2019-05-30 00:17:422145 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(6));
landellcce7ad62017-04-28 12:07:382146 checkpoint.Call(2);
Yoichi Osatocf55e6da2019-05-30 00:17:422147 ASSERT_EQ(CHANNEL_ALIVE, channel_->AddReceiveFlowControlQuota(6));
landellcce7ad62017-04-28 12:07:382148}
2149
[email protected]999bcaa2013-07-17 13:42:542150// RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
2151// WebSocketChannel actually only sets the mask bit in the header, it doesn't
2152// perform masking itself (not all transports actually use masking).
2153TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
[email protected]2f5d9f62013-09-26 12:14:282154 static const InitFrame expected[] = {
2155 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2156 MASKED, "NEEDS MASKING"}};
[email protected]999bcaa2013-07-17 13:42:542157 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212158 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052159 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2160 .WillOnce(Return(ERR_IO_PENDING));
2161 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412162 .WillOnce(Return(OK));
[email protected]999bcaa2013-07-17 13:42:542163
2164 CreateChannelAndConnectSuccessfully();
darin0da77e922016-10-04 17:31:232165 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2166 AsIOBuffer("NEEDS MASKING"), 13U);
[email protected]999bcaa2013-07-17 13:42:542167}
2168
[email protected]c0d29c22013-07-26 20:40:412169// RFC6455 5.5.1 "The application MUST NOT send any more data frames after
2170// sending a Close frame."
2171TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
[email protected]2f5d9f62013-09-26 12:14:282172 static const InitFrame expected[] = {
2173 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2174 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
[email protected]c0d29c22013-07-26 20:40:412175 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212176 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052177 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2178 .WillOnce(Return(ERR_IO_PENDING));
2179 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412180 .WillOnce(Return(OK));
2181
2182 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:492183 ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(1000, "Success"));
darin0da77e922016-10-04 17:31:232184 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2185 AsIOBuffer("SHOULD BE IGNORED"), 18U);
[email protected]c0d29c22013-07-26 20:40:412186}
2187
2188// RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
2189// send a Close frame, the endpoint MUST send a Close frame in response."
2190TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
[email protected]2f5d9f62013-09-26 12:14:282191 static const InitFrame frames[] = {
2192 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2193 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2194 static const InitFrame expected[] = {
2195 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2196 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
[email protected]c0d29c22013-07-26 20:40:412197 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212198 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052199 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]2f5d9f62013-09-26 12:14:282200 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:412201 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052202 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412203 .WillOnce(Return(OK));
2204
2205 CreateChannelAndConnectSuccessfully();
2206}
2207
2208// The converse of the above case; after sending a Close frame, we should not
2209// send another one.
2210TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
[email protected]2f5d9f62013-09-26 12:14:282211 static const InitFrame expected[] = {
2212 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2213 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2214 static const InitFrame frames_init[] = {
2215 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2216 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
[email protected]c0d29c22013-07-26 20:40:412217
2218 // We store the parameters that were passed to ReadFrames() so that we can
2219 // call them explicitly later.
Bence Békyf4f56e22018-07-17 02:00:052220 CompletionOnceCallback read_callback;
danakj9c5cab52016-04-16 00:54:332221 std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
[email protected]c0d29c22013-07-26 20:40:412222
[email protected]6c5d9f62014-01-27 15:05:212223 // These are not interesting.
2224 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2225 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2226
[email protected]c0d29c22013-07-26 20:40:412227 // Use a checkpoint to make the ordering of events clearer.
[email protected]f485985e2013-10-24 13:47:442228 Checkpoint checkpoint;
[email protected]c0d29c22013-07-26 20:40:412229 {
2230 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:052231 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2232 .WillOnce(DoAll(SaveArg<0>(&frames), SaveArg<1>(&read_callback),
[email protected]c0d29c22013-07-26 20:40:412233 Return(ERR_IO_PENDING)));
2234 EXPECT_CALL(checkpoint, Call(1));
Bence Békyf4f56e22018-07-17 02:00:052235 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412236 .WillOnce(Return(OK));
2237 EXPECT_CALL(checkpoint, Call(2));
Bence Békyf4f56e22018-07-17 02:00:052238 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]c0d29c22013-07-26 20:40:412239 .WillOnce(Return(ERR_IO_PENDING));
2240 EXPECT_CALL(checkpoint, Call(3));
2241 // WriteFrames() must not be called again. GoogleMock will ensure that the
2242 // test fails if it is.
2243 }
2244
2245 CreateChannelAndConnectSuccessfully();
2246 checkpoint.Call(1);
yhiranod2727df2016-04-11 05:32:492247 ASSERT_EQ(CHANNEL_ALIVE,
2248 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close"));
[email protected]c0d29c22013-07-26 20:40:412249 checkpoint.Call(2);
2250
[email protected]2f5d9f62013-09-26 12:14:282251 *frames = CreateFrameVector(frames_init);
Bence Békyf4f56e22018-07-17 02:00:052252 std::move(read_callback).Run(OK);
[email protected]c0d29c22013-07-26 20:40:412253 checkpoint.Call(3);
2254}
2255
[email protected]3de65092013-10-24 09:39:442256// Invalid close status codes should not be sent on the network.
2257TEST_F(WebSocketChannelStreamTest, InvalidCloseStatusCodeNotSent) {
2258 static const InitFrame expected[] = {
2259 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
[email protected]ea56b982014-01-27 03:21:032260 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
[email protected]3de65092013-10-24 09:39:442261
2262 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212263 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052264 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]3de65092013-10-24 09:39:442265 .WillOnce(Return(ERR_IO_PENDING));
2266
Bence Békyf4f56e22018-07-17 02:00:052267 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _));
[email protected]3de65092013-10-24 09:39:442268
2269 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:492270 ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(999, ""));
[email protected]3de65092013-10-24 09:39:442271}
2272
2273// A Close frame with a reason longer than 123 bytes cannot be sent on the
2274// network.
2275TEST_F(WebSocketChannelStreamTest, LongCloseReasonNotSent) {
2276 static const InitFrame expected[] = {
2277 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
[email protected]ea56b982014-01-27 03:21:032278 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
[email protected]3de65092013-10-24 09:39:442279
2280 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212281 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052282 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]3de65092013-10-24 09:39:442283 .WillOnce(Return(ERR_IO_PENDING));
2284
Bence Békyf4f56e22018-07-17 02:00:052285 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _));
[email protected]3de65092013-10-24 09:39:442286
2287 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:492288 ASSERT_EQ(CHANNEL_ALIVE,
2289 channel_->StartClosingHandshake(1000, std::string(124, 'A')));
[email protected]3de65092013-10-24 09:39:442290}
2291
[email protected]c0d29c22013-07-26 20:40:412292// We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no
2293// status in the Close message from the other side. Code 1005 is not allowed to
2294// appear on the wire, so we should not echo it back. See test
2295// CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is
2296// correctly generated internally.
2297TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
[email protected]2f5d9f62013-09-26 12:14:282298 static const InitFrame frames[] = {
2299 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
2300 static const InitFrame expected[] = {
2301 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
[email protected]c0d29c22013-07-26 20:40:412302 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212303 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052304 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]2f5d9f62013-09-26 12:14:282305 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:412306 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052307 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412308 .WillOnce(Return(OK));
2309
2310 CreateChannelAndConnectSuccessfully();
2311}
2312
[email protected]00f4daf2013-11-12 13:56:412313TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoedNull) {
2314 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:332315 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:412316 static const InitFrame expected[] = {
2317 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
2318 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212319 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052320 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]00f4daf2013-11-12 13:56:412321 .WillOnce(ReturnFrames(&frames))
2322 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052323 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]00f4daf2013-11-12 13:56:412324 .WillOnce(Return(OK));
2325
2326 CreateChannelAndConnectSuccessfully();
2327}
2328
[email protected]ea56b982014-01-27 03:21:032329// Receiving an invalid UTF-8 payload in a Close frame causes us to fail the
2330// connection.
2331TEST_F(WebSocketChannelStreamTest, CloseFrameInvalidUtf8) {
2332 static const InitFrame frames[] = {
2333 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2334 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
2335 static const InitFrame expected[] = {
2336 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2337 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in Close frame")}};
2338
2339 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212340 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052341 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]ea56b982014-01-27 03:21:032342 .WillOnce(ReturnFrames(&frames))
2343 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052344 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]ea56b982014-01-27 03:21:032345 .WillOnce(Return(OK));
2346 EXPECT_CALL(*mock_stream_, Close());
2347
2348 CreateChannelAndConnectSuccessfully();
2349}
2350
[email protected]c0d29c22013-07-26 20:40:412351// RFC6455 5.5.2 "Upon receipt of a Ping frame, an endpoint MUST send a Pong
2352// frame in response"
2353// 5.5.3 "A Pong frame sent in response to a Ping frame must have identical
2354// "Application data" as found in the message body of the Ping frame being
2355// replied to."
2356TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) {
[email protected]2f5d9f62013-09-26 12:14:282357 static const InitFrame frames[] = {
2358 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2359 NOT_MASKED, "Application data"}};
2360 static const InitFrame expected[] = {
2361 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2362 MASKED, "Application data"}};
[email protected]c0d29c22013-07-26 20:40:412363 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212364 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052365 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]2f5d9f62013-09-26 12:14:282366 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:412367 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052368 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412369 .WillOnce(Return(OK));
2370
2371 CreateChannelAndConnectSuccessfully();
2372}
2373
danakj9c5cab52016-04-16 00:54:332374// A ping with a null payload should be responded to with a Pong with a null
[email protected]00f4daf2013-11-12 13:56:412375// payload.
[email protected]403ee6e2014-01-27 10:10:442376TEST_F(WebSocketChannelStreamTest, NullPingRepliedWithNullPong) {
[email protected]00f4daf2013-11-12 13:56:412377 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:332378 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:412379 static const InitFrame expected[] = {
danakj9c5cab52016-04-16 00:54:332380 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:412381 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212382 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052383 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]00f4daf2013-11-12 13:56:412384 .WillOnce(ReturnFrames(&frames))
2385 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052386 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]00f4daf2013-11-12 13:56:412387 .WillOnce(Return(OK));
2388
2389 CreateChannelAndConnectSuccessfully();
2390}
2391
[email protected]c0d29c22013-07-26 20:40:412392TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
[email protected]2f5d9f62013-09-26 12:14:282393 static const InitFrame frames[] = {
2394 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2395 NOT_MASKED, "Application data"}};
2396 static const InitFrame expected1[] = {
2397 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2398 static const InitFrame expected2[] = {
2399 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2400 MASKED, "Application data"}};
2401 static const InitFrame expected3[] = {
2402 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2403 MASKED, "World"}};
danakj9c5cab52016-04-16 00:54:332404 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames;
Bence Békyf4f56e22018-07-17 02:00:052405 CompletionOnceCallback read_callback;
[email protected]c0d29c22013-07-26 20:40:412406 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212407 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052408 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2409 .WillOnce(DoAll(SaveArg<0>(&read_frames), SaveArg<1>(&read_callback),
[email protected]c0d29c22013-07-26 20:40:412410 Return(ERR_IO_PENDING)))
2411 .WillRepeatedly(Return(ERR_IO_PENDING));
2412 {
2413 InSequence s;
2414
Bence Békyf4f56e22018-07-17 02:00:052415 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
[email protected]c0d29c22013-07-26 20:40:412416 .WillOnce(Return(OK));
Bence Békyf4f56e22018-07-17 02:00:052417 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
[email protected]c0d29c22013-07-26 20:40:412418 .WillOnce(Return(OK));
Bence Békyf4f56e22018-07-17 02:00:052419 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected3), _))
[email protected]c0d29c22013-07-26 20:40:412420 .WillOnce(Return(OK));
2421 }
2422
2423 CreateChannelAndConnectSuccessfully();
darin0da77e922016-10-04 17:31:232424 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2425 AsIOBuffer("Hello "), 6U);
[email protected]2f5d9f62013-09-26 12:14:282426 *read_frames = CreateFrameVector(frames);
Bence Békyf4f56e22018-07-17 02:00:052427 std::move(read_callback).Run(OK);
darin0da77e922016-10-04 17:31:232428 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2429 AsIOBuffer("World"), 5U);
[email protected]c0d29c22013-07-26 20:40:412430}
2431
2432// WriteFrames() may not be called until the previous write has completed.
2433// WebSocketChannel must buffer writes that happen in the meantime.
2434TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
[email protected]2f5d9f62013-09-26 12:14:282435 static const InitFrame expected1[] = {
2436 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2437 static const InitFrame expected2[] = {
2438 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}};
Bence Békyf4f56e22018-07-17 02:00:052439 CompletionOnceCallback write_callback;
[email protected]f485985e2013-10-24 13:47:442440 Checkpoint checkpoint;
[email protected]c0d29c22013-07-26 20:40:412441
2442 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212443 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052444 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2445 .WillOnce(Return(ERR_IO_PENDING));
[email protected]c0d29c22013-07-26 20:40:412446 {
2447 InSequence s;
2448 EXPECT_CALL(checkpoint, Call(1));
Bence Békyf4f56e22018-07-17 02:00:052449 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
[email protected]c0d29c22013-07-26 20:40:412450 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
2451 EXPECT_CALL(checkpoint, Call(2));
Bence Békyf4f56e22018-07-17 02:00:052452 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
[email protected]c0d29c22013-07-26 20:40:412453 .WillOnce(Return(ERR_IO_PENDING));
2454 EXPECT_CALL(checkpoint, Call(3));
2455 }
2456
2457 CreateChannelAndConnectSuccessfully();
2458 checkpoint.Call(1);
darin0da77e922016-10-04 17:31:232459 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2460 AsIOBuffer("Hello "), 6U);
2461 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2462 AsIOBuffer("World"), 5U);
[email protected]c0d29c22013-07-26 20:40:412463 checkpoint.Call(2);
Bence Békyf4f56e22018-07-17 02:00:052464 std::move(write_callback).Run(OK);
[email protected]c0d29c22013-07-26 20:40:412465 checkpoint.Call(3);
2466}
2467
2468// WebSocketChannel must buffer frames while it is waiting for a write to
2469// complete, and then send them in a single batch. The batching behaviour is
2470// important to get good throughput in the "many small messages" case.
2471TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
2472 static const char input_letters[] = "Hello";
[email protected]2f5d9f62013-09-26 12:14:282473 static const InitFrame expected1[] = {
2474 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "H"}};
2475 static const InitFrame expected2[] = {
2476 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "e"},
2477 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2478 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2479 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
Bence Békyf4f56e22018-07-17 02:00:052480 CompletionOnceCallback write_callback;
[email protected]c0d29c22013-07-26 20:40:412481
2482 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212483 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052484 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2485 .WillOnce(Return(ERR_IO_PENDING));
[email protected]c0d29c22013-07-26 20:40:412486 {
2487 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:052488 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
[email protected]c0d29c22013-07-26 20:40:412489 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
Bence Békyf4f56e22018-07-17 02:00:052490 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
[email protected]c0d29c22013-07-26 20:40:412491 .WillOnce(Return(ERR_IO_PENDING));
2492 }
2493
2494 CreateChannelAndConnectSuccessfully();
2495 for (size_t i = 0; i < strlen(input_letters); ++i) {
darin0da77e922016-10-04 17:31:232496 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2497 AsIOBuffer(std::string(1, input_letters[i])), 1U);
[email protected]c0d29c22013-07-26 20:40:412498 }
Bence Békyf4f56e22018-07-17 02:00:052499 std::move(write_callback).Run(OK);
[email protected]c0d29c22013-07-26 20:40:412500}
2501
[email protected]4256dbb2014-03-24 15:39:362502// When the renderer sends more on a channel than it has quota for, we send the
2503// remote server a kWebSocketErrorGoingAway error code.
2504TEST_F(WebSocketChannelStreamTest, SendGoingAwayOnRendererQuotaExceeded) {
[email protected]2f5d9f62013-09-26 12:14:282505 static const InitFrame expected[] = {
2506 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
[email protected]ea56b982014-01-27 03:21:032507 MASKED, CLOSE_DATA(GOING_AWAY, "")}};
[email protected]c0d29c22013-07-26 20:40:412508 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212509 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052510 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2511 .WillOnce(Return(ERR_IO_PENDING));
2512 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412513 .WillOnce(Return(OK));
2514 EXPECT_CALL(*mock_stream_, Close());
2515
2516 CreateChannelAndConnectSuccessfully();
darin0da77e922016-10-04 17:31:232517 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2518 AsIOBuffer(std::string(kDefaultInitialQuota + 1, 'C')),
2519 kDefaultInitialQuota + 1);
[email protected]c0d29c22013-07-26 20:40:412520}
2521
2522// For convenience, most of these tests use Text frames. However, the WebSocket
2523// protocol also has Binary frames and those need to be 8-bit clean. For the
2524// sake of completeness, this test verifies that they are.
2525TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
danakj9c5cab52016-04-16 00:54:332526 std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
[email protected]c0d29c22013-07-26 20:40:412527
2528 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212529 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052530 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
2531 .WillOnce(Return(ERR_IO_PENDING));
2532 EXPECT_CALL(*mock_stream_, WriteFramesInternal(_, _))
[email protected]2f5d9f62013-09-26 12:14:282533 .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
[email protected]c0d29c22013-07-26 20:40:412534
2535 CreateChannelAndConnectSuccessfully();
2536 channel_->SendFrame(
darin0da77e922016-10-04 17:31:232537 true, WebSocketFrameHeader::kOpCodeBinary,
2538 AsIOBuffer(std::string(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)),
2539 kBinaryBlobSize);
danakj9c5cab52016-04-16 00:54:332540 ASSERT_TRUE(frames != nullptr);
[email protected]2f5d9f62013-09-26 12:14:282541 ASSERT_EQ(1U, frames->size());
yhirano592ff7f2015-12-07 08:45:192542 const WebSocketFrame* out_frame = (*frames)[0].get();
[email protected]2f5d9f62013-09-26 12:14:282543 EXPECT_EQ(kBinaryBlobSize, out_frame->header.payload_length);
dchengb206dc412014-08-26 19:46:232544 ASSERT_TRUE(out_frame->data.get());
[email protected]2f5d9f62013-09-26 12:14:282545 EXPECT_EQ(0, memcmp(kBinaryBlob, out_frame->data->data(), kBinaryBlobSize));
[email protected]c0d29c22013-07-26 20:40:412546}
2547
2548// Test the read path for 8-bit cleanliness as well.
2549TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
Bence Béky65623972018-03-05 15:31:562550 auto frame =
2551 std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodeBinary);
[email protected]2f5d9f62013-09-26 12:14:282552 WebSocketFrameHeader& frame_header = frame->header;
2553 frame_header.final = true;
2554 frame_header.payload_length = kBinaryBlobSize;
Bence Béky65623972018-03-05 15:31:562555 frame->data = base::MakeRefCounted<IOBuffer>(kBinaryBlobSize);
[email protected]2f5d9f62013-09-26 12:14:282556 memcpy(frame->data->data(), kBinaryBlob, kBinaryBlobSize);
danakj9c5cab52016-04-16 00:54:332557 std::vector<std::unique_ptr<WebSocketFrame>> frames;
dchengc7eeda422015-12-26 03:56:482558 frames.push_back(std::move(frame));
Bence Béky65623972018-03-05 15:31:562559 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
yhirano592ff7f2015-12-07 08:45:192560 stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
2561 std::move(frames));
dchengc7eeda422015-12-26 03:56:482562 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422563 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192564 EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_));
darin0da77e922016-10-04 17:31:232565 EXPECT_CALL(
2566 *event_interface_,
2567 OnDataFrameVector(
2568 true, WebSocketFrameHeader::kOpCodeBinary,
2569 std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)));
[email protected]c0d29c22013-07-26 20:40:412570
2571 CreateChannelAndConnectSuccessfully();
2572}
2573
[email protected]48cc6922014-02-10 14:20:482574// Invalid UTF-8 is not permitted in Text frames.
2575TEST_F(WebSocketChannelSendUtf8Test, InvalidUtf8Rejected) {
2576 EXPECT_CALL(
2577 *event_interface_,
2578 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2579
2580 CreateChannelAndConnectSuccessfully();
2581
darin0da77e922016-10-04 17:31:232582 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2583 AsIOBuffer("\xff"), 1U);
[email protected]48cc6922014-02-10 14:20:482584}
2585
2586// A Text message cannot end with a partial UTF-8 character.
2587TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInFinalFrame) {
2588 EXPECT_CALL(
2589 *event_interface_,
2590 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2591
2592 CreateChannelAndConnectSuccessfully();
2593
darin0da77e922016-10-04 17:31:232594 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2595 AsIOBuffer("\xc2"), 1U);
[email protected]48cc6922014-02-10 14:20:482596}
2597
2598// A non-final Text frame may end with a partial UTF-8 character (compare to
2599// previous test).
2600TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInNonFinalFrame) {
2601 CreateChannelAndConnectSuccessfully();
2602
darin0da77e922016-10-04 17:31:232603 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2604 AsIOBuffer("\xc2"), 1U);
[email protected]48cc6922014-02-10 14:20:482605}
2606
2607// UTF-8 parsing context must be retained between frames.
2608TEST_F(WebSocketChannelSendUtf8Test, ValidCharacterSplitBetweenFrames) {
2609 CreateChannelAndConnectSuccessfully();
2610
darin0da77e922016-10-04 17:31:232611 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2612 AsIOBuffer("\xf1"), 1U);
2613 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2614 AsIOBuffer("\x80\xa0\xbf"), 3U);
[email protected]48cc6922014-02-10 14:20:482615}
2616
2617// Similarly, an invalid character should be detected even if split.
2618TEST_F(WebSocketChannelSendUtf8Test, InvalidCharacterSplit) {
2619 EXPECT_CALL(
2620 *event_interface_,
2621 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2622
2623 CreateChannelAndConnectSuccessfully();
2624
darin0da77e922016-10-04 17:31:232625 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2626 AsIOBuffer("\xe1"), 1U);
2627 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2628 AsIOBuffer("\x80\xa0\xbf"), 3U);
[email protected]48cc6922014-02-10 14:20:482629}
2630
2631// An invalid character must be detected in continuation frames.
2632TEST_F(WebSocketChannelSendUtf8Test, InvalidByteInContinuation) {
2633 EXPECT_CALL(
2634 *event_interface_,
2635 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2636
2637 CreateChannelAndConnectSuccessfully();
2638
darin0da77e922016-10-04 17:31:232639 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2640 AsIOBuffer("foo"), 3U);
2641 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
2642 AsIOBuffer("bar"), 3U);
2643 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2644 AsIOBuffer("\xff"), 1U);
[email protected]48cc6922014-02-10 14:20:482645}
2646
2647// However, continuation frames of a Binary frame will not be tested for UTF-8
2648// validity.
2649TEST_F(WebSocketChannelSendUtf8Test, BinaryContinuationNotChecked) {
2650 CreateChannelAndConnectSuccessfully();
2651
darin0da77e922016-10-04 17:31:232652 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeBinary,
2653 AsIOBuffer("foo"), 3U);
2654 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
2655 AsIOBuffer("bar"), 3U);
2656 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2657 AsIOBuffer("\xff"), 1U);
[email protected]48cc6922014-02-10 14:20:482658}
2659
2660// Multiple text messages can be validated without the validation state getting
2661// confused.
2662TEST_F(WebSocketChannelSendUtf8Test, ValidateMultipleTextMessages) {
2663 CreateChannelAndConnectSuccessfully();
2664
darin0da77e922016-10-04 17:31:232665 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2666 AsIOBuffer("foo"), 3U);
2667 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2668 AsIOBuffer("bar"), 3U);
[email protected]48cc6922014-02-10 14:20:482669}
2670
2671// UTF-8 validation is enforced on received Text frames.
2672TEST_F(WebSocketChannelEventInterfaceTest, ReceivedInvalidUtf8) {
Bence Béky65623972018-03-05 15:31:562673 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]48cc6922014-02-10 14:20:482674 static const InitFrame frames[] = {
2675 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
2676 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482677 set_stream(std::move(stream));
[email protected]48cc6922014-02-10 14:20:482678
tyoshinoc06da562015-03-06 06:02:422679 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192680 EXPECT_CALL(*event_interface_,
2681 OnSendFlowControlQuotaAdded(kDefaultInitialQuota));
[email protected]48cc6922014-02-10 14:20:482682 EXPECT_CALL(*event_interface_,
2683 OnFailChannel("Could not decode a text frame as UTF-8."));
2684
2685 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:552686 base::RunLoop().RunUntilIdle();
[email protected]48cc6922014-02-10 14:20:482687}
2688
2689// Invalid UTF-8 is not sent over the network.
2690TEST_F(WebSocketChannelStreamTest, InvalidUtf8TextFrameNotSent) {
2691 static const InitFrame expected[] = {{FINAL_FRAME,
2692 WebSocketFrameHeader::kOpCodeClose,
2693 MASKED, CLOSE_DATA(GOING_AWAY, "")}};
2694 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2695 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052696 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482697 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052698 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]48cc6922014-02-10 14:20:482699 .WillOnce(Return(OK));
2700 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2701
2702 CreateChannelAndConnectSuccessfully();
2703
darin0da77e922016-10-04 17:31:232704 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2705 AsIOBuffer("\xff"), 1U);
[email protected]48cc6922014-02-10 14:20:482706}
2707
2708// The rest of the tests for receiving invalid UTF-8 test the communication with
2709// the server. Since there is only one code path, it would be redundant to
2710// perform the same tests on the EventInterface as well.
2711
2712// If invalid UTF-8 is received in a Text frame, the connection is failed.
2713TEST_F(WebSocketChannelReceiveUtf8Test, InvalidTextFrameRejected) {
2714 static const InitFrame frames[] = {
2715 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
2716 static const InitFrame expected[] = {
2717 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2718 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
2719 {
2720 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:052721 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482722 .WillOnce(ReturnFrames(&frames))
2723 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052724 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]48cc6922014-02-10 14:20:482725 .WillOnce(Return(OK));
2726 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2727 }
2728
2729 CreateChannelAndConnectSuccessfully();
2730}
2731
2732// A received Text message is not permitted to end with a partial UTF-8
2733// character.
2734TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterReceived) {
2735 static const InitFrame frames[] = {
2736 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
2737 static const InitFrame expected[] = {
2738 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2739 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
Bence Békyf4f56e22018-07-17 02:00:052740 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482741 .WillOnce(ReturnFrames(&frames))
2742 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052743 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]48cc6922014-02-10 14:20:482744 .WillOnce(Return(OK));
2745 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2746
2747 CreateChannelAndConnectSuccessfully();
2748}
2749
2750// However, a non-final Text frame may end with a partial UTF-8 character.
2751TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterIncompleteMessage) {
2752 static const InitFrame frames[] = {
2753 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
Bence Békyf4f56e22018-07-17 02:00:052754 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482755 .WillOnce(ReturnFrames(&frames))
2756 .WillRepeatedly(Return(ERR_IO_PENDING));
2757
2758 CreateChannelAndConnectSuccessfully();
2759}
2760
2761// However, it will become an error if it is followed by an empty final frame.
2762TEST_F(WebSocketChannelReceiveUtf8Test, TricksyIncompleteCharacter) {
2763 static const InitFrame frames[] = {
2764 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"},
2765 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
2766 static const InitFrame expected[] = {
2767 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2768 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
Bence Békyf4f56e22018-07-17 02:00:052769 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482770 .WillOnce(ReturnFrames(&frames))
2771 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052772 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]48cc6922014-02-10 14:20:482773 .WillOnce(Return(OK));
2774 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2775
2776 CreateChannelAndConnectSuccessfully();
2777}
2778
2779// UTF-8 parsing context must be retained between received frames of the same
2780// message.
2781TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedParsingContextRetained) {
2782 static const InitFrame frames[] = {
2783 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xf1"},
2784 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2785 NOT_MASKED, "\x80\xa0\xbf"}};
Bence Békyf4f56e22018-07-17 02:00:052786 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482787 .WillOnce(ReturnFrames(&frames))
2788 .WillRepeatedly(Return(ERR_IO_PENDING));
2789
2790 CreateChannelAndConnectSuccessfully();
2791}
2792
2793// An invalid character must be detected even if split between frames.
2794TEST_F(WebSocketChannelReceiveUtf8Test, SplitInvalidCharacterReceived) {
2795 static const InitFrame frames[] = {
2796 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xe1"},
2797 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2798 NOT_MASKED, "\x80\xa0\xbf"}};
2799 static const InitFrame expected[] = {
2800 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2801 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
Bence Békyf4f56e22018-07-17 02:00:052802 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482803 .WillOnce(ReturnFrames(&frames))
2804 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052805 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]48cc6922014-02-10 14:20:482806 .WillOnce(Return(OK));
2807 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2808
2809 CreateChannelAndConnectSuccessfully();
2810}
2811
2812// An invalid character received in a continuation frame must be detected.
2813TEST_F(WebSocketChannelReceiveUtf8Test, InvalidReceivedIncontinuation) {
2814 static const InitFrame frames[] = {
2815 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
2816 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2817 NOT_MASKED, "bar"},
2818 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2819 NOT_MASKED, "\xff"}};
2820 static const InitFrame expected[] = {
2821 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2822 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
Bence Békyf4f56e22018-07-17 02:00:052823 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482824 .WillOnce(ReturnFrames(&frames))
2825 .WillRepeatedly(Return(ERR_IO_PENDING));
Bence Békyf4f56e22018-07-17 02:00:052826 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]48cc6922014-02-10 14:20:482827 .WillOnce(Return(OK));
2828 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2829
2830 CreateChannelAndConnectSuccessfully();
2831}
2832
2833// Continuations of binary frames must not be tested for UTF-8 validity.
2834TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedBinaryNotUtf8Tested) {
2835 static const InitFrame frames[] = {
2836 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary, NOT_MASKED, "foo"},
2837 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2838 NOT_MASKED, "bar"},
2839 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2840 NOT_MASKED, "\xff"}};
Bence Békyf4f56e22018-07-17 02:00:052841 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482842 .WillOnce(ReturnFrames(&frames))
2843 .WillRepeatedly(Return(ERR_IO_PENDING));
2844
2845 CreateChannelAndConnectSuccessfully();
2846}
2847
2848// Multiple Text messages can be validated.
2849TEST_F(WebSocketChannelReceiveUtf8Test, ValidateMultipleReceived) {
2850 static const InitFrame frames[] = {
2851 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
2852 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "bar"}};
Bence Békyf4f56e22018-07-17 02:00:052853 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]48cc6922014-02-10 14:20:482854 .WillOnce(ReturnFrames(&frames))
2855 .WillRepeatedly(Return(ERR_IO_PENDING));
2856
2857 CreateChannelAndConnectSuccessfully();
2858}
2859
[email protected]4e4bbaae7e2014-02-19 08:28:532860// A new data message cannot start in the middle of another data message.
2861TEST_F(WebSocketChannelEventInterfaceTest, BogusContinuation) {
Bence Béky65623972018-03-05 15:31:562862 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]4e4bbaae7e2014-02-19 08:28:532863 static const InitFrame frames[] = {
2864 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary,
2865 NOT_MASKED, "frame1"},
2866 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2867 NOT_MASKED, "frame2"}};
2868 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482869 set_stream(std::move(stream));
[email protected]4e4bbaae7e2014-02-19 08:28:532870
tyoshinoc06da562015-03-06 06:02:422871 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192872 EXPECT_CALL(*event_interface_,
2873 OnSendFlowControlQuotaAdded(kDefaultInitialQuota));
darin0da77e922016-10-04 17:31:232874 EXPECT_CALL(*event_interface_,
2875 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeBinary,
2876 AsVector("frame1")));
[email protected]4e4bbaae7e2014-02-19 08:28:532877 EXPECT_CALL(
2878 *event_interface_,
2879 OnFailChannel(
2880 "Received start of new message but previous message is unfinished."));
2881
2882 CreateChannelAndConnectSuccessfully();
2883}
2884
2885// A new message cannot start with a Continuation frame.
2886TEST_F(WebSocketChannelEventInterfaceTest, MessageStartingWithContinuation) {
Bence Béky65623972018-03-05 15:31:562887 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]4e4bbaae7e2014-02-19 08:28:532888 static const InitFrame frames[] = {
2889 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2890 NOT_MASKED, "continuation"}};
2891 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482892 set_stream(std::move(stream));
[email protected]4e4bbaae7e2014-02-19 08:28:532893
tyoshinoc06da562015-03-06 06:02:422894 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192895 EXPECT_CALL(*event_interface_,
2896 OnSendFlowControlQuotaAdded(kDefaultInitialQuota));
[email protected]4e4bbaae7e2014-02-19 08:28:532897 EXPECT_CALL(*event_interface_,
2898 OnFailChannel("Received unexpected continuation frame."));
2899
2900 CreateChannelAndConnectSuccessfully();
2901}
2902
[email protected]326b8fb2014-02-21 21:14:002903// A frame passed to the renderer must be either non-empty or have the final bit
2904// set.
2905TEST_F(WebSocketChannelEventInterfaceTest, DataFramesNonEmptyOrFinal) {
Bence Béky65623972018-03-05 15:31:562906 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
[email protected]326b8fb2014-02-21 21:14:002907 static const InitFrame frames[] = {
2908 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, ""},
2909 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2910 NOT_MASKED, ""},
2911 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
2912 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482913 set_stream(std::move(stream));
[email protected]326b8fb2014-02-21 21:14:002914
tyoshinoc06da562015-03-06 06:02:422915 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
Yoichi Osatob088adc2019-06-06 05:52:192916 EXPECT_CALL(*event_interface_,
2917 OnSendFlowControlQuotaAdded(kDefaultInitialQuota));
[email protected]326b8fb2014-02-21 21:14:002918 EXPECT_CALL(
2919 *event_interface_,
darin0da77e922016-10-04 17:31:232920 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
[email protected]326b8fb2014-02-21 21:14:002921
2922 CreateChannelAndConnectSuccessfully();
2923}
2924
[email protected]a62449522014-06-05 11:11:152925// Calls to OnSSLCertificateError() must be passed through to the event
2926// interface with the correct URL attached.
2927TEST_F(WebSocketChannelEventInterfaceTest, OnSSLCertificateErrorCalled) {
2928 const GURL wss_url("wss://example.com/sslerror");
2929 connect_data_.socket_url = wss_url;
2930 const SSLInfo ssl_info;
2931 const bool fatal = true;
Bence Béky65623972018-03-05 15:31:562932 auto fake_callbacks = std::make_unique<FakeSSLErrorCallbacks>();
[email protected]a62449522014-06-05 11:11:152933
2934 EXPECT_CALL(*event_interface_,
2935 OnSSLCertificateErrorCalled(NotNull(), wss_url, _, fatal));
2936
2937 CreateChannelAndConnect();
tyoshinoccfcfde2016-07-21 14:06:552938 connect_data_.argument_saver.connect_delegate->OnSSLCertificateError(
Emily Stark79fba5842019-04-25 04:59:362939 std::move(fake_callbacks), net::ERR_CERT_DATE_INVALID, ssl_info, fatal);
[email protected]a62449522014-06-05 11:11:152940}
2941
Yutaka Hirano70fa25912018-06-06 05:26:542942// Calls to OnAuthRequired() must be passed through to the event interface.
2943TEST_F(WebSocketChannelEventInterfaceTest, OnAuthRequiredCalled) {
2944 const GURL wss_url("wss://example.com/on_auth_required");
2945 connect_data_.socket_url = wss_url;
Emily Starkf2c9bbd2019-04-09 17:08:582946 AuthChallengeInfo auth_info;
Yutaka Hirano70fa25912018-06-06 05:26:542947 base::Optional<AuthCredentials> credentials;
2948 scoped_refptr<HttpResponseHeaders> response_headers =
2949 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
Tsuyoshi Horo01faed62019-02-20 22:11:372950 IPEndPoint remote_endpoint(net::IPAddress(127, 0, 0, 1), 80);
Yutaka Hirano70fa25912018-06-06 05:26:542951
Emily Stark08f6c972019-05-28 17:24:272952 EXPECT_CALL(*event_interface_,
2953 OnAuthRequiredCalled(_, response_headers, _, &credentials))
Yutaka Hirano70fa25912018-06-06 05:26:542954 .WillOnce(Return(OK));
2955
2956 CreateChannelAndConnect();
2957 connect_data_.argument_saver.connect_delegate->OnAuthRequired(
Tsuyoshi Horo01faed62019-02-20 22:11:372958 auth_info, response_headers, remote_endpoint, {}, &credentials);
Yutaka Hirano70fa25912018-06-06 05:26:542959}
2960
[email protected]c0d29c22013-07-26 20:40:412961// If we receive another frame after Close, it is not valid. It is not
2962// completely clear what behaviour is required from the standard in this case,
2963// but the current implementation fails the connection. Since a Close has
2964// already been sent, this just means closing the connection.
2965TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
[email protected]2f5d9f62013-09-26 12:14:282966 static const InitFrame frames[] = {
2967 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2968 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
2969 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2970 NOT_MASKED, "Ping body"}};
2971 static const InitFrame expected[] = {
2972 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2973 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
[email protected]c0d29c22013-07-26 20:40:412974 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212975 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:052976 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]2f5d9f62013-09-26 12:14:282977 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:412978 .WillRepeatedly(Return(ERR_IO_PENDING));
2979 {
2980 // We only need to verify the relative order of WriteFrames() and
2981 // Close(). The current implementation calls WriteFrames() for the Close
2982 // frame before calling ReadFrames() again, but that is an implementation
2983 // detail and better not to consider required behaviour.
2984 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:052985 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412986 .WillOnce(Return(OK));
2987 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2988 }
2989
2990 CreateChannelAndConnectSuccessfully();
2991}
2992
[email protected]2f5d9f62013-09-26 12:14:282993// A protocol error from the remote server should result in a close frame with
2994// status 1002, followed by the connection closing.
2995TEST_F(WebSocketChannelStreamTest, ProtocolError) {
2996 static const InitFrame expected[] = {
2997 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2998 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}};
2999 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213000 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:053001 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]2f5d9f62013-09-26 12:14:283002 .WillOnce(Return(ERR_WS_PROTOCOL_ERROR));
Bence Békyf4f56e22018-07-17 02:00:053003 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]2f5d9f62013-09-26 12:14:283004 .WillOnce(Return(OK));
3005 EXPECT_CALL(*mock_stream_, Close());
3006
3007 CreateChannelAndConnectSuccessfully();
3008}
3009
[email protected]3a266762013-10-23 08:15:103010// Set the closing handshake timeout to a very tiny value before connecting.
3011class WebSocketChannelStreamTimeoutTest : public WebSocketChannelStreamTest {
3012 protected:
Chris Watkins28c2fdd2017-11-30 06:06:523013 WebSocketChannelStreamTimeoutTest() = default;
[email protected]3a266762013-10-23 08:15:103014
dchengb03027d2014-10-21 12:00:203015 void CreateChannelAndConnectSuccessfully() override {
dchengc7eeda422015-12-26 03:56:483016 set_stream(std::move(mock_stream_));
[email protected]3a266762013-10-23 08:15:103017 CreateChannelAndConnect();
3018 channel_->SetClosingHandshakeTimeoutForTesting(
3019 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
tyoshinod4d1d302014-11-07 04:31:163020 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
3021 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
tyoshinoccfcfde2016-07-21 14:06:553022 connect_data_.argument_saver.connect_delegate->OnSuccess(
3023 std::move(stream_));
Yutaka Hiranodfa67e52019-07-29 03:13:263024 base::IgnoreResult(channel_->AddReceiveFlowControlQuota(kPlentyOfQuota));
[email protected]3a266762013-10-23 08:15:103025 }
3026};
3027
3028// In this case the server initiates the closing handshake with a Close
3029// message. WebSocketChannel responds with a matching Close message, and waits
3030// for the server to close the TCP/IP connection. The server never closes the
3031// connection, so the closing handshake times out and WebSocketChannel closes
3032// the connection itself.
3033TEST_F(WebSocketChannelStreamTimeoutTest, ServerInitiatedCloseTimesOut) {
3034 static const InitFrame frames[] = {
3035 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3036 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3037 static const InitFrame expected[] = {
3038 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3039 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3040 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213041 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:053042 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]3a266762013-10-23 08:15:103043 .WillOnce(ReturnFrames(&frames))
3044 .WillRepeatedly(Return(ERR_IO_PENDING));
[email protected]f485985e2013-10-24 13:47:443045 Checkpoint checkpoint;
[email protected]3a266762013-10-23 08:15:103046 TestClosure completion;
3047 {
3048 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:053049 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]3a266762013-10-23 08:15:103050 .WillOnce(Return(OK));
3051 EXPECT_CALL(checkpoint, Call(1));
3052 EXPECT_CALL(*mock_stream_, Close())
3053 .WillOnce(InvokeClosure(completion.closure()));
3054 }
3055
3056 CreateChannelAndConnectSuccessfully();
3057 checkpoint.Call(1);
3058 completion.WaitForResult();
3059}
3060
3061// In this case the client initiates the closing handshake by sending a Close
3062// message. WebSocketChannel waits for a Close message in response from the
3063// server. The server never responds to the Close message, so the closing
3064// handshake times out and WebSocketChannel closes the connection.
3065TEST_F(WebSocketChannelStreamTimeoutTest, ClientInitiatedCloseTimesOut) {
3066 static const InitFrame expected[] = {
3067 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3068 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3069 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213070 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
Bence Békyf4f56e22018-07-17 02:00:053071 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]3a266762013-10-23 08:15:103072 .WillRepeatedly(Return(ERR_IO_PENDING));
3073 TestClosure completion;
3074 {
3075 InSequence s;
Bence Békyf4f56e22018-07-17 02:00:053076 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]3a266762013-10-23 08:15:103077 .WillOnce(Return(OK));
3078 EXPECT_CALL(*mock_stream_, Close())
3079 .WillOnce(InvokeClosure(completion.closure()));
3080 }
3081
3082 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:493083 ASSERT_EQ(CHANNEL_ALIVE,
3084 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"));
[email protected]3a266762013-10-23 08:15:103085 completion.WaitForResult();
3086}
3087
3088// In this case the client initiates the closing handshake and the server
3089// responds with a matching Close message. WebSocketChannel waits for the server
3090// to close the TCP/IP connection, but it never does. The closing handshake
3091// times out and WebSocketChannel closes the connection.
3092TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) {
3093 static const InitFrame expected[] = {
3094 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3095 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3096 static const InitFrame frames[] = {
3097 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3098 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3099 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213100 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]3a266762013-10-23 08:15:103101 TestClosure completion;
danakj9c5cab52016-04-16 00:54:333102 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames = nullptr;
Bence Békyf4f56e22018-07-17 02:00:053103 CompletionOnceCallback read_callback;
[email protected]3a266762013-10-23 08:15:103104 {
3105 InSequence s;
3106 // Copy the arguments to ReadFrames so that the test can call the callback
3107 // after it has send the close message.
Bence Békyf4f56e22018-07-17 02:00:053108 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
3109 .WillOnce(DoAll(SaveArg<0>(&read_frames), SaveArg<1>(&read_callback),
[email protected]3a266762013-10-23 08:15:103110 Return(ERR_IO_PENDING)));
3111 // The first real event that happens is the client sending the Close
3112 // message.
Bence Békyf4f56e22018-07-17 02:00:053113 EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
[email protected]3a266762013-10-23 08:15:103114 .WillOnce(Return(OK));
3115 // The |read_frames| callback is called (from this test case) at this
3116 // point. ReadFrames is called again by WebSocketChannel, waiting for
3117 // ERR_CONNECTION_CLOSED.
Bence Békyf4f56e22018-07-17 02:00:053118 EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
[email protected]3a266762013-10-23 08:15:103119 .WillOnce(Return(ERR_IO_PENDING));
3120 // The timeout happens and so WebSocketChannel closes the stream.
3121 EXPECT_CALL(*mock_stream_, Close())
3122 .WillOnce(InvokeClosure(completion.closure()));
3123 }
3124
3125 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:493126 ASSERT_EQ(CHANNEL_ALIVE,
3127 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"));
[email protected]3a266762013-10-23 08:15:103128 ASSERT_TRUE(read_frames);
3129 // Provide the "Close" message from the server.
3130 *read_frames = CreateFrameVector(frames);
Bence Békyf4f56e22018-07-17 02:00:053131 std::move(read_callback).Run(OK);
[email protected]3a266762013-10-23 08:15:103132 completion.WaitForResult();
3133}
3134
ricea5858a5052016-01-06 04:57:383135// Verify that current_send_quota() returns a non-zero value for a newly
3136// connected channel.
3137TEST_F(WebSocketChannelTest, CurrentSendQuotaNonZero) {
3138 CreateChannelAndConnectSuccessfully();
3139 EXPECT_GT(channel_->current_send_quota(), 0);
3140}
3141
3142// Verify that current_send_quota() is updated when SendFrame() is called.
3143TEST_F(WebSocketChannelTest, CurrentSendQuotaUpdated) {
3144 const int kMessageSize = 5;
Bence Béky8f9d7d3952017-10-09 19:58:043145 set_stream(std::make_unique<WriteableFakeWebSocketStream>());
ricea5858a5052016-01-06 04:57:383146 CreateChannelAndConnectSuccessfully();
3147
3148 int initial_send_quota = channel_->current_send_quota();
3149 EXPECT_GE(initial_send_quota, kMessageSize);
3150
3151 channel_->SendFrame(
3152 true, WebSocketFrameHeader::kOpCodeText,
darin0da77e922016-10-04 17:31:233153 AsIOBuffer(std::string(static_cast<size_t>(kMessageSize), 'a')),
3154 static_cast<size_t>(kMessageSize));
ricea5858a5052016-01-06 04:57:383155 int new_send_quota = channel_->current_send_quota();
3156 EXPECT_EQ(kMessageSize, initial_send_quota - new_send_quota);
3157}
3158
[email protected]999bcaa2013-07-17 13:42:543159} // namespace
3160} // namespace net