blob: dd2fa354b2c59f0b17e5e8d67d4992990b66a71a [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
[email protected]999bcaa2013-07-17 13:42:5411#include <iostream>
yhirano592ff7f2015-12-07 08:45:1912#include <iterator>
danakj9c5cab52016-04-16 00:54:3313#include <memory>
[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"
[email protected]c0d29c22013-07-26 20:40:4121#include "base/location.h"
Avi Drissman13fc8932015-12-20 04:40:4622#include "base/macros.h"
danakj9c5cab52016-04-16 00:54:3323#include "base/memory/ptr_util.h"
[email protected]f485985e2013-10-24 13:47:4424#include "base/memory/weak_ptr.h"
[email protected]999bcaa2013-07-17 13:42:5425#include "base/message_loop/message_loop.h"
fdoray92e35a72016-06-10 15:54:5526#include "base/run_loop.h"
skyostil4891b25b2015-06-11 11:43:4527#include "base/single_thread_task_runner.h"
[email protected]999bcaa2013-07-17 13:42:5428#include "base/strings/string_piece.h"
gabf767595f2016-05-11 18:50:3529#include "base/threading/thread_task_runner_handle.h"
[email protected]999bcaa2013-07-17 13:42:5430#include "net/base/net_errors.h"
[email protected]3a266762013-10-23 08:15:1031#include "net/base/test_completion_callback.h"
[email protected]cd48ed12014-01-22 14:34:2232#include "net/http/http_response_headers.h"
[email protected]999bcaa2013-07-17 13:42:5433#include "net/url_request/url_request_context.h"
34#include "net/websockets/websocket_errors.h"
35#include "net/websockets/websocket_event_interface.h"
[email protected]cd48ed12014-01-22 14:34:2236#include "net/websockets/websocket_handshake_request_info.h"
37#include "net/websockets/websocket_handshake_response_info.h"
[email protected]999bcaa2013-07-17 13:42:5438#include "net/websockets/websocket_mux.h"
39#include "testing/gmock/include/gmock/gmock.h"
40#include "testing/gtest/include/gtest/gtest.h"
[email protected]15fbdb42013-07-20 00:09:3841#include "url/gurl.h"
mkwst4997ce82015-07-25 12:00:0542#include "url/origin.h"
[email protected]999bcaa2013-07-17 13:42:5443
[email protected]c0d29c22013-07-26 20:40:4144// Hacky macros to construct the body of a Close message from a code and a
45// string, while ensuring the result is a compile-time constant string.
46// Use like CLOSE_DATA(NORMAL_CLOSURE, "Explanation String")
47#define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string
48#define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8"
49#define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9"
[email protected]2f5d9f62013-09-26 12:14:2850#define WEBSOCKET_CLOSE_CODE_AS_STRING_PROTOCOL_ERROR "\x03\xea"
[email protected]ea56b982014-01-27 03:21:0351#define WEBSOCKET_CLOSE_CODE_AS_STRING_ABNORMAL_CLOSURE "\x03\xee"
[email protected]c0d29c22013-07-26 20:40:4152#define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3"
53
[email protected]999bcaa2013-07-17 13:42:5454namespace net {
55
[email protected]2f5d9f62013-09-26 12:14:2856// Printing helpers to allow GoogleMock to print frames. These are explicitly
57// designed to look like the static initialisation format we use in these
58// tests. They have to live in the net namespace in order to be found by
[email protected]999bcaa2013-07-17 13:42:5459// GoogleMock; a nested anonymous namespace will not work.
60
61std::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) {
[email protected]2f5d9f62013-09-26 12:14:2862 return os << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
[email protected]999bcaa2013-07-17 13:42:5463 << header.opcode << ", "
[email protected]2f5d9f62013-09-26 12:14:2864 << (header.masked ? "MASKED" : "NOT_MASKED");
[email protected]999bcaa2013-07-17 13:42:5465}
66
[email protected]2f5d9f62013-09-26 12:14:2867std::ostream& operator<<(std::ostream& os, const WebSocketFrame& frame) {
68 os << "{" << frame.header << ", ";
dchengb206dc412014-08-26 19:46:2369 if (frame.data.get()) {
[email protected]2f5d9f62013-09-26 12:14:2870 return os << "\"" << base::StringPiece(frame.data->data(),
71 frame.header.payload_length)
72 << "\"}";
[email protected]999bcaa2013-07-17 13:42:5473 }
[email protected]2f5d9f62013-09-26 12:14:2874 return os << "NULL}";
[email protected]c0d29c22013-07-26 20:40:4175}
76
yhirano592ff7f2015-12-07 08:45:1977std::ostream& operator<<(
78 std::ostream& os,
danakj9c5cab52016-04-16 00:54:3379 const std::vector<std::unique_ptr<WebSocketFrame>>& frames) {
[email protected]c0d29c22013-07-26 20:40:4180 os << "{";
81 bool first = true;
yhirano592ff7f2015-12-07 08:45:1982 for (const auto& frame : frames) {
[email protected]c0d29c22013-07-26 20:40:4183 if (!first) {
84 os << ",\n";
85 } else {
86 first = false;
87 }
yhirano592ff7f2015-12-07 08:45:1988 os << *frame;
[email protected]c0d29c22013-07-26 20:40:4189 }
90 return os << "}";
91}
92
yhirano592ff7f2015-12-07 08:45:1993std::ostream& operator<<(
94 std::ostream& os,
danakj9c5cab52016-04-16 00:54:3395 const std::vector<std::unique_ptr<WebSocketFrame>>* vector) {
[email protected]c0d29c22013-07-26 20:40:4196 return os << '&' << *vector;
[email protected]999bcaa2013-07-17 13:42:5497}
98
99namespace {
100
[email protected]3a266762013-10-23 08:15:10101using ::base::TimeDelta;
102
[email protected]999bcaa2013-07-17 13:42:54103using ::testing::AnyNumber;
[email protected]f485985e2013-10-24 13:47:44104using ::testing::DefaultValue;
[email protected]999bcaa2013-07-17 13:42:54105using ::testing::InSequence;
106using ::testing::MockFunction;
[email protected]a62449522014-06-05 11:11:15107using ::testing::NotNull;
[email protected]999bcaa2013-07-17 13:42:54108using ::testing::Return;
[email protected]c0d29c22013-07-26 20:40:41109using ::testing::SaveArg;
[email protected]999bcaa2013-07-17 13:42:54110using ::testing::StrictMock;
111using ::testing::_;
112
[email protected]c0d29c22013-07-26 20:40:41113// A selection of characters that have traditionally been mangled in some
114// environment or other, for testing 8-bit cleanliness.
[email protected]2f5d9f62013-09-26 12:14:28115const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
[email protected]c0d29c22013-07-26 20:40:41116 '\0', // nul
117 '\x7F', // DEL
118 '\x80', '\xFF', // NOT VALID UTF-8
119 '\x1A', // Control-Z, EOF on DOS
120 '\x03', // Control-C
121 '\x04', // EOT, special for Unix terms
122 '\x1B', // ESC, often special
123 '\b', // backspace
124 '\'', // single-quote, special in PHP
125};
126const size_t kBinaryBlobSize = arraysize(kBinaryBlob);
127
128// The amount of quota a new connection gets by default.
129// TODO(ricea): If kDefaultSendQuotaHighWaterMark changes, then this value will
130// need to be updated.
131const size_t kDefaultInitialQuota = 1 << 17;
132// The amount of bytes we need to send after the initial connection to trigger a
133// quota refresh. TODO(ricea): Change this if kDefaultSendQuotaHighWaterMark or
134// kDefaultSendQuotaLowWaterMark change.
135const size_t kDefaultQuotaRefreshTrigger = (1 << 16) + 1;
136
tyoshinod4d1d302014-11-07 04:31:16137const int kVeryBigTimeoutMillis = 60 * 60 * 24 * 1000;
138
[email protected]3a266762013-10-23 08:15:10139// TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world
140// in that time! I would like my tests to run a bit quicker.
141const int kVeryTinyTimeoutMillis = 1;
142
[email protected]4256dbb2014-03-24 15:39:36143// Enough quota to pass any test.
tfarina8a2c66c22015-10-13 19:14:49144const int64_t kPlentyOfQuota = INT_MAX;
[email protected]4256dbb2014-03-24 15:39:36145
[email protected]f485985e2013-10-24 13:47:44146typedef WebSocketEventInterface::ChannelState ChannelState;
147const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE;
148const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED;
149
150// This typedef mainly exists to avoid having to repeat the "NOLINT" incantation
151// all over the place.
[email protected]4256dbb2014-03-24 15:39:36152typedef StrictMock< MockFunction<void(int)> > Checkpoint; // NOLINT
[email protected]f485985e2013-10-24 13:47:44153
[email protected]999bcaa2013-07-17 13:42:54154// This mock is for testing expectations about how the EventInterface is used.
155class MockWebSocketEventInterface : public WebSocketEventInterface {
156 public:
[email protected]cd48ed12014-01-22 14:34:22157 MockWebSocketEventInterface() {}
158
tyoshinoc06da562015-03-06 06:02:42159 MOCK_METHOD2(OnAddChannelResponse,
160 ChannelState(const std::string&,
[email protected]6c5d9f62014-01-27 15:05:21161 const std::string&)); // NOLINT
[email protected]999bcaa2013-07-17 13:42:54162 MOCK_METHOD3(OnDataFrame,
[email protected]f485985e2013-10-24 13:47:44163 ChannelState(bool,
164 WebSocketMessageType,
165 const std::vector<char>&)); // NOLINT
tfarina8a2c66c22015-10-13 19:14:49166 MOCK_METHOD1(OnFlowControl, ChannelState(int64_t)); // NOLINT
[email protected]f485985e2013-10-24 13:47:44167 MOCK_METHOD0(OnClosingHandshake, ChannelState(void)); // NOLINT
[email protected]96868202014-01-09 10:38:04168 MOCK_METHOD1(OnFailChannel, ChannelState(const std::string&)); // NOLINT
[email protected]86ec55502014-02-10 13:16:16169 MOCK_METHOD3(OnDropChannel,
tfarina8a2c66c22015-10-13 19:14:49170 ChannelState(bool, uint16_t, const std::string&)); // NOLINT
[email protected]cd48ed12014-01-22 14:34:22171
172 // We can't use GMock with scoped_ptr.
173 ChannelState OnStartOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33174 std::unique_ptr<WebSocketHandshakeRequestInfo>) override {
[email protected]cd48ed12014-01-22 14:34:22175 OnStartOpeningHandshakeCalled();
176 return CHANNEL_ALIVE;
177 }
178 ChannelState OnFinishOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33179 std::unique_ptr<WebSocketHandshakeResponseInfo>) override {
[email protected]cd48ed12014-01-22 14:34:22180 OnFinishOpeningHandshakeCalled();
181 return CHANNEL_ALIVE;
182 }
nickd3f30d022015-04-23 10:18:37183 ChannelState OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33184 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
[email protected]a62449522014-06-05 11:11:15185 const GURL& url,
186 const SSLInfo& ssl_info,
mostynbba063d6032014-10-09 11:01:13187 bool fatal) override {
[email protected]a62449522014-06-05 11:11:15188 OnSSLCertificateErrorCalled(
189 ssl_error_callbacks.get(), url, ssl_info, fatal);
190 return CHANNEL_ALIVE;
191 }
[email protected]cd48ed12014-01-22 14:34:22192
193 MOCK_METHOD0(OnStartOpeningHandshakeCalled, void()); // NOLINT
194 MOCK_METHOD0(OnFinishOpeningHandshakeCalled, void()); // NOLINT
[email protected]a62449522014-06-05 11:11:15195 MOCK_METHOD4(
196 OnSSLCertificateErrorCalled,
197 void(SSLErrorCallbacks*, const GURL&, const SSLInfo&, bool)); // NOLINT
[email protected]999bcaa2013-07-17 13:42:54198};
199
200// This fake EventInterface is for tests which need a WebSocketEventInterface
201// implementation but are not verifying how it is used.
202class FakeWebSocketEventInterface : public WebSocketEventInterface {
tyoshinoc06da562015-03-06 06:02:42203 ChannelState OnAddChannelResponse(const std::string& selected_protocol,
dchengb03027d2014-10-21 12:00:20204 const std::string& extensions) override {
tyoshinoc06da562015-03-06 06:02:42205 return CHANNEL_ALIVE;
[email protected]f485985e2013-10-24 13:47:44206 }
dchengb03027d2014-10-21 12:00:20207 ChannelState OnDataFrame(bool fin,
208 WebSocketMessageType type,
209 const std::vector<char>& data) override {
[email protected]f485985e2013-10-24 13:47:44210 return CHANNEL_ALIVE;
211 }
tfarina8a2c66c22015-10-13 19:14:49212 ChannelState OnFlowControl(int64_t quota) override { return CHANNEL_ALIVE; }
dchengb03027d2014-10-21 12:00:20213 ChannelState OnClosingHandshake() override { return CHANNEL_ALIVE; }
214 ChannelState OnFailChannel(const std::string& message) override {
[email protected]96868202014-01-09 10:38:04215 return CHANNEL_DELETED;
216 }
dchengb03027d2014-10-21 12:00:20217 ChannelState OnDropChannel(bool was_clean,
tfarina8a2c66c22015-10-13 19:14:49218 uint16_t code,
dchengb03027d2014-10-21 12:00:20219 const std::string& reason) override {
[email protected]f485985e2013-10-24 13:47:44220 return CHANNEL_DELETED;
221 }
dchengb03027d2014-10-21 12:00:20222 ChannelState OnStartOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33223 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {
[email protected]cd48ed12014-01-22 14:34:22224 return CHANNEL_ALIVE;
225 }
dchengb03027d2014-10-21 12:00:20226 ChannelState OnFinishOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33227 std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {
[email protected]cd48ed12014-01-22 14:34:22228 return CHANNEL_ALIVE;
229 }
dchengb03027d2014-10-21 12:00:20230 ChannelState OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33231 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
[email protected]a62449522014-06-05 11:11:15232 const GURL& url,
233 const SSLInfo& ssl_info,
mostynbba063d6032014-10-09 11:01:13234 bool fatal) override {
[email protected]a62449522014-06-05 11:11:15235 return CHANNEL_ALIVE;
236 }
[email protected]999bcaa2013-07-17 13:42:54237};
238
239// This fake WebSocketStream is for tests that require a WebSocketStream but are
240// not testing the way it is used. It has minimal functionality to return
241// the |protocol| and |extensions| that it was constructed with.
242class FakeWebSocketStream : public WebSocketStream {
243 public:
244 // Constructs with empty protocol and extensions.
245 FakeWebSocketStream() {}
246
247 // Constructs with specified protocol and extensions.
248 FakeWebSocketStream(const std::string& protocol,
249 const std::string& extensions)
250 : protocol_(protocol), extensions_(extensions) {}
251
danakj9c5cab52016-04-16 00:54:33252 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20253 const CompletionCallback& callback) override {
[email protected]999bcaa2013-07-17 13:42:54254 return ERR_IO_PENDING;
255 }
256
danakj9c5cab52016-04-16 00:54:33257 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20258 const CompletionCallback& callback) override {
[email protected]999bcaa2013-07-17 13:42:54259 return ERR_IO_PENDING;
260 }
261
dchengb03027d2014-10-21 12:00:20262 void Close() override {}
[email protected]999bcaa2013-07-17 13:42:54263
264 // Returns the string passed to the constructor.
dchengb03027d2014-10-21 12:00:20265 std::string GetSubProtocol() const override { return protocol_; }
[email protected]999bcaa2013-07-17 13:42:54266
267 // Returns the string passed to the constructor.
dchengb03027d2014-10-21 12:00:20268 std::string GetExtensions() const override { return extensions_; }
[email protected]999bcaa2013-07-17 13:42:54269
270 private:
271 // The string to return from GetSubProtocol().
272 std::string protocol_;
273
274 // The string to return from GetExtensions().
275 std::string extensions_;
276};
277
278// To make the static initialisers easier to read, we use enums rather than
279// bools.
[email protected]ea56b982014-01-27 03:21:03280enum IsFinal { NOT_FINAL_FRAME, FINAL_FRAME };
[email protected]999bcaa2013-07-17 13:42:54281
[email protected]ea56b982014-01-27 03:21:03282enum IsMasked { NOT_MASKED, MASKED };
[email protected]999bcaa2013-07-17 13:42:54283
[email protected]2f5d9f62013-09-26 12:14:28284// This is used to initialise a WebSocketFrame but is statically initialisable.
285struct InitFrame {
286 IsFinal final;
287 // Reserved fields omitted for now. Add them if you need them.
288 WebSocketFrameHeader::OpCode opcode;
289 IsMasked masked;
[email protected]999bcaa2013-07-17 13:42:54290
danakj9c5cab52016-04-16 00:54:33291 // Will be used to create the IOBuffer member. Can be null for null data. Is a
[email protected]2f5d9f62013-09-26 12:14:28292 // nul-terminated string for ease-of-use. |header.payload_length| is
293 // initialised from |strlen(data)|. This means it is not 8-bit clean, but this
294 // is not an issue for test data.
[email protected]999bcaa2013-07-17 13:42:54295 const char* const data;
296};
297
[email protected]c0d29c22013-07-26 20:40:41298// For GoogleMock
[email protected]2f5d9f62013-09-26 12:14:28299std::ostream& operator<<(std::ostream& os, const InitFrame& frame) {
300 os << "{" << (frame.final == FINAL_FRAME ? "FINAL_FRAME" : "NOT_FINAL_FRAME")
301 << ", " << frame.opcode << ", "
302 << (frame.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", ";
303 if (frame.data) {
304 return os << "\"" << frame.data << "\"}";
[email protected]c0d29c22013-07-26 20:40:41305 }
[email protected]2f5d9f62013-09-26 12:14:28306 return os << "NULL}";
[email protected]c0d29c22013-07-26 20:40:41307}
308
309template <size_t N>
[email protected]2f5d9f62013-09-26 12:14:28310std::ostream& operator<<(std::ostream& os, const InitFrame (&frames)[N]) {
[email protected]c0d29c22013-07-26 20:40:41311 os << "{";
312 bool first = true;
313 for (size_t i = 0; i < N; ++i) {
314 if (!first) {
315 os << ",\n";
316 } else {
317 first = false;
318 }
[email protected]2f5d9f62013-09-26 12:14:28319 os << frames[i];
[email protected]c0d29c22013-07-26 20:40:41320 }
321 return os << "}";
322}
323
[email protected]2f5d9f62013-09-26 12:14:28324// Convert a const array of InitFrame structs to the format used at
[email protected]999bcaa2013-07-17 13:42:54325// runtime. Templated on the size of the array to save typing.
326template <size_t N>
danakj9c5cab52016-04-16 00:54:33327std::vector<std::unique_ptr<WebSocketFrame>> CreateFrameVector(
328 const InitFrame (&source_frames)[N]) {
329 std::vector<std::unique_ptr<WebSocketFrame>> result_frames;
[email protected]2f5d9f62013-09-26 12:14:28330 result_frames.reserve(N);
[email protected]999bcaa2013-07-17 13:42:54331 for (size_t i = 0; i < N; ++i) {
[email protected]2f5d9f62013-09-26 12:14:28332 const InitFrame& source_frame = source_frames[i];
danakj9c5cab52016-04-16 00:54:33333 std::unique_ptr<WebSocketFrame> result_frame(
[email protected]2f5d9f62013-09-26 12:14:28334 new WebSocketFrame(source_frame.opcode));
335 size_t frame_length = source_frame.data ? strlen(source_frame.data) : 0;
336 WebSocketFrameHeader& result_header = result_frame->header;
337 result_header.final = (source_frame.final == FINAL_FRAME);
338 result_header.masked = (source_frame.masked == MASKED);
339 result_header.payload_length = frame_length;
340 if (source_frame.data) {
341 result_frame->data = new IOBuffer(frame_length);
342 memcpy(result_frame->data->data(), source_frame.data, frame_length);
[email protected]999bcaa2013-07-17 13:42:54343 }
dchengc7eeda422015-12-26 03:56:48344 result_frames.push_back(std::move(result_frame));
[email protected]999bcaa2013-07-17 13:42:54345 }
yhirano592ff7f2015-12-07 08:45:19346 return result_frames;
[email protected]999bcaa2013-07-17 13:42:54347}
348
349// A GoogleMock action which can be used to respond to call to ReadFrames with
[email protected]2f5d9f62013-09-26 12:14:28350// some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames));
351// |frames| is an array of InitFrame. |frames| needs to be passed by pointer
352// because otherwise it will be treated as a pointer and the array size
353// information will be lost.
354ACTION_P(ReturnFrames, source_frames) {
355 *arg0 = CreateFrameVector(*source_frames);
[email protected]999bcaa2013-07-17 13:42:54356 return OK;
357}
358
[email protected]c0d29c22013-07-26 20:40:41359// The implementation of a GoogleMock matcher which can be used to compare a
danakj9c5cab52016-04-16 00:54:33360// std::vector<std::unique_ptr<WebSocketFrame>>* against an expectation defined
361// as an
yhirano592ff7f2015-12-07 08:45:19362// array of InitFrame objects. Although it is possible to compose built-in
363// GoogleMock matchers to check the contents of a WebSocketFrame, the results
364// are so unreadable that it is better to use this matcher.
[email protected]c0d29c22013-07-26 20:40:41365template <size_t N>
yhirano592ff7f2015-12-07 08:45:19366class EqualsFramesMatcher : public ::testing::MatcherInterface<
danakj9c5cab52016-04-16 00:54:33367 std::vector<std::unique_ptr<WebSocketFrame>>*> {
[email protected]c0d29c22013-07-26 20:40:41368 public:
[email protected]2f5d9f62013-09-26 12:14:28369 EqualsFramesMatcher(const InitFrame (*expect_frames)[N])
370 : expect_frames_(expect_frames) {}
[email protected]c0d29c22013-07-26 20:40:41371
yhirano592ff7f2015-12-07 08:45:19372 virtual bool MatchAndExplain(
danakj9c5cab52016-04-16 00:54:33373 std::vector<std::unique_ptr<WebSocketFrame>>* actual_frames,
yhirano592ff7f2015-12-07 08:45:19374 ::testing::MatchResultListener* listener) const {
[email protected]2f5d9f62013-09-26 12:14:28375 if (actual_frames->size() != N) {
376 *listener << "the vector size is " << actual_frames->size();
[email protected]c0d29c22013-07-26 20:40:41377 return false;
378 }
379 for (size_t i = 0; i < N; ++i) {
[email protected]2f5d9f62013-09-26 12:14:28380 const WebSocketFrame& actual_frame = *(*actual_frames)[i];
381 const InitFrame& expected_frame = (*expect_frames_)[i];
382 if (actual_frame.header.final != (expected_frame.final == FINAL_FRAME)) {
383 *listener << "the frame is marked as "
384 << (actual_frame.header.final ? "" : "not ") << "final";
[email protected]c0d29c22013-07-26 20:40:41385 return false;
386 }
[email protected]2f5d9f62013-09-26 12:14:28387 if (actual_frame.header.opcode != expected_frame.opcode) {
388 *listener << "the opcode is " << actual_frame.header.opcode;
[email protected]c0d29c22013-07-26 20:40:41389 return false;
390 }
[email protected]2f5d9f62013-09-26 12:14:28391 if (actual_frame.header.masked != (expected_frame.masked == MASKED)) {
392 *listener << "the frame is "
393 << (actual_frame.header.masked ? "masked" : "not masked");
[email protected]c0d29c22013-07-26 20:40:41394 return false;
395 }
[email protected]2f5d9f62013-09-26 12:14:28396 const size_t expected_length =
397 expected_frame.data ? strlen(expected_frame.data) : 0;
398 if (actual_frame.header.payload_length != expected_length) {
399 *listener << "the payload length is "
400 << actual_frame.header.payload_length;
401 return false;
402 }
403 if (expected_length != 0 &&
404 memcmp(actual_frame.data->data(),
405 expected_frame.data,
406 actual_frame.header.payload_length) != 0) {
[email protected]c0d29c22013-07-26 20:40:41407 *listener << "the data content differs";
408 return false;
409 }
410 }
411 return true;
412 }
413
414 virtual void DescribeTo(std::ostream* os) const {
[email protected]2f5d9f62013-09-26 12:14:28415 *os << "matches " << *expect_frames_;
[email protected]c0d29c22013-07-26 20:40:41416 }
417
418 virtual void DescribeNegationTo(std::ostream* os) const {
[email protected]2f5d9f62013-09-26 12:14:28419 *os << "does not match " << *expect_frames_;
[email protected]c0d29c22013-07-26 20:40:41420 }
421
422 private:
[email protected]2f5d9f62013-09-26 12:14:28423 const InitFrame (*expect_frames_)[N];
[email protected]c0d29c22013-07-26 20:40:41424};
425
[email protected]2f5d9f62013-09-26 12:14:28426// The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames
[email protected]c0d29c22013-07-26 20:40:41427// action, this can take the array by reference.
428template <size_t N>
danakj9c5cab52016-04-16 00:54:33429::testing::Matcher<std::vector<std::unique_ptr<WebSocketFrame>>*> EqualsFrames(
430 const InitFrame (&frames)[N]) {
[email protected]2f5d9f62013-09-26 12:14:28431 return ::testing::MakeMatcher(new EqualsFramesMatcher<N>(&frames));
[email protected]c0d29c22013-07-26 20:40:41432}
433
[email protected]3a266762013-10-23 08:15:10434// A GoogleMock action to run a Closure.
435ACTION_P(InvokeClosure, closure) { closure.Run(); }
436
[email protected]f485985e2013-10-24 13:47:44437// A GoogleMock action to run a Closure and return CHANNEL_DELETED.
438ACTION_P(InvokeClosureReturnDeleted, closure) {
439 closure.Run();
440 return WebSocketEventInterface::CHANNEL_DELETED;
441}
442
[email protected]999bcaa2013-07-17 13:42:54443// A FakeWebSocketStream whose ReadFrames() function returns data.
444class ReadableFakeWebSocketStream : public FakeWebSocketStream {
445 public:
[email protected]ea56b982014-01-27 03:21:03446 enum IsSync { SYNC, ASYNC };
[email protected]999bcaa2013-07-17 13:42:54447
448 // After constructing the object, call PrepareReadFrames() once for each
449 // time you wish it to return from the test.
450 ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {}
451
452 // Check that all the prepared responses have been consumed.
dchengb03027d2014-10-21 12:00:20453 ~ReadableFakeWebSocketStream() override {
[email protected]999bcaa2013-07-17 13:42:54454 CHECK(index_ >= responses_.size());
455 CHECK(!read_frames_pending_);
456 }
457
[email protected]2f5d9f62013-09-26 12:14:28458 // Prepares a fake response. Fake responses will be returned from ReadFrames()
459 // in the same order they were prepared with PrepareReadFrames() and
460 // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
[email protected]999bcaa2013-07-17 13:42:54461 // return ERR_IO_PENDING and the callback will be scheduled to run on the
462 // message loop. This requires the test case to run the message loop. If
463 // |async| is SYNC, the response will be returned synchronously. |error| is
464 // returned directly from ReadFrames() in the synchronous case, or passed to
[email protected]2f5d9f62013-09-26 12:14:28465 // the callback in the asynchronous case. |frames| will be converted to a
danakj9c5cab52016-04-16 00:54:33466 // std::vector<std::unique_ptr<WebSocketFrame>> and copied to the pointer that
467 // was
yhirano592ff7f2015-12-07 08:45:19468 // passed to ReadFrames().
[email protected]999bcaa2013-07-17 13:42:54469 template <size_t N>
470 void PrepareReadFrames(IsSync async,
471 int error,
[email protected]2f5d9f62013-09-26 12:14:28472 const InitFrame (&frames)[N]) {
danakj9c5cab52016-04-16 00:54:33473 responses_.push_back(base::WrapUnique(
474 new Response(async, error, CreateFrameVector(frames))));
[email protected]999bcaa2013-07-17 13:42:54475 }
476
[email protected]c0d29c22013-07-26 20:40:41477 // An alternate version of PrepareReadFrames for when we need to construct
478 // the frames manually.
danakj9c5cab52016-04-16 00:54:33479 void PrepareRawReadFrames(
480 IsSync async,
481 int error,
482 std::vector<std::unique_ptr<WebSocketFrame>> frames) {
yhirano592ff7f2015-12-07 08:45:19483 responses_.push_back(
danakj9c5cab52016-04-16 00:54:33484 base::WrapUnique(new Response(async, error, std::move(frames))));
[email protected]c0d29c22013-07-26 20:40:41485 }
486
[email protected]999bcaa2013-07-17 13:42:54487 // Prepares a fake error response (ie. there is no data).
488 void PrepareReadFramesError(IsSync async, int error) {
danakj9c5cab52016-04-16 00:54:33489 responses_.push_back(base::WrapUnique(new Response(
490 async, error, std::vector<std::unique_ptr<WebSocketFrame>>())));
[email protected]999bcaa2013-07-17 13:42:54491 }
492
danakj9c5cab52016-04-16 00:54:33493 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20494 const CompletionCallback& callback) override {
[email protected]999bcaa2013-07-17 13:42:54495 CHECK(!read_frames_pending_);
496 if (index_ >= responses_.size())
497 return ERR_IO_PENDING;
498 if (responses_[index_]->async == ASYNC) {
499 read_frames_pending_ = true;
skyostil4891b25b2015-06-11 11:43:45500 base::ThreadTaskRunnerHandle::Get()->PostTask(
501 FROM_HERE, base::Bind(&ReadableFakeWebSocketStream::DoCallback,
502 base::Unretained(this), frames, callback));
[email protected]999bcaa2013-07-17 13:42:54503 return ERR_IO_PENDING;
504 } else {
[email protected]2f5d9f62013-09-26 12:14:28505 frames->swap(responses_[index_]->frames);
[email protected]999bcaa2013-07-17 13:42:54506 return responses_[index_++]->error;
507 }
508 }
509
510 private:
danakj9c5cab52016-04-16 00:54:33511 void DoCallback(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
[email protected]999bcaa2013-07-17 13:42:54512 const CompletionCallback& callback) {
513 read_frames_pending_ = false;
[email protected]2f5d9f62013-09-26 12:14:28514 frames->swap(responses_[index_]->frames);
[email protected]999bcaa2013-07-17 13:42:54515 callback.Run(responses_[index_++]->error);
516 return;
517 }
518
519 struct Response {
yhirano592ff7f2015-12-07 08:45:19520 Response(IsSync async,
521 int error,
danakj9c5cab52016-04-16 00:54:33522 std::vector<std::unique_ptr<WebSocketFrame>> frames)
yhirano592ff7f2015-12-07 08:45:19523 : async(async), error(error), frames(std::move(frames)) {}
[email protected]999bcaa2013-07-17 13:42:54524
525 IsSync async;
526 int error;
danakj9c5cab52016-04-16 00:54:33527 std::vector<std::unique_ptr<WebSocketFrame>> frames;
[email protected]999bcaa2013-07-17 13:42:54528
529 private:
[email protected]2f5d9f62013-09-26 12:14:28530 // Bad things will happen if we attempt to copy or assign |frames|.
[email protected]999bcaa2013-07-17 13:42:54531 DISALLOW_COPY_AND_ASSIGN(Response);
532 };
danakj9c5cab52016-04-16 00:54:33533 std::vector<std::unique_ptr<Response>> responses_;
[email protected]999bcaa2013-07-17 13:42:54534
535 // The index into the responses_ array of the next response to be returned.
536 size_t index_;
537
538 // True when an async response from ReadFrames() is pending. This only applies
539 // to "real" async responses. Once all the prepared responses have been
540 // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is
541 // not set to true.
542 bool read_frames_pending_;
543};
544
545// A FakeWebSocketStream where writes always complete successfully and
546// synchronously.
547class WriteableFakeWebSocketStream : public FakeWebSocketStream {
548 public:
danakj9c5cab52016-04-16 00:54:33549 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20550 const CompletionCallback& callback) override {
[email protected]999bcaa2013-07-17 13:42:54551 return OK;
552 }
553};
554
555// A FakeWebSocketStream where writes always fail.
556class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
557 public:
danakj9c5cab52016-04-16 00:54:33558 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20559 const CompletionCallback& callback) override {
[email protected]999bcaa2013-07-17 13:42:54560 return ERR_CONNECTION_RESET;
561 }
562};
563
564// A FakeWebSocketStream which echoes any frames written back. Clears the
565// "masked" header bit, but makes no other checks for validity. Tests using this
566// must run the MessageLoop to receive the callback(s). If a message with opcode
567// Close is echoed, then an ERR_CONNECTION_CLOSED is returned in the next
568// callback. The test must do something to cause WriteFrames() to be called,
569// otherwise the ReadFrames() callback will never be called.
570class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
571 public:
danakj9c5cab52016-04-16 00:54:33572 EchoeyFakeWebSocketStream() : read_frames_(nullptr), done_(false) {}
[email protected]999bcaa2013-07-17 13:42:54573
danakj9c5cab52016-04-16 00:54:33574 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20575 const CompletionCallback& callback) override {
yhirano592ff7f2015-12-07 08:45:19576 stored_frames_.insert(stored_frames_.end(),
577 std::make_move_iterator(frames->begin()),
578 std::make_move_iterator(frames->end()));
579 frames->clear();
[email protected]999bcaa2013-07-17 13:42:54580 // Users of WebSocketStream will not expect the ReadFrames() callback to be
581 // called from within WriteFrames(), so post it to the message loop instead.
[email protected]999bcaa2013-07-17 13:42:54582 PostCallback();
583 return OK;
584 }
585
danakj9c5cab52016-04-16 00:54:33586 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20587 const CompletionCallback& callback) override {
[email protected]999bcaa2013-07-17 13:42:54588 read_callback_ = callback;
[email protected]2f5d9f62013-09-26 12:14:28589 read_frames_ = frames;
[email protected]999bcaa2013-07-17 13:42:54590 if (done_)
591 PostCallback();
592 return ERR_IO_PENDING;
593 }
594
595 private:
596 void PostCallback() {
skyostil4891b25b2015-06-11 11:43:45597 base::ThreadTaskRunnerHandle::Get()->PostTask(
598 FROM_HERE, base::Bind(&EchoeyFakeWebSocketStream::DoCallback,
599 base::Unretained(this)));
[email protected]999bcaa2013-07-17 13:42:54600 }
601
602 void DoCallback() {
603 if (done_) {
604 read_callback_.Run(ERR_CONNECTION_CLOSED);
[email protected]2f5d9f62013-09-26 12:14:28605 } else if (!stored_frames_.empty()) {
606 done_ = MoveFrames(read_frames_);
danakj9c5cab52016-04-16 00:54:33607 read_frames_ = nullptr;
[email protected]999bcaa2013-07-17 13:42:54608 read_callback_.Run(OK);
609 }
610 }
611
[email protected]2f5d9f62013-09-26 12:14:28612 // Copy the frames stored in stored_frames_ to |out|, while clearing the
[email protected]999bcaa2013-07-17 13:42:54613 // "masked" header bit. Returns true if a Close Frame was seen, false
614 // otherwise.
danakj9c5cab52016-04-16 00:54:33615 bool MoveFrames(std::vector<std::unique_ptr<WebSocketFrame>>* out) {
[email protected]999bcaa2013-07-17 13:42:54616 bool seen_close = false;
yhirano592ff7f2015-12-07 08:45:19617 *out = std::move(stored_frames_);
618 for (const auto& frame : *out) {
619 WebSocketFrameHeader& header = frame->header;
[email protected]2f5d9f62013-09-26 12:14:28620 header.masked = false;
621 if (header.opcode == WebSocketFrameHeader::kOpCodeClose)
622 seen_close = true;
[email protected]999bcaa2013-07-17 13:42:54623 }
624 return seen_close;
625 }
626
danakj9c5cab52016-04-16 00:54:33627 std::vector<std::unique_ptr<WebSocketFrame>> stored_frames_;
[email protected]999bcaa2013-07-17 13:42:54628 CompletionCallback read_callback_;
629 // Owned by the caller of ReadFrames().
danakj9c5cab52016-04-16 00:54:33630 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames_;
[email protected]999bcaa2013-07-17 13:42:54631 // True if we should close the connection.
632 bool done_;
633};
634
[email protected]c0d29c22013-07-26 20:40:41635// A FakeWebSocketStream where writes trigger a connection reset.
636// This differs from UnWriteableFakeWebSocketStream in that it is asynchronous
637// and triggers ReadFrames to return a reset as well. Tests using this need to
[email protected]f485985e2013-10-24 13:47:44638// run the message loop. There are two tricky parts here:
639// 1. Calling the write callback may call Close(), after which the read callback
640// should not be called.
641// 2. Calling either callback may delete the stream altogether.
[email protected]c0d29c22013-07-26 20:40:41642class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
643 public:
[email protected]f485985e2013-10-24 13:47:44644 ResetOnWriteFakeWebSocketStream() : closed_(false), weak_ptr_factory_(this) {}
645
danakj9c5cab52016-04-16 00:54:33646 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20647 const CompletionCallback& callback) override {
skyostil4891b25b2015-06-11 11:43:45648 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]f485985e2013-10-24 13:47:44649 FROM_HERE,
650 base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
skyostil4891b25b2015-06-11 11:43:45651 weak_ptr_factory_.GetWeakPtr(), callback,
[email protected]f485985e2013-10-24 13:47:44652 ERR_CONNECTION_RESET));
skyostil4891b25b2015-06-11 11:43:45653 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]f485985e2013-10-24 13:47:44654 FROM_HERE,
655 base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
skyostil4891b25b2015-06-11 11:43:45656 weak_ptr_factory_.GetWeakPtr(), read_callback_,
[email protected]f485985e2013-10-24 13:47:44657 ERR_CONNECTION_RESET));
[email protected]c0d29c22013-07-26 20:40:41658 return ERR_IO_PENDING;
659 }
660
danakj9c5cab52016-04-16 00:54:33661 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
dchengb03027d2014-10-21 12:00:20662 const CompletionCallback& callback) override {
[email protected]c0d29c22013-07-26 20:40:41663 read_callback_ = callback;
664 return ERR_IO_PENDING;
665 }
666
dchengb03027d2014-10-21 12:00:20667 void Close() override { closed_ = true; }
[email protected]f485985e2013-10-24 13:47:44668
[email protected]c0d29c22013-07-26 20:40:41669 private:
[email protected]f485985e2013-10-24 13:47:44670 void CallCallbackUnlessClosed(const CompletionCallback& callback, int value) {
671 if (!closed_)
672 callback.Run(value);
673 }
674
[email protected]c0d29c22013-07-26 20:40:41675 CompletionCallback read_callback_;
[email protected]f485985e2013-10-24 13:47:44676 bool closed_;
677 // An IO error can result in the socket being deleted, so we use weak pointers
678 // to ensure correct behaviour in that case.
679 base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_;
[email protected]c0d29c22013-07-26 20:40:41680};
681
[email protected]999bcaa2013-07-17 13:42:54682// This mock is for verifying that WebSocket protocol semantics are obeyed (to
683// the extent that they are implemented in WebSocketCommon).
684class MockWebSocketStream : public WebSocketStream {
685 public:
686 MOCK_METHOD2(ReadFrames,
danakj9c5cab52016-04-16 00:54:33687 int(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
[email protected]999bcaa2013-07-17 13:42:54688 const CompletionCallback& callback));
689 MOCK_METHOD2(WriteFrames,
danakj9c5cab52016-04-16 00:54:33690 int(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
[email protected]999bcaa2013-07-17 13:42:54691 const CompletionCallback& callback));
692 MOCK_METHOD0(Close, void());
693 MOCK_CONST_METHOD0(GetSubProtocol, std::string());
694 MOCK_CONST_METHOD0(GetExtensions, std::string());
695 MOCK_METHOD0(AsWebSocketStream, WebSocketStream*());
[email protected]999bcaa2013-07-17 13:42:54696};
697
[email protected]969dde72013-11-13 15:59:14698struct ArgumentCopyingWebSocketStreamCreator {
danakj9c5cab52016-04-16 00:54:33699 std::unique_ptr<WebSocketStreamRequest> Create(
[email protected]999bcaa2013-07-17 13:42:54700 const GURL& socket_url,
701 const std::vector<std::string>& requested_subprotocols,
mkwst4997ce82015-07-25 12:00:05702 const url::Origin& origin,
[email protected]999bcaa2013-07-17 13:42:54703 URLRequestContext* url_request_context,
704 const BoundNetLog& net_log,
danakj9c5cab52016-04-16 00:54:33705 std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
[email protected]999bcaa2013-07-17 13:42:54706 this->socket_url = socket_url;
707 this->requested_subprotocols = requested_subprotocols;
708 this->origin = origin;
709 this->url_request_context = url_request_context;
710 this->net_log = net_log;
dchengc7eeda422015-12-26 03:56:48711 this->connect_delegate = std::move(connect_delegate);
danakj9c5cab52016-04-16 00:54:33712 return base::WrapUnique(new WebSocketStreamRequest);
[email protected]999bcaa2013-07-17 13:42:54713 }
714
715 GURL socket_url;
mkwst4997ce82015-07-25 12:00:05716 url::Origin origin;
[email protected]999bcaa2013-07-17 13:42:54717 std::vector<std::string> requested_subprotocols;
718 URLRequestContext* url_request_context;
719 BoundNetLog net_log;
danakj9c5cab52016-04-16 00:54:33720 std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate;
[email protected]999bcaa2013-07-17 13:42:54721};
722
723// Converts a std::string to a std::vector<char>. For test purposes, it is
724// convenient to be able to specify data as a string, but the
725// WebSocketEventInterface requires the vector<char> type.
726std::vector<char> AsVector(const std::string& s) {
727 return std::vector<char>(s.begin(), s.end());
728}
729
[email protected]a62449522014-06-05 11:11:15730class FakeSSLErrorCallbacks
731 : public WebSocketEventInterface::SSLErrorCallbacks {
732 public:
dchengb03027d2014-10-21 12:00:20733 void CancelSSLRequest(int error, const SSLInfo* ssl_info) override {}
734 void ContinueSSLRequest() override {}
[email protected]a62449522014-06-05 11:11:15735};
736
[email protected]999bcaa2013-07-17 13:42:54737// Base class for all test fixtures.
738class WebSocketChannelTest : public ::testing::Test {
739 protected:
740 WebSocketChannelTest() : stream_(new FakeWebSocketStream) {}
741
742 // Creates a new WebSocketChannel and connects it, using the settings stored
743 // in |connect_data_|.
744 void CreateChannelAndConnect() {
[email protected]dab33eb2013-10-08 02:27:51745 channel_.reset(new WebSocketChannel(CreateEventInterface(),
746 &connect_data_.url_request_context));
[email protected]999bcaa2013-07-17 13:42:54747 channel_->SendAddChannelRequestForTesting(
[email protected]72dd6fda2013-10-17 16:21:11748 connect_data_.socket_url,
[email protected]999bcaa2013-07-17 13:42:54749 connect_data_.requested_subprotocols,
750 connect_data_.origin,
[email protected]969dde72013-11-13 15:59:14751 base::Bind(&ArgumentCopyingWebSocketStreamCreator::Create,
752 base::Unretained(&connect_data_.creator)));
[email protected]999bcaa2013-07-17 13:42:54753 }
754
755 // Same as CreateChannelAndConnect(), but calls the on_success callback as
756 // well. This method is virtual so that subclasses can also set the stream.
757 virtual void CreateChannelAndConnectSuccessfully() {
758 CreateChannelAndConnect();
[email protected]4256dbb2014-03-24 15:39:36759 // Most tests aren't concerned with flow control from the renderer, so allow
760 // MAX_INT quota units.
yhiranod2727df2016-04-11 05:32:49761 EXPECT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(kPlentyOfQuota));
dchengc7eeda422015-12-26 03:56:48762 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]999bcaa2013-07-17 13:42:54763 }
764
765 // Returns a WebSocketEventInterface to be passed to the WebSocketChannel.
766 // This implementation returns a newly-created fake. Subclasses may return a
767 // mock instead.
danakj9c5cab52016-04-16 00:54:33768 virtual std::unique_ptr<WebSocketEventInterface> CreateEventInterface() {
769 return base::WrapUnique(new FakeWebSocketEventInterface);
[email protected]999bcaa2013-07-17 13:42:54770 }
771
772 // This method serves no other purpose than to provide a nice syntax for
773 // assigning to stream_. class T must be a subclass of WebSocketStream or you
774 // will have unpleasant compile errors.
775 template <class T>
danakj9c5cab52016-04-16 00:54:33776 void set_stream(std::unique_ptr<T> stream) {
dchengc7eeda422015-12-26 03:56:48777 stream_ = std::move(stream);
[email protected]999bcaa2013-07-17 13:42:54778 }
779
780 // A struct containing the data that will be used to connect the channel.
[email protected]72dd6fda2013-10-17 16:21:11781 // Grouped for readability.
[email protected]999bcaa2013-07-17 13:42:54782 struct ConnectData {
mkwst4997ce82015-07-25 12:00:05783 ConnectData() : socket_url("ws://ws/"), origin(GURL("http://ws")) {}
[email protected]53deacb2013-11-22 14:02:43784
[email protected]999bcaa2013-07-17 13:42:54785 // URLRequestContext object.
786 URLRequestContext url_request_context;
[email protected]72dd6fda2013-10-17 16:21:11787
788 // URL to (pretend to) connect to.
789 GURL socket_url;
790 // Requested protocols for the request.
791 std::vector<std::string> requested_subprotocols;
792 // Origin of the request
mkwst4997ce82015-07-25 12:00:05793 url::Origin origin;
[email protected]72dd6fda2013-10-17 16:21:11794
[email protected]969dde72013-11-13 15:59:14795 // A fake WebSocketStreamCreator that just records its arguments.
796 ArgumentCopyingWebSocketStreamCreator creator;
[email protected]999bcaa2013-07-17 13:42:54797 };
798 ConnectData connect_data_;
799
800 // The channel we are testing. Not initialised until SetChannel() is called.
danakj9c5cab52016-04-16 00:54:33801 std::unique_ptr<WebSocketChannel> channel_;
[email protected]999bcaa2013-07-17 13:42:54802
803 // A mock or fake stream for tests that need one.
danakj9c5cab52016-04-16 00:54:33804 std::unique_ptr<WebSocketStream> stream_;
[email protected]999bcaa2013-07-17 13:42:54805};
806
[email protected]f485985e2013-10-24 13:47:44807// enum of WebSocketEventInterface calls. These are intended to be or'd together
808// in order to instruct WebSocketChannelDeletingTest when it should fail.
809enum EventInterfaceCall {
810 EVENT_ON_ADD_CHANNEL_RESPONSE = 0x1,
811 EVENT_ON_DATA_FRAME = 0x2,
812 EVENT_ON_FLOW_CONTROL = 0x4,
813 EVENT_ON_CLOSING_HANDSHAKE = 0x8,
[email protected]96868202014-01-09 10:38:04814 EVENT_ON_FAIL_CHANNEL = 0x10,
815 EVENT_ON_DROP_CHANNEL = 0x20,
[email protected]cd48ed12014-01-22 14:34:22816 EVENT_ON_START_OPENING_HANDSHAKE = 0x40,
817 EVENT_ON_FINISH_OPENING_HANDSHAKE = 0x80,
[email protected]a62449522014-06-05 11:11:15818 EVENT_ON_SSL_CERTIFICATE_ERROR = 0x100,
[email protected]f485985e2013-10-24 13:47:44819};
820
[email protected]c0d29c22013-07-26 20:40:41821class WebSocketChannelDeletingTest : public WebSocketChannelTest {
822 public:
[email protected]f485985e2013-10-24 13:47:44823 ChannelState DeleteIfDeleting(EventInterfaceCall call) {
824 if (deleting_ & call) {
825 channel_.reset();
826 return CHANNEL_DELETED;
827 } else {
828 return CHANNEL_ALIVE;
829 }
830 }
[email protected]c0d29c22013-07-26 20:40:41831
832 protected:
[email protected]f485985e2013-10-24 13:47:44833 WebSocketChannelDeletingTest()
834 : deleting_(EVENT_ON_ADD_CHANNEL_RESPONSE | EVENT_ON_DATA_FRAME |
835 EVENT_ON_FLOW_CONTROL |
836 EVENT_ON_CLOSING_HANDSHAKE |
[email protected]96868202014-01-09 10:38:04837 EVENT_ON_FAIL_CHANNEL |
[email protected]cd48ed12014-01-22 14:34:22838 EVENT_ON_DROP_CHANNEL |
839 EVENT_ON_START_OPENING_HANDSHAKE |
[email protected]a62449522014-06-05 11:11:15840 EVENT_ON_FINISH_OPENING_HANDSHAKE |
841 EVENT_ON_SSL_CERTIFICATE_ERROR) {}
[email protected]c0d29c22013-07-26 20:40:41842 // Create a ChannelDeletingFakeWebSocketEventInterface. Defined out-of-line to
843 // avoid circular dependency.
danakj9c5cab52016-04-16 00:54:33844 std::unique_ptr<WebSocketEventInterface> CreateEventInterface() override;
[email protected]f485985e2013-10-24 13:47:44845
846 // Tests can set deleting_ to a bitmap of EventInterfaceCall members that they
847 // want to cause Channel deletion. The default is for all calls to cause
848 // deletion.
849 int deleting_;
[email protected]c0d29c22013-07-26 20:40:41850};
851
852// A FakeWebSocketEventInterface that deletes the WebSocketChannel on failure to
853// connect.
854class ChannelDeletingFakeWebSocketEventInterface
855 : public FakeWebSocketEventInterface {
856 public:
857 ChannelDeletingFakeWebSocketEventInterface(
858 WebSocketChannelDeletingTest* fixture)
859 : fixture_(fixture) {}
860
tyoshinoc06da562015-03-06 06:02:42861 ChannelState OnAddChannelResponse(const std::string& selected_protocol,
dchengb03027d2014-10-21 12:00:20862 const std::string& extensions) override {
[email protected]f485985e2013-10-24 13:47:44863 return fixture_->DeleteIfDeleting(EVENT_ON_ADD_CHANNEL_RESPONSE);
864 }
865
dchengb03027d2014-10-21 12:00:20866 ChannelState OnDataFrame(bool fin,
867 WebSocketMessageType type,
868 const std::vector<char>& data) override {
[email protected]f485985e2013-10-24 13:47:44869 return fixture_->DeleteIfDeleting(EVENT_ON_DATA_FRAME);
870 }
871
tfarina8a2c66c22015-10-13 19:14:49872 ChannelState OnFlowControl(int64_t quota) override {
[email protected]f485985e2013-10-24 13:47:44873 return fixture_->DeleteIfDeleting(EVENT_ON_FLOW_CONTROL);
874 }
875
dchengb03027d2014-10-21 12:00:20876 ChannelState OnClosingHandshake() override {
[email protected]f485985e2013-10-24 13:47:44877 return fixture_->DeleteIfDeleting(EVENT_ON_CLOSING_HANDSHAKE);
878 }
879
dchengb03027d2014-10-21 12:00:20880 ChannelState OnFailChannel(const std::string& message) override {
[email protected]96868202014-01-09 10:38:04881 return fixture_->DeleteIfDeleting(EVENT_ON_FAIL_CHANNEL);
882 }
883
dchengb03027d2014-10-21 12:00:20884 ChannelState OnDropChannel(bool was_clean,
tfarina8a2c66c22015-10-13 19:14:49885 uint16_t code,
dchengb03027d2014-10-21 12:00:20886 const std::string& reason) override {
[email protected]f485985e2013-10-24 13:47:44887 return fixture_->DeleteIfDeleting(EVENT_ON_DROP_CHANNEL);
[email protected]c0d29c22013-07-26 20:40:41888 }
889
dchengb03027d2014-10-21 12:00:20890 ChannelState OnStartOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33891 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {
[email protected]cd48ed12014-01-22 14:34:22892 return fixture_->DeleteIfDeleting(EVENT_ON_START_OPENING_HANDSHAKE);
893 }
dchengb03027d2014-10-21 12:00:20894 ChannelState OnFinishOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33895 std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {
[email protected]cd48ed12014-01-22 14:34:22896 return fixture_->DeleteIfDeleting(EVENT_ON_FINISH_OPENING_HANDSHAKE);
897 }
dchengb03027d2014-10-21 12:00:20898 ChannelState OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33899 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
[email protected]a62449522014-06-05 11:11:15900 const GURL& url,
901 const SSLInfo& ssl_info,
mostynbba063d6032014-10-09 11:01:13902 bool fatal) override {
[email protected]a62449522014-06-05 11:11:15903 return fixture_->DeleteIfDeleting(EVENT_ON_SSL_CERTIFICATE_ERROR);
904 }
[email protected]cd48ed12014-01-22 14:34:22905
[email protected]c0d29c22013-07-26 20:40:41906 private:
907 // A pointer to the test fixture. Owned by the test harness; this object will
908 // be deleted before it is.
909 WebSocketChannelDeletingTest* fixture_;
910};
911
danakj9c5cab52016-04-16 00:54:33912std::unique_ptr<WebSocketEventInterface>
[email protected]c0d29c22013-07-26 20:40:41913WebSocketChannelDeletingTest::CreateEventInterface() {
danakj9c5cab52016-04-16 00:54:33914 return base::WrapUnique(new ChannelDeletingFakeWebSocketEventInterface(this));
[email protected]c0d29c22013-07-26 20:40:41915}
916
[email protected]999bcaa2013-07-17 13:42:54917// Base class for tests which verify that EventInterface methods are called
918// appropriately.
919class WebSocketChannelEventInterfaceTest : public WebSocketChannelTest {
920 protected:
921 WebSocketChannelEventInterfaceTest()
[email protected]f485985e2013-10-24 13:47:44922 : event_interface_(new StrictMock<MockWebSocketEventInterface>) {
923 DefaultValue<ChannelState>::Set(CHANNEL_ALIVE);
[email protected]86ec55502014-02-10 13:16:16924 ON_CALL(*event_interface_, OnDropChannel(_, _, _))
[email protected]f485985e2013-10-24 13:47:44925 .WillByDefault(Return(CHANNEL_DELETED));
[email protected]ea56b982014-01-27 03:21:03926 ON_CALL(*event_interface_, OnFailChannel(_))
927 .WillByDefault(Return(CHANNEL_DELETED));
[email protected]f485985e2013-10-24 13:47:44928 }
929
dcheng67be2b1f2014-10-27 21:47:29930 ~WebSocketChannelEventInterfaceTest() override {
[email protected]f485985e2013-10-24 13:47:44931 DefaultValue<ChannelState>::Clear();
932 }
[email protected]999bcaa2013-07-17 13:42:54933
934 // Tests using this fixture must set expectations on the event_interface_ mock
935 // object before calling CreateChannelAndConnect() or
936 // CreateChannelAndConnectSuccessfully(). This will only work once per test
937 // case, but once should be enough.
danakj9c5cab52016-04-16 00:54:33938 std::unique_ptr<WebSocketEventInterface> CreateEventInterface() override {
939 return base::WrapUnique(event_interface_.release());
[email protected]999bcaa2013-07-17 13:42:54940 }
941
danakj9c5cab52016-04-16 00:54:33942 std::unique_ptr<MockWebSocketEventInterface> event_interface_;
[email protected]999bcaa2013-07-17 13:42:54943};
944
945// Base class for tests which verify that WebSocketStream methods are called
946// appropriately by using a MockWebSocketStream.
947class WebSocketChannelStreamTest : public WebSocketChannelTest {
948 protected:
949 WebSocketChannelStreamTest()
950 : mock_stream_(new StrictMock<MockWebSocketStream>) {}
951
dchengb03027d2014-10-21 12:00:20952 void CreateChannelAndConnectSuccessfully() override {
dchengc7eeda422015-12-26 03:56:48953 set_stream(std::move(mock_stream_));
[email protected]999bcaa2013-07-17 13:42:54954 WebSocketChannelTest::CreateChannelAndConnectSuccessfully();
955 }
956
danakj9c5cab52016-04-16 00:54:33957 std::unique_ptr<MockWebSocketStream> mock_stream_;
[email protected]999bcaa2013-07-17 13:42:54958};
959
[email protected]48cc6922014-02-10 14:20:48960// Fixture for tests which test UTF-8 validation of sent Text frames via the
961// EventInterface.
962class WebSocketChannelSendUtf8Test
963 : public WebSocketChannelEventInterfaceTest {
964 public:
dcheng67be2b1f2014-10-27 21:47:29965 void SetUp() override {
danakj9c5cab52016-04-16 00:54:33966 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
[email protected]48cc6922014-02-10 14:20:48967 // For the purpose of the tests using this fixture, it doesn't matter
968 // whether these methods are called or not.
tyoshinoc06da562015-03-06 06:02:42969 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _))
[email protected]48cc6922014-02-10 14:20:48970 .Times(AnyNumber());
971 EXPECT_CALL(*event_interface_, OnFlowControl(_))
972 .Times(AnyNumber());
973 }
974};
975
[email protected]4256dbb2014-03-24 15:39:36976// Fixture for tests which test use of receive quota from the renderer.
977class WebSocketChannelFlowControlTest
978 : public WebSocketChannelEventInterfaceTest {
979 protected:
980 // Tests using this fixture should use CreateChannelAndConnectWithQuota()
981 // instead of CreateChannelAndConnectSuccessfully().
tfarina8a2c66c22015-10-13 19:14:49982 void CreateChannelAndConnectWithQuota(int64_t quota) {
[email protected]4256dbb2014-03-24 15:39:36983 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:49984 EXPECT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(quota));
dchengc7eeda422015-12-26 03:56:48985 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]4256dbb2014-03-24 15:39:36986 }
987
988 virtual void CreateChannelAndConnectSuccesfully() { NOTREACHED(); }
989};
990
[email protected]48cc6922014-02-10 14:20:48991// Fixture for tests which test UTF-8 validation of received Text frames using a
992// mock WebSocketStream.
993class WebSocketChannelReceiveUtf8Test : public WebSocketChannelStreamTest {
994 public:
dcheng67be2b1f2014-10-27 21:47:29995 void SetUp() override {
[email protected]48cc6922014-02-10 14:20:48996 // For the purpose of the tests using this fixture, it doesn't matter
997 // whether these methods are called or not.
998 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
999 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
1000 }
1001};
1002
[email protected]969dde72013-11-13 15:59:141003// Simple test that everything that should be passed to the creator function is
1004// passed to the creator function.
1005TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) {
[email protected]72dd6fda2013-10-17 16:21:111006 connect_data_.socket_url = GURL("ws://example.com/test");
mkwst4997ce82015-07-25 12:00:051007 connect_data_.origin = url::Origin(GURL("http://example.com"));
[email protected]999bcaa2013-07-17 13:42:541008 connect_data_.requested_subprotocols.push_back("Sinbad");
1009
1010 CreateChannelAndConnect();
1011
[email protected]969dde72013-11-13 15:59:141012 const ArgumentCopyingWebSocketStreamCreator& actual = connect_data_.creator;
[email protected]72dd6fda2013-10-17 16:21:111013
1014 EXPECT_EQ(&connect_data_.url_request_context, actual.url_request_context);
1015
1016 EXPECT_EQ(connect_data_.socket_url, actual.socket_url);
[email protected]999bcaa2013-07-17 13:42:541017 EXPECT_EQ(connect_data_.requested_subprotocols,
[email protected]72dd6fda2013-10-17 16:21:111018 actual.requested_subprotocols);
mkwst4997ce82015-07-25 12:00:051019 EXPECT_EQ(connect_data_.origin.Serialize(), actual.origin.Serialize());
[email protected]999bcaa2013-07-17 13:42:541020}
1021
[email protected]abda70d2013-12-12 07:53:541022// Verify that calling SendFlowControl before the connection is established does
1023// not cause a crash.
1024TEST_F(WebSocketChannelTest, SendFlowControlDuringHandshakeOkay) {
1025 CreateChannelAndConnect();
1026 ASSERT_TRUE(channel_);
yhiranod2727df2016-04-11 05:32:491027 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(65536));
[email protected]abda70d2013-12-12 07:53:541028}
1029
[email protected]f485985e2013-10-24 13:47:441030// Any WebSocketEventInterface methods can delete the WebSocketChannel and
1031// return CHANNEL_DELETED. The WebSocketChannelDeletingTests are intended to
1032// verify that there are no use-after-free bugs when this happens. Problems will
1033// probably only be found when running under Address Sanitizer or a similar
1034// tool.
1035TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseFail) {
[email protected]c0d29c22013-07-26 20:40:411036 CreateChannelAndConnect();
[email protected]f485985e2013-10-24 13:47:441037 EXPECT_TRUE(channel_);
[email protected]96868202014-01-09 10:38:041038 connect_data_.creator.connect_delegate->OnFailure("bye");
danakj9c5cab52016-04-16 00:54:331039 EXPECT_EQ(nullptr, channel_.get());
[email protected]c0d29c22013-07-26 20:40:411040}
1041
[email protected]f485985e2013-10-24 13:47:441042// Deletion is possible (due to IPC failure) even if the connect succeeds.
1043TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseSuccess) {
1044 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331045 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441046}
1047
1048TEST_F(WebSocketChannelDeletingTest, OnDataFrameSync) {
danakj9c5cab52016-04-16 00:54:331049 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441050 new ReadableFakeWebSocketStream);
1051 static const InitFrame frames[] = {
1052 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1053 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481054 set_stream(std::move(stream));
[email protected]f485985e2013-10-24 13:47:441055 deleting_ = EVENT_ON_DATA_FRAME;
1056
1057 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331058 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441059}
1060
1061TEST_F(WebSocketChannelDeletingTest, OnDataFrameAsync) {
danakj9c5cab52016-04-16 00:54:331062 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441063 new ReadableFakeWebSocketStream);
1064 static const InitFrame frames[] = {
1065 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1066 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481067 set_stream(std::move(stream));
[email protected]f485985e2013-10-24 13:47:441068 deleting_ = EVENT_ON_DATA_FRAME;
1069
1070 CreateChannelAndConnectSuccessfully();
1071 EXPECT_TRUE(channel_);
fdoray92e35a72016-06-10 15:54:551072 base::RunLoop().RunUntilIdle();
danakj9c5cab52016-04-16 00:54:331073 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441074}
1075
1076TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterConnect) {
1077 deleting_ = EVENT_ON_FLOW_CONTROL;
1078
1079 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331080 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441081}
1082
1083TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterSend) {
danakj9c5cab52016-04-16 00:54:331084 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
[email protected]f485985e2013-10-24 13:47:441085 // Avoid deleting the channel yet.
[email protected]96868202014-01-09 10:38:041086 deleting_ = EVENT_ON_FAIL_CHANNEL | EVENT_ON_DROP_CHANNEL;
[email protected]f485985e2013-10-24 13:47:441087 CreateChannelAndConnectSuccessfully();
1088 ASSERT_TRUE(channel_);
1089 deleting_ = EVENT_ON_FLOW_CONTROL;
1090 channel_->SendFrame(true,
1091 WebSocketFrameHeader::kOpCodeText,
1092 std::vector<char>(kDefaultInitialQuota, 'B'));
danakj9c5cab52016-04-16 00:54:331093 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441094}
1095
1096TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeSync) {
danakj9c5cab52016-04-16 00:54:331097 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441098 new ReadableFakeWebSocketStream);
1099 static const InitFrame frames[] = {
1100 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1101 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
1102 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481103 set_stream(std::move(stream));
[email protected]f485985e2013-10-24 13:47:441104 deleting_ = EVENT_ON_CLOSING_HANDSHAKE;
1105 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331106 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441107}
1108
1109TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeAsync) {
danakj9c5cab52016-04-16 00:54:331110 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441111 new ReadableFakeWebSocketStream);
1112 static const InitFrame frames[] = {
1113 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1114 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
1115 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481116 set_stream(std::move(stream));
[email protected]f485985e2013-10-24 13:47:441117 deleting_ = EVENT_ON_CLOSING_HANDSHAKE;
1118 CreateChannelAndConnectSuccessfully();
1119 ASSERT_TRUE(channel_);
fdoray92e35a72016-06-10 15:54:551120 base::RunLoop().RunUntilIdle();
danakj9c5cab52016-04-16 00:54:331121 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441122}
1123
1124TEST_F(WebSocketChannelDeletingTest, OnDropChannelWriteError) {
danakj9c5cab52016-04-16 00:54:331125 set_stream(base::WrapUnique(new UnWriteableFakeWebSocketStream));
[email protected]f485985e2013-10-24 13:47:441126 deleting_ = EVENT_ON_DROP_CHANNEL;
1127 CreateChannelAndConnectSuccessfully();
1128 ASSERT_TRUE(channel_);
1129 channel_->SendFrame(
1130 true, WebSocketFrameHeader::kOpCodeText, AsVector("this will fail"));
danakj9c5cab52016-04-16 00:54:331131 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441132}
1133
1134TEST_F(WebSocketChannelDeletingTest, OnDropChannelReadError) {
danakj9c5cab52016-04-16 00:54:331135 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441136 new ReadableFakeWebSocketStream);
1137 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1138 ERR_FAILED);
dchengc7eeda422015-12-26 03:56:481139 set_stream(std::move(stream));
[email protected]f485985e2013-10-24 13:47:441140 deleting_ = EVENT_ON_DROP_CHANNEL;
1141 CreateChannelAndConnectSuccessfully();
1142 ASSERT_TRUE(channel_);
fdoray92e35a72016-06-10 15:54:551143 base::RunLoop().RunUntilIdle();
danakj9c5cab52016-04-16 00:54:331144 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441145}
1146
[email protected]cd48ed12014-01-22 14:34:221147TEST_F(WebSocketChannelDeletingTest, OnNotifyStartOpeningHandshakeError) {
danakj9c5cab52016-04-16 00:54:331148 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]cd48ed12014-01-22 14:34:221149 new ReadableFakeWebSocketStream);
1150 static const InitFrame frames[] = {
1151 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1152 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481153 set_stream(std::move(stream));
[email protected]cd48ed12014-01-22 14:34:221154 deleting_ = EVENT_ON_START_OPENING_HANDSHAKE;
1155
1156 CreateChannelAndConnectSuccessfully();
1157 ASSERT_TRUE(channel_);
danakj9c5cab52016-04-16 00:54:331158 channel_->OnStartOpeningHandshake(
1159 std::unique_ptr<WebSocketHandshakeRequestInfo>(
1160 new WebSocketHandshakeRequestInfo(GURL("http://www.example.com/"),
1161 base::Time())));
fdoray92e35a72016-06-10 15:54:551162 base::RunLoop().RunUntilIdle();
danakj9c5cab52016-04-16 00:54:331163 EXPECT_EQ(nullptr, channel_.get());
[email protected]cd48ed12014-01-22 14:34:221164}
1165
1166TEST_F(WebSocketChannelDeletingTest, OnNotifyFinishOpeningHandshakeError) {
danakj9c5cab52016-04-16 00:54:331167 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]cd48ed12014-01-22 14:34:221168 new ReadableFakeWebSocketStream);
1169 static const InitFrame frames[] = {
1170 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1171 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481172 set_stream(std::move(stream));
[email protected]cd48ed12014-01-22 14:34:221173 deleting_ = EVENT_ON_FINISH_OPENING_HANDSHAKE;
1174
1175 CreateChannelAndConnectSuccessfully();
1176 ASSERT_TRUE(channel_);
1177 scoped_refptr<HttpResponseHeaders> response_headers(
1178 new HttpResponseHeaders(""));
danakj9c5cab52016-04-16 00:54:331179 channel_->OnFinishOpeningHandshake(
1180 base::WrapUnique(new WebSocketHandshakeResponseInfo(
1181 GURL("http://www.example.com/"), 200, "OK", response_headers,
1182 base::Time())));
fdoray92e35a72016-06-10 15:54:551183 base::RunLoop().RunUntilIdle();
danakj9c5cab52016-04-16 00:54:331184 EXPECT_EQ(nullptr, channel_.get());
[email protected]cd48ed12014-01-22 14:34:221185}
1186
[email protected]f485985e2013-10-24 13:47:441187TEST_F(WebSocketChannelDeletingTest, FailChannelInSendFrame) {
danakj9c5cab52016-04-16 00:54:331188 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
[email protected]ea56b982014-01-27 03:21:031189 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]f485985e2013-10-24 13:47:441190 CreateChannelAndConnectSuccessfully();
1191 ASSERT_TRUE(channel_);
1192 channel_->SendFrame(true,
1193 WebSocketFrameHeader::kOpCodeText,
1194 std::vector<char>(kDefaultInitialQuota * 2, 'T'));
danakj9c5cab52016-04-16 00:54:331195 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441196}
1197
1198TEST_F(WebSocketChannelDeletingTest, FailChannelInOnReadDone) {
danakj9c5cab52016-04-16 00:54:331199 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441200 new ReadableFakeWebSocketStream);
1201 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1202 ERR_WS_PROTOCOL_ERROR);
dchengc7eeda422015-12-26 03:56:481203 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031204 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]f485985e2013-10-24 13:47:441205 CreateChannelAndConnectSuccessfully();
1206 ASSERT_TRUE(channel_);
fdoray92e35a72016-06-10 15:54:551207 base::RunLoop().RunUntilIdle();
danakj9c5cab52016-04-16 00:54:331208 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441209}
1210
1211TEST_F(WebSocketChannelDeletingTest, FailChannelDueToMaskedFrame) {
danakj9c5cab52016-04-16 00:54:331212 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441213 new ReadableFakeWebSocketStream);
1214 static const InitFrame frames[] = {
1215 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
1216 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481217 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031218 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]f485985e2013-10-24 13:47:441219
1220 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331221 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441222}
1223
1224TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrame) {
danakj9c5cab52016-04-16 00:54:331225 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441226 new ReadableFakeWebSocketStream);
1227 static const InitFrame frames[] = {
[email protected]bae48422014-03-05 15:07:251228 {FINAL_FRAME, 0xF, NOT_MASKED, ""}};
[email protected]f485985e2013-10-24 13:47:441229 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481230 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031231 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]f485985e2013-10-24 13:47:441232
1233 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331234 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441235}
1236
danakj9c5cab52016-04-16 00:54:331237// Version of above test with null data.
[email protected]00f4daf2013-11-12 13:56:411238TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrameNull) {
danakj9c5cab52016-04-16 00:54:331239 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]00f4daf2013-11-12 13:56:411240 new ReadableFakeWebSocketStream);
danakj9c5cab52016-04-16 00:54:331241 static const InitFrame frames[] = {{FINAL_FRAME, 0xF, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411242 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481243 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031244 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]00f4daf2013-11-12 13:56:411245
1246 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331247 EXPECT_EQ(nullptr, channel_.get());
[email protected]00f4daf2013-11-12 13:56:411248}
1249
[email protected]f485985e2013-10-24 13:47:441250TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterClose) {
danakj9c5cab52016-04-16 00:54:331251 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441252 new ReadableFakeWebSocketStream);
1253 static const InitFrame frames[] = {
[email protected]ea56b982014-01-27 03:21:031254 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1255 CLOSE_DATA(NORMAL_CLOSURE, "Success")},
1256 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
[email protected]f485985e2013-10-24 13:47:441257 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481258 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031259 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]f485985e2013-10-24 13:47:441260
1261 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331262 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441263}
1264
[email protected]00f4daf2013-11-12 13:56:411265TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterCloseNull) {
danakj9c5cab52016-04-16 00:54:331266 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]00f4daf2013-11-12 13:56:411267 new ReadableFakeWebSocketStream);
1268 static const InitFrame frames[] = {
[email protected]ea56b982014-01-27 03:21:031269 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1270 CLOSE_DATA(NORMAL_CLOSURE, "Success")},
danakj9c5cab52016-04-16 00:54:331271 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411272 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481273 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031274 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]00f4daf2013-11-12 13:56:411275
1276 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331277 EXPECT_EQ(nullptr, channel_.get());
[email protected]00f4daf2013-11-12 13:56:411278}
1279
[email protected]f485985e2013-10-24 13:47:441280TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCode) {
danakj9c5cab52016-04-16 00:54:331281 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]f485985e2013-10-24 13:47:441282 new ReadableFakeWebSocketStream);
1283 static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, ""}};
1284 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481285 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031286 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]f485985e2013-10-24 13:47:441287
1288 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331289 EXPECT_EQ(nullptr, channel_.get());
[email protected]f485985e2013-10-24 13:47:441290}
1291
[email protected]00f4daf2013-11-12 13:56:411292TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCodeNull) {
danakj9c5cab52016-04-16 00:54:331293 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]00f4daf2013-11-12 13:56:411294 new ReadableFakeWebSocketStream);
danakj9c5cab52016-04-16 00:54:331295 static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411296 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481297 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031298 deleting_ = EVENT_ON_FAIL_CHANNEL;
1299
1300 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331301 EXPECT_EQ(nullptr, channel_.get());
[email protected]ea56b982014-01-27 03:21:031302}
1303
1304TEST_F(WebSocketChannelDeletingTest, FailChannelDueInvalidCloseReason) {
danakj9c5cab52016-04-16 00:54:331305 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]ea56b982014-01-27 03:21:031306 new ReadableFakeWebSocketStream);
[email protected]48cc6922014-02-10 14:20:481307 static const InitFrame frames[] = {
[email protected]ea56b982014-01-27 03:21:031308 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1309 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
1310 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481311 set_stream(std::move(stream));
[email protected]ea56b982014-01-27 03:21:031312 deleting_ = EVENT_ON_FAIL_CHANNEL;
[email protected]00f4daf2013-11-12 13:56:411313
1314 CreateChannelAndConnectSuccessfully();
danakj9c5cab52016-04-16 00:54:331315 EXPECT_EQ(nullptr, channel_.get());
[email protected]00f4daf2013-11-12 13:56:411316}
1317
[email protected]999bcaa2013-07-17 13:42:541318TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) {
1319 // false means success.
tyoshinoc06da562015-03-06 06:02:421320 EXPECT_CALL(*event_interface_, OnAddChannelResponse("", ""));
[email protected]999bcaa2013-07-17 13:42:541321 // OnFlowControl is always called immediately after connect to provide initial
1322 // quota to the renderer.
1323 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1324
1325 CreateChannelAndConnect();
1326
dchengc7eeda422015-12-26 03:56:481327 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]999bcaa2013-07-17 13:42:541328}
1329
1330TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) {
[email protected]96868202014-01-09 10:38:041331 EXPECT_CALL(*event_interface_, OnFailChannel("hello"));
[email protected]999bcaa2013-07-17 13:42:541332
1333 CreateChannelAndConnect();
1334
[email protected]96868202014-01-09 10:38:041335 connect_data_.creator.connect_delegate->OnFailure("hello");
[email protected]999bcaa2013-07-17 13:42:541336}
1337
[email protected]53deacb2013-11-22 14:02:431338TEST_F(WebSocketChannelEventInterfaceTest, NonWebSocketSchemeRejected) {
tyoshinoc06da562015-03-06 06:02:421339 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid scheme"));
[email protected]53deacb2013-11-22 14:02:431340 connect_data_.socket_url = GURL("http://www.google.com/");
1341 CreateChannelAndConnect();
1342}
1343
[email protected]999bcaa2013-07-17 13:42:541344TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
tyoshinoc06da562015-03-06 06:02:421345 EXPECT_CALL(*event_interface_, OnAddChannelResponse("Bob", ""));
[email protected]999bcaa2013-07-17 13:42:541346 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1347
1348 CreateChannelAndConnect();
1349
[email protected]969dde72013-11-13 15:59:141350 connect_data_.creator.connect_delegate->OnSuccess(
danakj9c5cab52016-04-16 00:54:331351 base::WrapUnique(new FakeWebSocketStream("Bob", "")));
[email protected]999bcaa2013-07-17 13:42:541352}
1353
[email protected]6c5d9f62014-01-27 15:05:211354TEST_F(WebSocketChannelEventInterfaceTest, ExtensionsPassed) {
1355 EXPECT_CALL(*event_interface_,
tyoshinoc06da562015-03-06 06:02:421356 OnAddChannelResponse("", "extension1, extension2"));
[email protected]6c5d9f62014-01-27 15:05:211357 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1358
1359 CreateChannelAndConnect();
1360
danakj9c5cab52016-04-16 00:54:331361 connect_data_.creator.connect_delegate->OnSuccess(
1362 base::WrapUnique(new FakeWebSocketStream("", "extension1, extension2")));
[email protected]6c5d9f62014-01-27 15:05:211363}
1364
[email protected]999bcaa2013-07-17 13:42:541365// The first frames from the server can arrive together with the handshake, in
1366// which case they will be available as soon as ReadFrames() is called the first
1367// time.
1368TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
danakj9c5cab52016-04-16 00:54:331369 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541370 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281371 static const InitFrame frames[] = {
1372 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1373 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481374 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541375 {
1376 InSequence s;
tyoshinoc06da562015-03-06 06:02:421377 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541378 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1379 EXPECT_CALL(
1380 *event_interface_,
1381 OnDataFrame(
1382 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
1383 }
1384
1385 CreateChannelAndConnectSuccessfully();
1386}
1387
1388// A remote server could accept the handshake, but then immediately send a
1389// Close frame.
1390TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) {
danakj9c5cab52016-04-16 00:54:331391 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541392 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281393 static const InitFrame frames[] = {
1394 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1395 NOT_MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
1396 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
[email protected]999bcaa2013-07-17 13:42:541397 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1398 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481399 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541400 {
1401 InSequence s;
tyoshinoc06da562015-03-06 06:02:421402 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541403 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1404 EXPECT_CALL(*event_interface_, OnClosingHandshake());
[email protected]86ec55502014-02-10 13:16:161405 EXPECT_CALL(
1406 *event_interface_,
1407 OnDropChannel(
1408 true, kWebSocketErrorInternalServerError, "Internal Server Error"));
[email protected]999bcaa2013-07-17 13:42:541409 }
1410
1411 CreateChannelAndConnectSuccessfully();
1412}
1413
1414// A remote server could close the connection immediately after sending the
1415// handshake response (most likely a bug in the server).
1416TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) {
danakj9c5cab52016-04-16 00:54:331417 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541418 new ReadableFakeWebSocketStream);
1419 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1420 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481421 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541422 {
1423 InSequence s;
tyoshinoc06da562015-03-06 06:02:421424 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541425 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1426 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161427 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541428 }
1429
1430 CreateChannelAndConnectSuccessfully();
1431}
1432
1433TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
danakj9c5cab52016-04-16 00:54:331434 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541435 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281436 static const InitFrame frames[] = {
1437 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
[email protected]999bcaa2013-07-17 13:42:541438 // We use this checkpoint object to verify that the callback isn't called
1439 // until we expect it to be.
[email protected]f485985e2013-10-24 13:47:441440 Checkpoint checkpoint;
[email protected]2f5d9f62013-09-26 12:14:281441 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481442 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541443 {
1444 InSequence s;
tyoshinoc06da562015-03-06 06:02:421445 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541446 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1447 EXPECT_CALL(checkpoint, Call(1));
1448 EXPECT_CALL(
1449 *event_interface_,
1450 OnDataFrame(
1451 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
1452 EXPECT_CALL(checkpoint, Call(2));
1453 }
1454
1455 CreateChannelAndConnectSuccessfully();
1456 checkpoint.Call(1);
fdoray92e35a72016-06-10 15:54:551457 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541458 checkpoint.Call(2);
1459}
1460
1461// Extra data can arrive while a read is being processed, resulting in the next
1462// read completing synchronously.
1463TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
danakj9c5cab52016-04-16 00:54:331464 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541465 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281466 static const InitFrame frames1[] = {
1467 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1468 static const InitFrame frames2[] = {
1469 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "WORLD"}};
1470 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1471 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames2);
dchengc7eeda422015-12-26 03:56:481472 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541473 {
1474 InSequence s;
tyoshinoc06da562015-03-06 06:02:421475 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541476 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1477 EXPECT_CALL(
1478 *event_interface_,
1479 OnDataFrame(
1480 true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
1481 EXPECT_CALL(
1482 *event_interface_,
1483 OnDataFrame(
1484 true, WebSocketFrameHeader::kOpCodeText, AsVector("WORLD")));
1485 }
1486
1487 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551488 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541489}
1490
[email protected]2f5d9f62013-09-26 12:14:281491// Data frames are delivered the same regardless of how many reads they arrive
1492// as.
1493TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) {
danakj9c5cab52016-04-16 00:54:331494 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541495 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281496 // Here we have one message which arrived in five frames split across three
1497 // reads. It may have been reframed on arrival, but this class doesn't care
1498 // about that.
1499 static const InitFrame frames1[] = {
1500 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "THREE"},
1501 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1502 NOT_MASKED, " "}};
1503 static const InitFrame frames2[] = {
1504 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1505 NOT_MASKED, "SMALL"}};
1506 static const InitFrame frames3[] = {
1507 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1508 NOT_MASKED, " "},
1509 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1510 NOT_MASKED, "FRAMES"}};
1511 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1512 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1513 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
dchengc7eeda422015-12-26 03:56:481514 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541515 {
1516 InSequence s;
tyoshinoc06da562015-03-06 06:02:421517 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541518 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1519 EXPECT_CALL(
1520 *event_interface_,
1521 OnDataFrame(
1522 false, WebSocketFrameHeader::kOpCodeText, AsVector("THREE")));
1523 EXPECT_CALL(
1524 *event_interface_,
1525 OnDataFrame(
1526 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" ")));
1527 EXPECT_CALL(*event_interface_,
1528 OnDataFrame(false,
1529 WebSocketFrameHeader::kOpCodeContinuation,
1530 AsVector("SMALL")));
1531 EXPECT_CALL(
1532 *event_interface_,
1533 OnDataFrame(
1534 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" ")));
1535 EXPECT_CALL(*event_interface_,
1536 OnDataFrame(true,
1537 WebSocketFrameHeader::kOpCodeContinuation,
1538 AsVector("FRAMES")));
1539 }
1540
1541 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551542 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541543}
1544
danakj9c5cab52016-04-16 00:54:331545// A message can consist of one frame with null payload.
[email protected]00f4daf2013-11-12 13:56:411546TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) {
danakj9c5cab52016-04-16 00:54:331547 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]00f4daf2013-11-12 13:56:411548 new ReadableFakeWebSocketStream);
1549 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:331550 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411551 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481552 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421553 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]00f4daf2013-11-12 13:56:411554 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1555 EXPECT_CALL(
1556 *event_interface_,
1557 OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
1558 CreateChannelAndConnectSuccessfully();
1559}
1560
[email protected]999bcaa2013-07-17 13:42:541561// Connection closed by the remote host without a closing handshake.
1562TEST_F(WebSocketChannelEventInterfaceTest, AsyncAbnormalClosure) {
danakj9c5cab52016-04-16 00:54:331563 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541564 new ReadableFakeWebSocketStream);
1565 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1566 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481567 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541568 {
1569 InSequence s;
tyoshinoc06da562015-03-06 06:02:421570 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541571 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1572 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161573 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541574 }
1575
1576 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551577 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541578}
1579
1580// A connection reset should produce the same event as an unexpected closure.
1581TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) {
danakj9c5cab52016-04-16 00:54:331582 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541583 new ReadableFakeWebSocketStream);
1584 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1585 ERR_CONNECTION_RESET);
dchengc7eeda422015-12-26 03:56:481586 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541587 {
1588 InSequence s;
tyoshinoc06da562015-03-06 06:02:421589 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541590 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1591 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161592 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541593 }
1594
1595 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551596 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541597}
1598
[email protected]999bcaa2013-07-17 13:42:541599// RFC6455 5.1 "A client MUST close a connection if it detects a masked frame."
1600TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
danakj9c5cab52016-04-16 00:54:331601 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541602 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281603 static const InitFrame frames[] = {
1604 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
[email protected]999bcaa2013-07-17 13:42:541605
[email protected]2f5d9f62013-09-26 12:14:281606 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481607 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541608 {
1609 InSequence s;
tyoshinoc06da562015-03-06 06:02:421610 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541611 EXPECT_CALL(*event_interface_, OnFlowControl(_));
[email protected]ea56b982014-01-27 03:21:031612 EXPECT_CALL(
1613 *event_interface_,
1614 OnFailChannel(
1615 "A server must not mask any frames that it sends to the client."));
[email protected]999bcaa2013-07-17 13:42:541616 }
1617
1618 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551619 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541620}
1621
1622// RFC6455 5.2 "If an unknown opcode is received, the receiving endpoint MUST
1623// _Fail the WebSocket Connection_."
1624TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) {
danakj9c5cab52016-04-16 00:54:331625 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541626 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281627 static const InitFrame frames[] = {{FINAL_FRAME, 4, NOT_MASKED, "HELLO"}};
[email protected]999bcaa2013-07-17 13:42:541628
[email protected]2f5d9f62013-09-26 12:14:281629 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481630 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541631 {
1632 InSequence s;
tyoshinoc06da562015-03-06 06:02:421633 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541634 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1635 EXPECT_CALL(*event_interface_,
[email protected]ea56b982014-01-27 03:21:031636 OnFailChannel("Unrecognized frame opcode: 4"));
[email protected]999bcaa2013-07-17 13:42:541637 }
1638
1639 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551640 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541641}
1642
1643// RFC6455 5.4 "Control frames ... MAY be injected in the middle of a
1644// fragmented message."
1645TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
danakj9c5cab52016-04-16 00:54:331646 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]999bcaa2013-07-17 13:42:541647 new ReadableFakeWebSocketStream);
1648 // We have one message of type Text split into two frames. In the middle is a
1649 // control message of type Pong.
[email protected]2f5d9f62013-09-26 12:14:281650 static const InitFrame frames1[] = {
1651 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1652 NOT_MASKED, "SPLIT "}};
1653 static const InitFrame frames2[] = {
1654 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
1655 static const InitFrame frames3[] = {
1656 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1657 NOT_MASKED, "MESSAGE"}};
1658 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1659 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1660 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
dchengc7eeda422015-12-26 03:56:481661 set_stream(std::move(stream));
[email protected]999bcaa2013-07-17 13:42:541662 {
1663 InSequence s;
tyoshinoc06da562015-03-06 06:02:421664 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541665 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1666 EXPECT_CALL(
1667 *event_interface_,
1668 OnDataFrame(
1669 false, WebSocketFrameHeader::kOpCodeText, AsVector("SPLIT ")));
1670 EXPECT_CALL(*event_interface_,
1671 OnDataFrame(true,
1672 WebSocketFrameHeader::kOpCodeContinuation,
1673 AsVector("MESSAGE")));
1674 }
1675
1676 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551677 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541678}
1679
[email protected]00f4daf2013-11-12 13:56:411680// It seems redundant to repeat the entirety of the above test, so just test a
danakj9c5cab52016-04-16 00:54:331681// Pong with null data.
[email protected]00f4daf2013-11-12 13:56:411682TEST_F(WebSocketChannelEventInterfaceTest, PongWithNullData) {
danakj9c5cab52016-04-16 00:54:331683 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]00f4daf2013-11-12 13:56:411684 new ReadableFakeWebSocketStream);
1685 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:331686 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411687 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481688 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421689 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]00f4daf2013-11-12 13:56:411690 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1691
1692 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551693 base::RunLoop().RunUntilIdle();
[email protected]00f4daf2013-11-12 13:56:411694}
1695
[email protected]2f5d9f62013-09-26 12:14:281696// If a frame has an invalid header, then the connection is closed and
1697// subsequent frames must not trigger events.
1698TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) {
danakj9c5cab52016-04-16 00:54:331699 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]c0d29c22013-07-26 20:40:411700 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281701 static const InitFrame frames[] = {
1702 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"},
1703 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, " WORLD"}};
[email protected]c0d29c22013-07-26 20:40:411704
[email protected]2f5d9f62013-09-26 12:14:281705 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:481706 set_stream(std::move(stream));
[email protected]c0d29c22013-07-26 20:40:411707 {
1708 InSequence s;
tyoshinoc06da562015-03-06 06:02:421709 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]c0d29c22013-07-26 20:40:411710 EXPECT_CALL(*event_interface_, OnFlowControl(_));
[email protected]ea56b982014-01-27 03:21:031711 EXPECT_CALL(
1712 *event_interface_,
1713 OnFailChannel(
1714 "A server must not mask any frames that it sends to the client."));
[email protected]c0d29c22013-07-26 20:40:411715 }
1716
1717 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551718 base::RunLoop().RunUntilIdle();
[email protected]c0d29c22013-07-26 20:40:411719}
1720
[email protected]999bcaa2013-07-17 13:42:541721// If the renderer sends lots of small writes, we don't want to update the quota
1722// for each one.
1723TEST_F(WebSocketChannelEventInterfaceTest, SmallWriteDoesntUpdateQuota) {
danakj9c5cab52016-04-16 00:54:331724 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
[email protected]999bcaa2013-07-17 13:42:541725 {
1726 InSequence s;
tyoshinoc06da562015-03-06 06:02:421727 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541728 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1729 }
1730
1731 CreateChannelAndConnectSuccessfully();
1732 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("B"));
1733}
1734
ricea10bf0e12015-12-14 11:18:291735// If we send enough to go below |send_quota_low_water_mark_| we should get our
[email protected]999bcaa2013-07-17 13:42:541736// quota refreshed.
1737TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) {
danakj9c5cab52016-04-16 00:54:331738 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
[email protected]999bcaa2013-07-17 13:42:541739 // We use this checkpoint object to verify that the quota update comes after
1740 // the write.
[email protected]f485985e2013-10-24 13:47:441741 Checkpoint checkpoint;
[email protected]999bcaa2013-07-17 13:42:541742 {
1743 InSequence s;
tyoshinoc06da562015-03-06 06:02:421744 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541745 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1746 EXPECT_CALL(checkpoint, Call(1));
1747 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1748 EXPECT_CALL(checkpoint, Call(2));
1749 }
1750
1751 CreateChannelAndConnectSuccessfully();
1752 checkpoint.Call(1);
[email protected]c0d29c22013-07-26 20:40:411753 channel_->SendFrame(true,
1754 WebSocketFrameHeader::kOpCodeText,
1755 std::vector<char>(kDefaultInitialQuota, 'B'));
[email protected]999bcaa2013-07-17 13:42:541756 checkpoint.Call(2);
1757}
1758
1759// Verify that our quota actually is refreshed when we are told it is.
1760TEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) {
danakj9c5cab52016-04-16 00:54:331761 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
[email protected]f485985e2013-10-24 13:47:441762 Checkpoint checkpoint;
[email protected]999bcaa2013-07-17 13:42:541763 {
1764 InSequence s;
tyoshinoc06da562015-03-06 06:02:421765 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541766 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1767 EXPECT_CALL(checkpoint, Call(1));
1768 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1769 EXPECT_CALL(checkpoint, Call(2));
1770 // If quota was not really refreshed, we would get an OnDropChannel()
1771 // message.
1772 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1773 EXPECT_CALL(checkpoint, Call(3));
1774 }
1775
1776 CreateChannelAndConnectSuccessfully();
1777 checkpoint.Call(1);
[email protected]999bcaa2013-07-17 13:42:541778 channel_->SendFrame(true,
1779 WebSocketFrameHeader::kOpCodeText,
[email protected]c0d29c22013-07-26 20:40:411780 std::vector<char>(kDefaultQuotaRefreshTrigger, 'D'));
[email protected]999bcaa2013-07-17 13:42:541781 checkpoint.Call(2);
1782 // We should have received more quota at this point.
1783 channel_->SendFrame(true,
1784 WebSocketFrameHeader::kOpCodeText,
[email protected]c0d29c22013-07-26 20:40:411785 std::vector<char>(kDefaultQuotaRefreshTrigger, 'E'));
[email protected]999bcaa2013-07-17 13:42:541786 checkpoint.Call(3);
1787}
1788
1789// If we send more than the available quota then the connection will be closed
1790// with an error.
1791TEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) {
danakj9c5cab52016-04-16 00:54:331792 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
[email protected]999bcaa2013-07-17 13:42:541793 {
1794 InSequence s;
tyoshinoc06da562015-03-06 06:02:421795 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]c0d29c22013-07-26 20:40:411796 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
[email protected]ea56b982014-01-27 03:21:031797 EXPECT_CALL(*event_interface_, OnFailChannel("Send quota exceeded"));
[email protected]999bcaa2013-07-17 13:42:541798 }
1799
1800 CreateChannelAndConnectSuccessfully();
1801 channel_->SendFrame(true,
1802 WebSocketFrameHeader::kOpCodeText,
[email protected]c0d29c22013-07-26 20:40:411803 std::vector<char>(kDefaultInitialQuota + 1, 'C'));
[email protected]999bcaa2013-07-17 13:42:541804}
1805
1806// If a write fails, the channel is dropped.
1807TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) {
danakj9c5cab52016-04-16 00:54:331808 set_stream(base::WrapUnique(new UnWriteableFakeWebSocketStream));
[email protected]f485985e2013-10-24 13:47:441809 Checkpoint checkpoint;
[email protected]999bcaa2013-07-17 13:42:541810 {
1811 InSequence s;
tyoshinoc06da562015-03-06 06:02:421812 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541813 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1814 EXPECT_CALL(checkpoint, Call(1));
1815 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161816 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
[email protected]999bcaa2013-07-17 13:42:541817 EXPECT_CALL(checkpoint, Call(2));
1818 }
1819
1820 CreateChannelAndConnectSuccessfully();
1821 checkpoint.Call(1);
1822
1823 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("H"));
1824 checkpoint.Call(2);
1825}
1826
1827// OnDropChannel() is called exactly once when StartClosingHandshake() is used.
1828TEST_F(WebSocketChannelEventInterfaceTest, SendCloseDropsChannel) {
danakj9c5cab52016-04-16 00:54:331829 set_stream(base::WrapUnique(new EchoeyFakeWebSocketStream));
[email protected]999bcaa2013-07-17 13:42:541830 {
1831 InSequence s;
tyoshinoc06da562015-03-06 06:02:421832 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]999bcaa2013-07-17 13:42:541833 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1834 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161835 OnDropChannel(true, kWebSocketNormalClosure, "Fred"));
[email protected]999bcaa2013-07-17 13:42:541836 }
1837
1838 CreateChannelAndConnectSuccessfully();
1839
yhiranod2727df2016-04-11 05:32:491840 ASSERT_EQ(CHANNEL_ALIVE,
1841 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Fred"));
fdoray92e35a72016-06-10 15:54:551842 base::RunLoop().RunUntilIdle();
[email protected]999bcaa2013-07-17 13:42:541843}
1844
[email protected]6dfd8b32014-02-05 11:24:491845// StartClosingHandshake() also works before connection completes, and calls
1846// OnDropChannel.
1847TEST_F(WebSocketChannelEventInterfaceTest, CloseDuringConnection) {
1848 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161849 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""));
[email protected]6dfd8b32014-02-05 11:24:491850
1851 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:491852 ASSERT_EQ(CHANNEL_DELETED,
1853 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Joe"));
[email protected]6dfd8b32014-02-05 11:24:491854}
1855
[email protected]c0d29c22013-07-26 20:40:411856// OnDropChannel() is only called once when a write() on the socket triggers a
1857// connection reset.
1858TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
danakj9c5cab52016-04-16 00:54:331859 set_stream(base::WrapUnique(new ResetOnWriteFakeWebSocketStream));
tyoshinoc06da562015-03-06 06:02:421860 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]c0d29c22013-07-26 20:40:411861 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1862
1863 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161864 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""))
[email protected]c0d29c22013-07-26 20:40:411865 .Times(1);
1866
1867 CreateChannelAndConnectSuccessfully();
1868
1869 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("yt?"));
fdoray92e35a72016-06-10 15:54:551870 base::RunLoop().RunUntilIdle();
[email protected]c0d29c22013-07-26 20:40:411871}
1872
1873// When the remote server sends a Close frame with an empty payload,
1874// WebSocketChannel should report code 1005, kWebSocketErrorNoStatusReceived.
1875TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
danakj9c5cab52016-04-16 00:54:331876 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]c0d29c22013-07-26 20:40:411877 new ReadableFakeWebSocketStream);
[email protected]2f5d9f62013-09-26 12:14:281878 static const InitFrame frames[] = {
1879 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
1880 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
[email protected]c0d29c22013-07-26 20:40:411881 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1882 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481883 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421884 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]c0d29c22013-07-26 20:40:411885 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1886 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1887 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161888 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
[email protected]c0d29c22013-07-26 20:40:411889
1890 CreateChannelAndConnectSuccessfully();
1891}
1892
danakj9c5cab52016-04-16 00:54:331893// A version of the above test with null payload.
[email protected]00f4daf2013-11-12 13:56:411894TEST_F(WebSocketChannelEventInterfaceTest,
1895 CloseWithNullPayloadGivesStatus1005) {
danakj9c5cab52016-04-16 00:54:331896 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]00f4daf2013-11-12 13:56:411897 new ReadableFakeWebSocketStream);
1898 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:331899 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:411900 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1901 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1902 ERR_CONNECTION_CLOSED);
dchengc7eeda422015-12-26 03:56:481903 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421904 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]00f4daf2013-11-12 13:56:411905 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1906 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1907 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:161908 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
[email protected]00f4daf2013-11-12 13:56:411909
1910 CreateChannelAndConnectSuccessfully();
1911}
1912
[email protected]ea56b982014-01-27 03:21:031913// If ReadFrames() returns ERR_WS_PROTOCOL_ERROR, then the connection must be
1914// failed.
[email protected]2f5d9f62013-09-26 12:14:281915TEST_F(WebSocketChannelEventInterfaceTest, SyncProtocolErrorGivesStatus1002) {
danakj9c5cab52016-04-16 00:54:331916 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]2f5d9f62013-09-26 12:14:281917 new ReadableFakeWebSocketStream);
1918 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1919 ERR_WS_PROTOCOL_ERROR);
dchengc7eeda422015-12-26 03:56:481920 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421921 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]2f5d9f62013-09-26 12:14:281922 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1923
[email protected]ea56b982014-01-27 03:21:031924 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
[email protected]2f5d9f62013-09-26 12:14:281925
1926 CreateChannelAndConnectSuccessfully();
1927}
1928
1929// Async version of above test.
1930TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) {
danakj9c5cab52016-04-16 00:54:331931 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]2f5d9f62013-09-26 12:14:281932 new ReadableFakeWebSocketStream);
1933 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1934 ERR_WS_PROTOCOL_ERROR);
dchengc7eeda422015-12-26 03:56:481935 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:421936 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]2f5d9f62013-09-26 12:14:281937 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1938
[email protected]ea56b982014-01-27 03:21:031939 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header"));
[email protected]2f5d9f62013-09-26 12:14:281940
1941 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:551942 base::RunLoop().RunUntilIdle();
[email protected]2f5d9f62013-09-26 12:14:281943}
1944
[email protected]cd48ed12014-01-22 14:34:221945TEST_F(WebSocketChannelEventInterfaceTest, StartHandshakeRequest) {
1946 {
1947 InSequence s;
tyoshinoc06da562015-03-06 06:02:421948 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]cd48ed12014-01-22 14:34:221949 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1950 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
1951 }
1952
1953 CreateChannelAndConnectSuccessfully();
1954
danakj9c5cab52016-04-16 00:54:331955 std::unique_ptr<WebSocketHandshakeRequestInfo> request_info(
[email protected]cd48ed12014-01-22 14:34:221956 new WebSocketHandshakeRequestInfo(GURL("ws://www.example.com/"),
1957 base::Time()));
1958 connect_data_.creator.connect_delegate->OnStartOpeningHandshake(
dchengc7eeda422015-12-26 03:56:481959 std::move(request_info));
[email protected]cd48ed12014-01-22 14:34:221960
fdoray92e35a72016-06-10 15:54:551961 base::RunLoop().RunUntilIdle();
[email protected]cd48ed12014-01-22 14:34:221962}
1963
1964TEST_F(WebSocketChannelEventInterfaceTest, FinishHandshakeRequest) {
1965 {
1966 InSequence s;
tyoshinoc06da562015-03-06 06:02:421967 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]cd48ed12014-01-22 14:34:221968 EXPECT_CALL(*event_interface_, OnFlowControl(_));
1969 EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
1970 }
1971
1972 CreateChannelAndConnectSuccessfully();
1973
1974 scoped_refptr<HttpResponseHeaders> response_headers(
1975 new HttpResponseHeaders(""));
danakj9c5cab52016-04-16 00:54:331976 std::unique_ptr<WebSocketHandshakeResponseInfo> response_info(
1977 new WebSocketHandshakeResponseInfo(GURL("ws://www.example.com/"), 200,
1978 "OK", response_headers, base::Time()));
[email protected]cd48ed12014-01-22 14:34:221979 connect_data_.creator.connect_delegate->OnFinishOpeningHandshake(
dchengc7eeda422015-12-26 03:56:481980 std::move(response_info));
fdoray92e35a72016-06-10 15:54:551981 base::RunLoop().RunUntilIdle();
[email protected]cd48ed12014-01-22 14:34:221982}
1983
1984TEST_F(WebSocketChannelEventInterfaceTest, FailJustAfterHandshake) {
1985 {
1986 InSequence s;
1987 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
1988 EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled());
1989 EXPECT_CALL(*event_interface_, OnFailChannel("bye"));
1990 }
1991
1992 CreateChannelAndConnect();
1993
1994 WebSocketStream::ConnectDelegate* connect_delegate =
1995 connect_data_.creator.connect_delegate.get();
1996 GURL url("ws://www.example.com/");
danakj9c5cab52016-04-16 00:54:331997 std::unique_ptr<WebSocketHandshakeRequestInfo> request_info(
[email protected]cd48ed12014-01-22 14:34:221998 new WebSocketHandshakeRequestInfo(url, base::Time()));
1999 scoped_refptr<HttpResponseHeaders> response_headers(
2000 new HttpResponseHeaders(""));
danakj9c5cab52016-04-16 00:54:332001 std::unique_ptr<WebSocketHandshakeResponseInfo> response_info(
2002 new WebSocketHandshakeResponseInfo(url, 200, "OK", response_headers,
[email protected]cd48ed12014-01-22 14:34:222003 base::Time()));
dchengc7eeda422015-12-26 03:56:482004 connect_delegate->OnStartOpeningHandshake(std::move(request_info));
2005 connect_delegate->OnFinishOpeningHandshake(std::move(response_info));
[email protected]cd48ed12014-01-22 14:34:222006
2007 connect_delegate->OnFailure("bye");
fdoray92e35a72016-06-10 15:54:552008 base::RunLoop().RunUntilIdle();
[email protected]cd48ed12014-01-22 14:34:222009}
2010
[email protected]ea56b982014-01-27 03:21:032011// Any frame after close is invalid. This test uses a Text frame. See also
2012// test "PingAfterCloseIfRejected".
2013TEST_F(WebSocketChannelEventInterfaceTest, DataAfterCloseIsRejected) {
danakj9c5cab52016-04-16 00:54:332014 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]ea56b982014-01-27 03:21:032015 new ReadableFakeWebSocketStream);
2016 static const InitFrame frames[] = {
2017 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
2018 CLOSE_DATA(NORMAL_CLOSURE, "OK")},
2019 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "Payload"}};
2020 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482021 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422022 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]ea56b982014-01-27 03:21:032023 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2024
2025 {
2026 InSequence s;
2027 EXPECT_CALL(*event_interface_, OnClosingHandshake());
2028 EXPECT_CALL(*event_interface_,
2029 OnFailChannel("Data frame received after close"));
2030 }
2031
2032 CreateChannelAndConnectSuccessfully();
2033}
2034
2035// A Close frame with a one-byte payload elicits a specific console error
2036// message.
2037TEST_F(WebSocketChannelEventInterfaceTest, OneByteClosePayloadMessage) {
danakj9c5cab52016-04-16 00:54:332038 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]ea56b982014-01-27 03:21:032039 new ReadableFakeWebSocketStream);
2040 static const InitFrame frames[] = {
2041 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, "\x03"}};
2042 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482043 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422044 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]ea56b982014-01-27 03:21:032045 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2046 EXPECT_CALL(
2047 *event_interface_,
2048 OnFailChannel(
2049 "Received a broken close frame containing an invalid size body."));
2050
2051 CreateChannelAndConnectSuccessfully();
2052}
2053
2054// A Close frame with a reserved status code also elicits a specific console
2055// error message.
2056TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadReservedStatusMessage) {
danakj9c5cab52016-04-16 00:54:332057 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]ea56b982014-01-27 03:21:032058 new ReadableFakeWebSocketStream);
2059 static const InitFrame frames[] = {
2060 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2061 NOT_MASKED, CLOSE_DATA(ABNORMAL_CLOSURE, "Not valid on wire")}};
2062 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482063 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422064 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]ea56b982014-01-27 03:21:032065 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2066 EXPECT_CALL(
2067 *event_interface_,
2068 OnFailChannel(
2069 "Received a broken close frame containing a reserved status code."));
2070
2071 CreateChannelAndConnectSuccessfully();
2072}
2073
2074// A Close frame with invalid UTF-8 also elicits a specific console error
2075// message.
2076TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadInvalidReason) {
danakj9c5cab52016-04-16 00:54:332077 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]ea56b982014-01-27 03:21:032078 new ReadableFakeWebSocketStream);
2079 static const InitFrame frames[] = {
2080 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2081 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
2082 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482083 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422084 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]ea56b982014-01-27 03:21:032085 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2086 EXPECT_CALL(
2087 *event_interface_,
2088 OnFailChannel(
2089 "Received a broken close frame containing invalid UTF-8."));
2090
2091 CreateChannelAndConnectSuccessfully();
2092}
2093
[email protected]658d7672014-02-26 13:11:352094// The reserved bits must all be clear on received frames. Extensions should
2095// clear the bits when they are set correctly before passing on the frame.
2096TEST_F(WebSocketChannelEventInterfaceTest, ReservedBitsMustNotBeSet) {
danakj9c5cab52016-04-16 00:54:332097 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]658d7672014-02-26 13:11:352098 new ReadableFakeWebSocketStream);
2099 static const InitFrame frames[] = {
2100 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2101 NOT_MASKED, "sakana"}};
2102 // It is not worth adding support for reserved bits to InitFrame just for this
2103 // one test, so set the bit manually.
danakj9c5cab52016-04-16 00:54:332104 std::vector<std::unique_ptr<WebSocketFrame>> raw_frames =
yhirano592ff7f2015-12-07 08:45:192105 CreateFrameVector(frames);
[email protected]658d7672014-02-26 13:11:352106 raw_frames[0]->header.reserved1 = true;
yhirano592ff7f2015-12-07 08:45:192107 stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
2108 std::move(raw_frames));
dchengc7eeda422015-12-26 03:56:482109 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422110 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]658d7672014-02-26 13:11:352111 EXPECT_CALL(*event_interface_, OnFlowControl(_));
[email protected]c46c2612014-02-28 17:08:022112 EXPECT_CALL(*event_interface_,
2113 OnFailChannel(
2114 "One or more reserved bits are on: reserved1 = 1, "
2115 "reserved2 = 0, reserved3 = 0"));
[email protected]658d7672014-02-26 13:11:352116
2117 CreateChannelAndConnectSuccessfully();
2118}
2119
[email protected]3a266762013-10-23 08:15:102120// The closing handshake times out and sends an OnDropChannel event if no
2121// response to the client Close message is received.
2122TEST_F(WebSocketChannelEventInterfaceTest,
2123 ClientInitiatedClosingHandshakeTimesOut) {
danakj9c5cab52016-04-16 00:54:332124 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]3a266762013-10-23 08:15:102125 new ReadableFakeWebSocketStream);
2126 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
2127 ERR_IO_PENDING);
dchengc7eeda422015-12-26 03:56:482128 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422129 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]3a266762013-10-23 08:15:102130 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2131 // This checkpoint object verifies that the OnDropChannel message comes after
2132 // the timeout.
[email protected]f485985e2013-10-24 13:47:442133 Checkpoint checkpoint;
[email protected]3a266762013-10-23 08:15:102134 TestClosure completion;
2135 {
2136 InSequence s;
2137 EXPECT_CALL(checkpoint, Call(1));
2138 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:162139 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _))
[email protected]f485985e2013-10-24 13:47:442140 .WillOnce(InvokeClosureReturnDeleted(completion.closure()));
[email protected]3a266762013-10-23 08:15:102141 }
2142 CreateChannelAndConnectSuccessfully();
2143 // OneShotTimer is not very friendly to testing; there is no apparent way to
2144 // set an expectation on it. Instead the tests need to infer that the timeout
2145 // was fired by the behaviour of the WebSocketChannel object.
2146 channel_->SetClosingHandshakeTimeoutForTesting(
2147 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
tyoshinod4d1d302014-11-07 04:31:162148 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
2149 TimeDelta::FromMilliseconds(kVeryBigTimeoutMillis));
yhiranod2727df2016-04-11 05:32:492150 ASSERT_EQ(CHANNEL_ALIVE,
2151 channel_->StartClosingHandshake(kWebSocketNormalClosure, ""));
[email protected]3a266762013-10-23 08:15:102152 checkpoint.Call(1);
2153 completion.WaitForResult();
2154}
2155
2156// The closing handshake times out and sends an OnDropChannel event if a Close
2157// message is received but the connection isn't closed by the remote host.
2158TEST_F(WebSocketChannelEventInterfaceTest,
2159 ServerInitiatedClosingHandshakeTimesOut) {
danakj9c5cab52016-04-16 00:54:332160 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]3a266762013-10-23 08:15:102161 new ReadableFakeWebSocketStream);
2162 static const InitFrame frames[] = {
2163 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2164 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2165 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482166 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422167 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]3a266762013-10-23 08:15:102168 EXPECT_CALL(*event_interface_, OnFlowControl(_));
[email protected]f485985e2013-10-24 13:47:442169 Checkpoint checkpoint;
[email protected]3a266762013-10-23 08:15:102170 TestClosure completion;
2171 {
2172 InSequence s;
2173 EXPECT_CALL(checkpoint, Call(1));
2174 EXPECT_CALL(*event_interface_, OnClosingHandshake());
2175 EXPECT_CALL(*event_interface_,
[email protected]86ec55502014-02-10 13:16:162176 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _))
[email protected]f485985e2013-10-24 13:47:442177 .WillOnce(InvokeClosureReturnDeleted(completion.closure()));
[email protected]3a266762013-10-23 08:15:102178 }
2179 CreateChannelAndConnectSuccessfully();
2180 channel_->SetClosingHandshakeTimeoutForTesting(
tyoshinod4d1d302014-11-07 04:31:162181 TimeDelta::FromMilliseconds(kVeryBigTimeoutMillis));
2182 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
[email protected]3a266762013-10-23 08:15:102183 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
2184 checkpoint.Call(1);
2185 completion.WaitForResult();
2186}
2187
[email protected]4256dbb2014-03-24 15:39:362188// The renderer should provide us with some quota immediately, and then
2189// WebSocketChannel calls ReadFrames as soon as the stream is available.
2190TEST_F(WebSocketChannelStreamTest, FlowControlEarly) {
2191 Checkpoint checkpoint;
2192 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2193 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2194 {
2195 InSequence s;
2196 EXPECT_CALL(checkpoint, Call(1));
2197 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2198 .WillOnce(Return(ERR_IO_PENDING));
2199 EXPECT_CALL(checkpoint, Call(2));
2200 }
2201
dchengc7eeda422015-12-26 03:56:482202 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:362203 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:492204 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(kPlentyOfQuota));
[email protected]4256dbb2014-03-24 15:39:362205 checkpoint.Call(1);
dchengc7eeda422015-12-26 03:56:482206 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]4256dbb2014-03-24 15:39:362207 checkpoint.Call(2);
2208}
2209
2210// If for some reason the connect succeeds before the renderer sends us quota,
2211// we shouldn't call ReadFrames() immediately.
2212// TODO(ricea): Actually we should call ReadFrames() with a small limit so we
2213// can still handle control frames. This should be done once we have any API to
2214// expose quota to the lower levels.
2215TEST_F(WebSocketChannelStreamTest, FlowControlLate) {
2216 Checkpoint checkpoint;
2217 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2218 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2219 {
2220 InSequence s;
2221 EXPECT_CALL(checkpoint, Call(1));
2222 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2223 .WillOnce(Return(ERR_IO_PENDING));
2224 EXPECT_CALL(checkpoint, Call(2));
2225 }
2226
dchengc7eeda422015-12-26 03:56:482227 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:362228 CreateChannelAndConnect();
dchengc7eeda422015-12-26 03:56:482229 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]4256dbb2014-03-24 15:39:362230 checkpoint.Call(1);
yhiranod2727df2016-04-11 05:32:492231 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(kPlentyOfQuota));
[email protected]4256dbb2014-03-24 15:39:362232 checkpoint.Call(2);
2233}
2234
2235// We should stop calling ReadFrames() when all quota is used.
2236TEST_F(WebSocketChannelStreamTest, FlowControlStopsReadFrames) {
2237 static const InitFrame frames[] = {
2238 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2239
2240 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2241 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2242 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2243 .WillOnce(ReturnFrames(&frames));
2244
dchengc7eeda422015-12-26 03:56:482245 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:362246 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:492247 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(4));
dchengc7eeda422015-12-26 03:56:482248 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]4256dbb2014-03-24 15:39:362249}
2250
2251// Providing extra quota causes ReadFrames() to be called again.
2252TEST_F(WebSocketChannelStreamTest, FlowControlStartsWithMoreQuota) {
2253 static const InitFrame frames[] = {
2254 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2255 Checkpoint checkpoint;
2256
2257 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2258 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2259 {
2260 InSequence s;
2261 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2262 .WillOnce(ReturnFrames(&frames));
2263 EXPECT_CALL(checkpoint, Call(1));
2264 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2265 .WillOnce(Return(ERR_IO_PENDING));
2266 }
2267
dchengc7eeda422015-12-26 03:56:482268 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:362269 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:492270 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(4));
dchengc7eeda422015-12-26 03:56:482271 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]4256dbb2014-03-24 15:39:362272 checkpoint.Call(1);
yhiranod2727df2016-04-11 05:32:492273 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(4));
[email protected]4256dbb2014-03-24 15:39:362274}
2275
2276// ReadFrames() isn't called again until all pending data has been passed to
2277// the renderer.
2278TEST_F(WebSocketChannelStreamTest, ReadFramesNotCalledUntilQuotaAvailable) {
2279 static const InitFrame frames[] = {
2280 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2281 Checkpoint checkpoint;
2282
2283 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2284 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2285 {
2286 InSequence s;
2287 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2288 .WillOnce(ReturnFrames(&frames));
2289 EXPECT_CALL(checkpoint, Call(1));
2290 EXPECT_CALL(checkpoint, Call(2));
2291 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2292 .WillOnce(Return(ERR_IO_PENDING));
2293 }
2294
dchengc7eeda422015-12-26 03:56:482295 set_stream(std::move(mock_stream_));
[email protected]4256dbb2014-03-24 15:39:362296 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:492297 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(2));
dchengc7eeda422015-12-26 03:56:482298 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]4256dbb2014-03-24 15:39:362299 checkpoint.Call(1);
yhiranod2727df2016-04-11 05:32:492300 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(2));
[email protected]4256dbb2014-03-24 15:39:362301 checkpoint.Call(2);
yhiranod2727df2016-04-11 05:32:492302 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(2));
[email protected]4256dbb2014-03-24 15:39:362303}
2304
2305// A message that needs to be split into frames to fit within quota should
2306// maintain correct semantics.
2307TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitSync) {
danakj9c5cab52016-04-16 00:54:332308 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]4256dbb2014-03-24 15:39:362309 new ReadableFakeWebSocketStream);
2310 static const InitFrame frames[] = {
2311 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2312 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482313 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:362314 {
2315 InSequence s;
tyoshinoc06da562015-03-06 06:02:422316 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]4256dbb2014-03-24 15:39:362317 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2318 EXPECT_CALL(
2319 *event_interface_,
2320 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
2321 EXPECT_CALL(
2322 *event_interface_,
2323 OnDataFrame(
2324 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
2325 EXPECT_CALL(
2326 *event_interface_,
2327 OnDataFrame(
2328 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
2329 }
2330
2331 CreateChannelAndConnectWithQuota(2);
yhiranod2727df2016-04-11 05:32:492332 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(1));
2333 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(1));
[email protected]4256dbb2014-03-24 15:39:362334}
2335
2336// The code path for async messages is slightly different, so test it
2337// separately.
2338TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitAsync) {
danakj9c5cab52016-04-16 00:54:332339 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]4256dbb2014-03-24 15:39:362340 new ReadableFakeWebSocketStream);
2341 static const InitFrame frames[] = {
2342 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
2343 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482344 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:362345 Checkpoint checkpoint;
2346 {
2347 InSequence s;
tyoshinoc06da562015-03-06 06:02:422348 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]4256dbb2014-03-24 15:39:362349 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2350 EXPECT_CALL(checkpoint, Call(1));
2351 EXPECT_CALL(
2352 *event_interface_,
2353 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
2354 EXPECT_CALL(checkpoint, Call(2));
2355 EXPECT_CALL(
2356 *event_interface_,
2357 OnDataFrame(
2358 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
2359 EXPECT_CALL(checkpoint, Call(3));
2360 EXPECT_CALL(
2361 *event_interface_,
2362 OnDataFrame(
2363 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
2364 }
2365
2366 CreateChannelAndConnectWithQuota(2);
2367 checkpoint.Call(1);
fdoray92e35a72016-06-10 15:54:552368 base::RunLoop().RunUntilIdle();
[email protected]4256dbb2014-03-24 15:39:362369 checkpoint.Call(2);
yhiranod2727df2016-04-11 05:32:492370 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(1));
[email protected]4256dbb2014-03-24 15:39:362371 checkpoint.Call(3);
yhiranod2727df2016-04-11 05:32:492372 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(1));
[email protected]4256dbb2014-03-24 15:39:362373}
2374
2375// A message split into multiple frames which is further split due to quota
2376// restrictions should stil be correct.
2377// TODO(ricea): The message ends up split into more frames than are strictly
2378// necessary. The complexity/performance tradeoffs here need further
2379// examination.
2380TEST_F(WebSocketChannelFlowControlTest, MultipleFrameSplit) {
danakj9c5cab52016-04-16 00:54:332381 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]4256dbb2014-03-24 15:39:362382 new ReadableFakeWebSocketStream);
2383 static const InitFrame frames[] = {
2384 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2385 NOT_MASKED, "FIRST FRAME IS 25 BYTES. "},
2386 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2387 NOT_MASKED, "SECOND FRAME IS 26 BYTES. "},
2388 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2389 NOT_MASKED, "FINAL FRAME IS 24 BYTES."}};
2390 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482391 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:362392 {
2393 InSequence s;
tyoshinoc06da562015-03-06 06:02:422394 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]4256dbb2014-03-24 15:39:362395 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2396 EXPECT_CALL(*event_interface_,
2397 OnDataFrame(false,
2398 WebSocketFrameHeader::kOpCodeText,
2399 AsVector("FIRST FRAME IS")));
2400 EXPECT_CALL(*event_interface_,
2401 OnDataFrame(false,
2402 WebSocketFrameHeader::kOpCodeContinuation,
2403 AsVector(" 25 BYTES. ")));
2404 EXPECT_CALL(*event_interface_,
2405 OnDataFrame(false,
2406 WebSocketFrameHeader::kOpCodeContinuation,
2407 AsVector("SECOND FRAME IS 26 BYTES. ")));
2408 EXPECT_CALL(*event_interface_,
2409 OnDataFrame(false,
2410 WebSocketFrameHeader::kOpCodeContinuation,
2411 AsVector("FINAL ")));
2412 EXPECT_CALL(*event_interface_,
2413 OnDataFrame(true,
2414 WebSocketFrameHeader::kOpCodeContinuation,
2415 AsVector("FRAME IS 24 BYTES.")));
2416 }
2417 CreateChannelAndConnectWithQuota(14);
yhiranod2727df2016-04-11 05:32:492418 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(43));
2419 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(32));
[email protected]4256dbb2014-03-24 15:39:362420}
2421
2422// An empty message handled when we are out of quota must not be delivered
2423// out-of-order with respect to other messages.
2424TEST_F(WebSocketChannelFlowControlTest, EmptyMessageNoQuota) {
danakj9c5cab52016-04-16 00:54:332425 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]4256dbb2014-03-24 15:39:362426 new ReadableFakeWebSocketStream);
2427 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:332428 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2429 "FIRST MESSAGE"},
2430 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr},
2431 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2432 "THIRD MESSAGE"}};
[email protected]4256dbb2014-03-24 15:39:362433 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:482434 set_stream(std::move(stream));
[email protected]4256dbb2014-03-24 15:39:362435 {
2436 InSequence s;
tyoshinoc06da562015-03-06 06:02:422437 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]4256dbb2014-03-24 15:39:362438 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2439 EXPECT_CALL(*event_interface_,
2440 OnDataFrame(false,
2441 WebSocketFrameHeader::kOpCodeText,
2442 AsVector("FIRST ")));
2443 EXPECT_CALL(*event_interface_,
2444 OnDataFrame(true,
2445 WebSocketFrameHeader::kOpCodeContinuation,
2446 AsVector("MESSAGE")));
2447 EXPECT_CALL(*event_interface_,
2448 OnDataFrame(true,
2449 WebSocketFrameHeader::kOpCodeText,
2450 AsVector("")));
2451 EXPECT_CALL(*event_interface_,
2452 OnDataFrame(true,
2453 WebSocketFrameHeader::kOpCodeText,
2454 AsVector("THIRD MESSAGE")));
2455 }
2456
2457 CreateChannelAndConnectWithQuota(6);
yhiranod2727df2016-04-11 05:32:492458 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(128));
2459}
2460
2461// A close frame should not overtake data frames.
2462TEST_F(WebSocketChannelFlowControlTest, CloseFrameShouldNotOvertakeDataFrames) {
danakj9c5cab52016-04-16 00:54:332463 std::unique_ptr<ReadableFakeWebSocketStream> stream(
yhiranod2727df2016-04-11 05:32:492464 new ReadableFakeWebSocketStream);
2465 static const InitFrame frames[] = {
2466 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2467 "FIRST "},
2468 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED,
2469 "MESSAGE"},
2470 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
2471 "SECOND "},
2472 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
2473 CLOSE_DATA(NORMAL_CLOSURE, "GOOD BYE")},
2474 };
2475 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2476 set_stream(std::move(stream));
2477 Checkpoint checkpoint;
2478 InSequence s;
2479 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
2480 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2481 EXPECT_CALL(*event_interface_,
2482 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText,
2483 AsVector("FIRST ")));
2484 EXPECT_CALL(checkpoint, Call(1));
2485 EXPECT_CALL(*event_interface_,
2486 OnDataFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
2487 AsVector("MESSAG")));
2488 EXPECT_CALL(checkpoint, Call(2));
2489 EXPECT_CALL(*event_interface_,
2490 OnDataFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2491 AsVector("E")));
2492 EXPECT_CALL(
2493 *event_interface_,
2494 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("SECON")));
2495 EXPECT_CALL(checkpoint, Call(3));
2496 EXPECT_CALL(*event_interface_,
2497 OnDataFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
2498 AsVector("D ")));
2499 EXPECT_CALL(*event_interface_, OnClosingHandshake());
2500 EXPECT_CALL(checkpoint, Call(4));
2501
2502 CreateChannelAndConnectWithQuota(6);
2503 checkpoint.Call(1);
2504 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(6));
2505 checkpoint.Call(2);
2506 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(6));
2507 checkpoint.Call(3);
2508 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(6));
2509 checkpoint.Call(4);
[email protected]4256dbb2014-03-24 15:39:362510}
2511
[email protected]999bcaa2013-07-17 13:42:542512// RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
2513// WebSocketChannel actually only sets the mask bit in the header, it doesn't
2514// perform masking itself (not all transports actually use masking).
2515TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
[email protected]2f5d9f62013-09-26 12:14:282516 static const InitFrame expected[] = {
2517 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2518 MASKED, "NEEDS MASKING"}};
[email protected]999bcaa2013-07-17 13:42:542519 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212520 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]999bcaa2013-07-17 13:42:542521 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
[email protected]2f5d9f62013-09-26 12:14:282522 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412523 .WillOnce(Return(OK));
[email protected]999bcaa2013-07-17 13:42:542524
2525 CreateChannelAndConnectSuccessfully();
2526 channel_->SendFrame(
2527 true, WebSocketFrameHeader::kOpCodeText, AsVector("NEEDS MASKING"));
2528}
2529
[email protected]c0d29c22013-07-26 20:40:412530// RFC6455 5.5.1 "The application MUST NOT send any more data frames after
2531// sending a Close frame."
2532TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
[email protected]2f5d9f62013-09-26 12:14:282533 static const InitFrame expected[] = {
2534 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2535 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
[email protected]c0d29c22013-07-26 20:40:412536 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212537 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412538 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
[email protected]2f5d9f62013-09-26 12:14:282539 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412540 .WillOnce(Return(OK));
2541
2542 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:492543 ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(1000, "Success"));
[email protected]c0d29c22013-07-26 20:40:412544 channel_->SendFrame(
2545 true, WebSocketFrameHeader::kOpCodeText, AsVector("SHOULD BE IGNORED"));
2546}
2547
2548// RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
2549// send a Close frame, the endpoint MUST send a Close frame in response."
2550TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
[email protected]2f5d9f62013-09-26 12:14:282551 static const InitFrame frames[] = {
2552 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2553 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2554 static const InitFrame expected[] = {
2555 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2556 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
[email protected]c0d29c22013-07-26 20:40:412557 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212558 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412559 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
[email protected]2f5d9f62013-09-26 12:14:282560 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:412561 .WillRepeatedly(Return(ERR_IO_PENDING));
[email protected]2f5d9f62013-09-26 12:14:282562 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412563 .WillOnce(Return(OK));
2564
2565 CreateChannelAndConnectSuccessfully();
2566}
2567
2568// The converse of the above case; after sending a Close frame, we should not
2569// send another one.
2570TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
[email protected]2f5d9f62013-09-26 12:14:282571 static const InitFrame expected[] = {
2572 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2573 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
2574 static const InitFrame frames_init[] = {
2575 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2576 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
[email protected]c0d29c22013-07-26 20:40:412577
2578 // We store the parameters that were passed to ReadFrames() so that we can
2579 // call them explicitly later.
2580 CompletionCallback read_callback;
danakj9c5cab52016-04-16 00:54:332581 std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
[email protected]c0d29c22013-07-26 20:40:412582
[email protected]6c5d9f62014-01-27 15:05:212583 // These are not interesting.
2584 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2585 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2586
[email protected]c0d29c22013-07-26 20:40:412587 // Use a checkpoint to make the ordering of events clearer.
[email protected]f485985e2013-10-24 13:47:442588 Checkpoint checkpoint;
[email protected]c0d29c22013-07-26 20:40:412589 {
2590 InSequence s;
[email protected]c0d29c22013-07-26 20:40:412591 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
[email protected]2f5d9f62013-09-26 12:14:282592 .WillOnce(DoAll(SaveArg<0>(&frames),
[email protected]c0d29c22013-07-26 20:40:412593 SaveArg<1>(&read_callback),
2594 Return(ERR_IO_PENDING)));
2595 EXPECT_CALL(checkpoint, Call(1));
[email protected]2f5d9f62013-09-26 12:14:282596 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412597 .WillOnce(Return(OK));
2598 EXPECT_CALL(checkpoint, Call(2));
2599 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2600 .WillOnce(Return(ERR_IO_PENDING));
2601 EXPECT_CALL(checkpoint, Call(3));
2602 // WriteFrames() must not be called again. GoogleMock will ensure that the
2603 // test fails if it is.
2604 }
2605
2606 CreateChannelAndConnectSuccessfully();
2607 checkpoint.Call(1);
yhiranod2727df2016-04-11 05:32:492608 ASSERT_EQ(CHANNEL_ALIVE,
2609 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close"));
[email protected]c0d29c22013-07-26 20:40:412610 checkpoint.Call(2);
2611
[email protected]2f5d9f62013-09-26 12:14:282612 *frames = CreateFrameVector(frames_init);
[email protected]c0d29c22013-07-26 20:40:412613 read_callback.Run(OK);
2614 checkpoint.Call(3);
2615}
2616
[email protected]3de65092013-10-24 09:39:442617// Invalid close status codes should not be sent on the network.
2618TEST_F(WebSocketChannelStreamTest, InvalidCloseStatusCodeNotSent) {
2619 static const InitFrame expected[] = {
2620 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
[email protected]ea56b982014-01-27 03:21:032621 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
[email protected]3de65092013-10-24 09:39:442622
2623 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212624 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]3de65092013-10-24 09:39:442625 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2626 .WillOnce(Return(ERR_IO_PENDING));
2627
2628 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
2629
2630 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:492631 ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(999, ""));
[email protected]3de65092013-10-24 09:39:442632}
2633
2634// A Close frame with a reason longer than 123 bytes cannot be sent on the
2635// network.
2636TEST_F(WebSocketChannelStreamTest, LongCloseReasonNotSent) {
2637 static const InitFrame expected[] = {
2638 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
[email protected]ea56b982014-01-27 03:21:032639 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
[email protected]3de65092013-10-24 09:39:442640
2641 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212642 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]3de65092013-10-24 09:39:442643 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2644 .WillOnce(Return(ERR_IO_PENDING));
2645
2646 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
2647
2648 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:492649 ASSERT_EQ(CHANNEL_ALIVE,
2650 channel_->StartClosingHandshake(1000, std::string(124, 'A')));
[email protected]3de65092013-10-24 09:39:442651}
2652
[email protected]c0d29c22013-07-26 20:40:412653// We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no
2654// status in the Close message from the other side. Code 1005 is not allowed to
2655// appear on the wire, so we should not echo it back. See test
2656// CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is
2657// correctly generated internally.
2658TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
[email protected]2f5d9f62013-09-26 12:14:282659 static const InitFrame frames[] = {
2660 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
2661 static const InitFrame expected[] = {
2662 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
[email protected]c0d29c22013-07-26 20:40:412663 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212664 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412665 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
[email protected]2f5d9f62013-09-26 12:14:282666 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:412667 .WillRepeatedly(Return(ERR_IO_PENDING));
[email protected]2f5d9f62013-09-26 12:14:282668 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412669 .WillOnce(Return(OK));
2670
2671 CreateChannelAndConnectSuccessfully();
2672}
2673
[email protected]00f4daf2013-11-12 13:56:412674TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoedNull) {
2675 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:332676 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:412677 static const InitFrame expected[] = {
2678 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
2679 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212680 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]00f4daf2013-11-12 13:56:412681 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2682 .WillOnce(ReturnFrames(&frames))
2683 .WillRepeatedly(Return(ERR_IO_PENDING));
2684 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2685 .WillOnce(Return(OK));
2686
2687 CreateChannelAndConnectSuccessfully();
2688}
2689
[email protected]ea56b982014-01-27 03:21:032690// Receiving an invalid UTF-8 payload in a Close frame causes us to fail the
2691// connection.
2692TEST_F(WebSocketChannelStreamTest, CloseFrameInvalidUtf8) {
2693 static const InitFrame frames[] = {
2694 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2695 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
2696 static const InitFrame expected[] = {
2697 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2698 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in Close frame")}};
2699
2700 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212701 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]ea56b982014-01-27 03:21:032702 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2703 .WillOnce(ReturnFrames(&frames))
2704 .WillRepeatedly(Return(ERR_IO_PENDING));
2705 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2706 .WillOnce(Return(OK));
2707 EXPECT_CALL(*mock_stream_, Close());
2708
2709 CreateChannelAndConnectSuccessfully();
2710}
2711
[email protected]c0d29c22013-07-26 20:40:412712// RFC6455 5.5.2 "Upon receipt of a Ping frame, an endpoint MUST send a Pong
2713// frame in response"
2714// 5.5.3 "A Pong frame sent in response to a Ping frame must have identical
2715// "Application data" as found in the message body of the Ping frame being
2716// replied to."
2717TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) {
[email protected]2f5d9f62013-09-26 12:14:282718 static const InitFrame frames[] = {
2719 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2720 NOT_MASKED, "Application data"}};
2721 static const InitFrame expected[] = {
2722 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2723 MASKED, "Application data"}};
[email protected]c0d29c22013-07-26 20:40:412724 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212725 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412726 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
[email protected]2f5d9f62013-09-26 12:14:282727 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:412728 .WillRepeatedly(Return(ERR_IO_PENDING));
[email protected]2f5d9f62013-09-26 12:14:282729 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412730 .WillOnce(Return(OK));
2731
2732 CreateChannelAndConnectSuccessfully();
2733}
2734
danakj9c5cab52016-04-16 00:54:332735// A ping with a null payload should be responded to with a Pong with a null
[email protected]00f4daf2013-11-12 13:56:412736// payload.
[email protected]403ee6e2014-01-27 10:10:442737TEST_F(WebSocketChannelStreamTest, NullPingRepliedWithNullPong) {
[email protected]00f4daf2013-11-12 13:56:412738 static const InitFrame frames[] = {
danakj9c5cab52016-04-16 00:54:332739 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:412740 static const InitFrame expected[] = {
danakj9c5cab52016-04-16 00:54:332741 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, nullptr}};
[email protected]00f4daf2013-11-12 13:56:412742 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212743 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]00f4daf2013-11-12 13:56:412744 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2745 .WillOnce(ReturnFrames(&frames))
2746 .WillRepeatedly(Return(ERR_IO_PENDING));
2747 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2748 .WillOnce(Return(OK));
2749
2750 CreateChannelAndConnectSuccessfully();
2751}
2752
[email protected]c0d29c22013-07-26 20:40:412753TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
[email protected]2f5d9f62013-09-26 12:14:282754 static const InitFrame frames[] = {
2755 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2756 NOT_MASKED, "Application data"}};
2757 static const InitFrame expected1[] = {
2758 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2759 static const InitFrame expected2[] = {
2760 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2761 MASKED, "Application data"}};
2762 static const InitFrame expected3[] = {
2763 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2764 MASKED, "World"}};
danakj9c5cab52016-04-16 00:54:332765 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames;
[email protected]c0d29c22013-07-26 20:40:412766 CompletionCallback read_callback;
2767 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212768 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412769 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
[email protected]2f5d9f62013-09-26 12:14:282770 .WillOnce(DoAll(SaveArg<0>(&read_frames),
[email protected]c0d29c22013-07-26 20:40:412771 SaveArg<1>(&read_callback),
2772 Return(ERR_IO_PENDING)))
2773 .WillRepeatedly(Return(ERR_IO_PENDING));
2774 {
2775 InSequence s;
2776
[email protected]2f5d9f62013-09-26 12:14:282777 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
[email protected]c0d29c22013-07-26 20:40:412778 .WillOnce(Return(OK));
[email protected]2f5d9f62013-09-26 12:14:282779 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
[email protected]c0d29c22013-07-26 20:40:412780 .WillOnce(Return(OK));
[email protected]2f5d9f62013-09-26 12:14:282781 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _))
[email protected]c0d29c22013-07-26 20:40:412782 .WillOnce(Return(OK));
2783 }
2784
2785 CreateChannelAndConnectSuccessfully();
2786 channel_->SendFrame(
2787 false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
[email protected]2f5d9f62013-09-26 12:14:282788 *read_frames = CreateFrameVector(frames);
[email protected]c0d29c22013-07-26 20:40:412789 read_callback.Run(OK);
2790 channel_->SendFrame(
2791 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("World"));
2792}
2793
2794// WriteFrames() may not be called until the previous write has completed.
2795// WebSocketChannel must buffer writes that happen in the meantime.
2796TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
[email protected]2f5d9f62013-09-26 12:14:282797 static const InitFrame expected1[] = {
2798 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2799 static const InitFrame expected2[] = {
2800 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}};
[email protected]c0d29c22013-07-26 20:40:412801 CompletionCallback write_callback;
[email protected]f485985e2013-10-24 13:47:442802 Checkpoint checkpoint;
[email protected]c0d29c22013-07-26 20:40:412803
2804 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212805 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412806 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2807 {
2808 InSequence s;
2809 EXPECT_CALL(checkpoint, Call(1));
[email protected]2f5d9f62013-09-26 12:14:282810 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
[email protected]c0d29c22013-07-26 20:40:412811 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
2812 EXPECT_CALL(checkpoint, Call(2));
[email protected]2f5d9f62013-09-26 12:14:282813 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
[email protected]c0d29c22013-07-26 20:40:412814 .WillOnce(Return(ERR_IO_PENDING));
2815 EXPECT_CALL(checkpoint, Call(3));
2816 }
2817
2818 CreateChannelAndConnectSuccessfully();
2819 checkpoint.Call(1);
2820 channel_->SendFrame(
2821 false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
2822 channel_->SendFrame(
2823 true, WebSocketFrameHeader::kOpCodeText, AsVector("World"));
2824 checkpoint.Call(2);
2825 write_callback.Run(OK);
2826 checkpoint.Call(3);
2827}
2828
2829// WebSocketChannel must buffer frames while it is waiting for a write to
2830// complete, and then send them in a single batch. The batching behaviour is
2831// important to get good throughput in the "many small messages" case.
2832TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
2833 static const char input_letters[] = "Hello";
[email protected]2f5d9f62013-09-26 12:14:282834 static const InitFrame expected1[] = {
2835 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "H"}};
2836 static const InitFrame expected2[] = {
2837 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "e"},
2838 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2839 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2840 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
[email protected]c0d29c22013-07-26 20:40:412841 CompletionCallback write_callback;
2842
2843 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212844 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412845 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2846 {
2847 InSequence s;
[email protected]2f5d9f62013-09-26 12:14:282848 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
[email protected]c0d29c22013-07-26 20:40:412849 .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
[email protected]2f5d9f62013-09-26 12:14:282850 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
[email protected]c0d29c22013-07-26 20:40:412851 .WillOnce(Return(ERR_IO_PENDING));
2852 }
2853
2854 CreateChannelAndConnectSuccessfully();
2855 for (size_t i = 0; i < strlen(input_letters); ++i) {
2856 channel_->SendFrame(true,
2857 WebSocketFrameHeader::kOpCodeText,
2858 std::vector<char>(1, input_letters[i]));
2859 }
2860 write_callback.Run(OK);
2861}
2862
[email protected]4256dbb2014-03-24 15:39:362863// When the renderer sends more on a channel than it has quota for, we send the
2864// remote server a kWebSocketErrorGoingAway error code.
2865TEST_F(WebSocketChannelStreamTest, SendGoingAwayOnRendererQuotaExceeded) {
[email protected]2f5d9f62013-09-26 12:14:282866 static const InitFrame expected[] = {
2867 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
[email protected]ea56b982014-01-27 03:21:032868 MASKED, CLOSE_DATA(GOING_AWAY, "")}};
[email protected]c0d29c22013-07-26 20:40:412869 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212870 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412871 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
[email protected]2f5d9f62013-09-26 12:14:282872 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:412873 .WillOnce(Return(OK));
2874 EXPECT_CALL(*mock_stream_, Close());
2875
2876 CreateChannelAndConnectSuccessfully();
2877 channel_->SendFrame(true,
2878 WebSocketFrameHeader::kOpCodeText,
2879 std::vector<char>(kDefaultInitialQuota + 1, 'C'));
2880}
2881
2882// For convenience, most of these tests use Text frames. However, the WebSocket
2883// protocol also has Binary frames and those need to be 8-bit clean. For the
2884// sake of completeness, this test verifies that they are.
2885TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
danakj9c5cab52016-04-16 00:54:332886 std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
[email protected]c0d29c22013-07-26 20:40:412887
2888 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:212889 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:412890 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2891 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
[email protected]2f5d9f62013-09-26 12:14:282892 .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
[email protected]c0d29c22013-07-26 20:40:412893
2894 CreateChannelAndConnectSuccessfully();
2895 channel_->SendFrame(
2896 true,
2897 WebSocketFrameHeader::kOpCodeBinary,
2898 std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize));
danakj9c5cab52016-04-16 00:54:332899 ASSERT_TRUE(frames != nullptr);
[email protected]2f5d9f62013-09-26 12:14:282900 ASSERT_EQ(1U, frames->size());
yhirano592ff7f2015-12-07 08:45:192901 const WebSocketFrame* out_frame = (*frames)[0].get();
[email protected]2f5d9f62013-09-26 12:14:282902 EXPECT_EQ(kBinaryBlobSize, out_frame->header.payload_length);
dchengb206dc412014-08-26 19:46:232903 ASSERT_TRUE(out_frame->data.get());
[email protected]2f5d9f62013-09-26 12:14:282904 EXPECT_EQ(0, memcmp(kBinaryBlob, out_frame->data->data(), kBinaryBlobSize));
[email protected]c0d29c22013-07-26 20:40:412905}
2906
2907// Test the read path for 8-bit cleanliness as well.
2908TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
danakj9c5cab52016-04-16 00:54:332909 std::unique_ptr<WebSocketFrame> frame(
[email protected]2f5d9f62013-09-26 12:14:282910 new WebSocketFrame(WebSocketFrameHeader::kOpCodeBinary));
2911 WebSocketFrameHeader& frame_header = frame->header;
2912 frame_header.final = true;
2913 frame_header.payload_length = kBinaryBlobSize;
2914 frame->data = new IOBuffer(kBinaryBlobSize);
2915 memcpy(frame->data->data(), kBinaryBlob, kBinaryBlobSize);
danakj9c5cab52016-04-16 00:54:332916 std::vector<std::unique_ptr<WebSocketFrame>> frames;
dchengc7eeda422015-12-26 03:56:482917 frames.push_back(std::move(frame));
danakj9c5cab52016-04-16 00:54:332918 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]c0d29c22013-07-26 20:40:412919 new ReadableFakeWebSocketStream);
yhirano592ff7f2015-12-07 08:45:192920 stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
2921 std::move(frames));
dchengc7eeda422015-12-26 03:56:482922 set_stream(std::move(stream));
tyoshinoc06da562015-03-06 06:02:422923 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]c0d29c22013-07-26 20:40:412924 EXPECT_CALL(*event_interface_, OnFlowControl(_));
2925 EXPECT_CALL(*event_interface_,
2926 OnDataFrame(true,
2927 WebSocketFrameHeader::kOpCodeBinary,
2928 std::vector<char>(kBinaryBlob,
2929 kBinaryBlob + kBinaryBlobSize)));
2930
2931 CreateChannelAndConnectSuccessfully();
2932}
2933
[email protected]48cc6922014-02-10 14:20:482934// Invalid UTF-8 is not permitted in Text frames.
2935TEST_F(WebSocketChannelSendUtf8Test, InvalidUtf8Rejected) {
2936 EXPECT_CALL(
2937 *event_interface_,
2938 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2939
2940 CreateChannelAndConnectSuccessfully();
2941
2942 channel_->SendFrame(
2943 true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff"));
2944}
2945
2946// A Text message cannot end with a partial UTF-8 character.
2947TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInFinalFrame) {
2948 EXPECT_CALL(
2949 *event_interface_,
2950 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2951
2952 CreateChannelAndConnectSuccessfully();
2953
2954 channel_->SendFrame(
2955 true, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2"));
2956}
2957
2958// A non-final Text frame may end with a partial UTF-8 character (compare to
2959// previous test).
2960TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInNonFinalFrame) {
2961 CreateChannelAndConnectSuccessfully();
2962
2963 channel_->SendFrame(
2964 false, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2"));
2965}
2966
2967// UTF-8 parsing context must be retained between frames.
2968TEST_F(WebSocketChannelSendUtf8Test, ValidCharacterSplitBetweenFrames) {
2969 CreateChannelAndConnectSuccessfully();
2970
2971 channel_->SendFrame(
2972 false, WebSocketFrameHeader::kOpCodeText, AsVector("\xf1"));
2973 channel_->SendFrame(true,
2974 WebSocketFrameHeader::kOpCodeContinuation,
2975 AsVector("\x80\xa0\xbf"));
2976}
2977
2978// Similarly, an invalid character should be detected even if split.
2979TEST_F(WebSocketChannelSendUtf8Test, InvalidCharacterSplit) {
2980 EXPECT_CALL(
2981 *event_interface_,
2982 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2983
2984 CreateChannelAndConnectSuccessfully();
2985
2986 channel_->SendFrame(
2987 false, WebSocketFrameHeader::kOpCodeText, AsVector("\xe1"));
2988 channel_->SendFrame(true,
2989 WebSocketFrameHeader::kOpCodeContinuation,
2990 AsVector("\x80\xa0\xbf"));
2991}
2992
2993// An invalid character must be detected in continuation frames.
2994TEST_F(WebSocketChannelSendUtf8Test, InvalidByteInContinuation) {
2995 EXPECT_CALL(
2996 *event_interface_,
2997 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2998
2999 CreateChannelAndConnectSuccessfully();
3000
3001 channel_->SendFrame(
3002 false, WebSocketFrameHeader::kOpCodeText, AsVector("foo"));
3003 channel_->SendFrame(
3004 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar"));
3005 channel_->SendFrame(
3006 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff"));
3007}
3008
3009// However, continuation frames of a Binary frame will not be tested for UTF-8
3010// validity.
3011TEST_F(WebSocketChannelSendUtf8Test, BinaryContinuationNotChecked) {
3012 CreateChannelAndConnectSuccessfully();
3013
3014 channel_->SendFrame(
3015 false, WebSocketFrameHeader::kOpCodeBinary, AsVector("foo"));
3016 channel_->SendFrame(
3017 false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar"));
3018 channel_->SendFrame(
3019 true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff"));
3020}
3021
3022// Multiple text messages can be validated without the validation state getting
3023// confused.
3024TEST_F(WebSocketChannelSendUtf8Test, ValidateMultipleTextMessages) {
3025 CreateChannelAndConnectSuccessfully();
3026
3027 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("foo"));
3028 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("bar"));
3029}
3030
3031// UTF-8 validation is enforced on received Text frames.
3032TEST_F(WebSocketChannelEventInterfaceTest, ReceivedInvalidUtf8) {
danakj9c5cab52016-04-16 00:54:333033 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]48cc6922014-02-10 14:20:483034 new ReadableFakeWebSocketStream);
3035 static const InitFrame frames[] = {
3036 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
3037 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:483038 set_stream(std::move(stream));
[email protected]48cc6922014-02-10 14:20:483039
tyoshinoc06da562015-03-06 06:02:423040 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]48cc6922014-02-10 14:20:483041 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3042 EXPECT_CALL(*event_interface_,
3043 OnFailChannel("Could not decode a text frame as UTF-8."));
3044
3045 CreateChannelAndConnectSuccessfully();
fdoray92e35a72016-06-10 15:54:553046 base::RunLoop().RunUntilIdle();
[email protected]48cc6922014-02-10 14:20:483047}
3048
3049// Invalid UTF-8 is not sent over the network.
3050TEST_F(WebSocketChannelStreamTest, InvalidUtf8TextFrameNotSent) {
3051 static const InitFrame expected[] = {{FINAL_FRAME,
3052 WebSocketFrameHeader::kOpCodeClose,
3053 MASKED, CLOSE_DATA(GOING_AWAY, "")}};
3054 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
3055 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
3056 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3057 .WillRepeatedly(Return(ERR_IO_PENDING));
3058 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3059 .WillOnce(Return(OK));
3060 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3061
3062 CreateChannelAndConnectSuccessfully();
3063
3064 channel_->SendFrame(
3065 true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff"));
3066}
3067
3068// The rest of the tests for receiving invalid UTF-8 test the communication with
3069// the server. Since there is only one code path, it would be redundant to
3070// perform the same tests on the EventInterface as well.
3071
3072// If invalid UTF-8 is received in a Text frame, the connection is failed.
3073TEST_F(WebSocketChannelReceiveUtf8Test, InvalidTextFrameRejected) {
3074 static const InitFrame frames[] = {
3075 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
3076 static const InitFrame expected[] = {
3077 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3078 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3079 {
3080 InSequence s;
3081 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3082 .WillOnce(ReturnFrames(&frames))
3083 .WillRepeatedly(Return(ERR_IO_PENDING));
3084 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3085 .WillOnce(Return(OK));
3086 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3087 }
3088
3089 CreateChannelAndConnectSuccessfully();
3090}
3091
3092// A received Text message is not permitted to end with a partial UTF-8
3093// character.
3094TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterReceived) {
3095 static const InitFrame frames[] = {
3096 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
3097 static const InitFrame expected[] = {
3098 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3099 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3100 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3101 .WillOnce(ReturnFrames(&frames))
3102 .WillRepeatedly(Return(ERR_IO_PENDING));
3103 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3104 .WillOnce(Return(OK));
3105 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3106
3107 CreateChannelAndConnectSuccessfully();
3108}
3109
3110// However, a non-final Text frame may end with a partial UTF-8 character.
3111TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterIncompleteMessage) {
3112 static const InitFrame frames[] = {
3113 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
3114 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3115 .WillOnce(ReturnFrames(&frames))
3116 .WillRepeatedly(Return(ERR_IO_PENDING));
3117
3118 CreateChannelAndConnectSuccessfully();
3119}
3120
3121// However, it will become an error if it is followed by an empty final frame.
3122TEST_F(WebSocketChannelReceiveUtf8Test, TricksyIncompleteCharacter) {
3123 static const InitFrame frames[] = {
3124 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"},
3125 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
3126 static const InitFrame expected[] = {
3127 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3128 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3129 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3130 .WillOnce(ReturnFrames(&frames))
3131 .WillRepeatedly(Return(ERR_IO_PENDING));
3132 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3133 .WillOnce(Return(OK));
3134 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3135
3136 CreateChannelAndConnectSuccessfully();
3137}
3138
3139// UTF-8 parsing context must be retained between received frames of the same
3140// message.
3141TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedParsingContextRetained) {
3142 static const InitFrame frames[] = {
3143 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xf1"},
3144 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3145 NOT_MASKED, "\x80\xa0\xbf"}};
3146 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3147 .WillOnce(ReturnFrames(&frames))
3148 .WillRepeatedly(Return(ERR_IO_PENDING));
3149
3150 CreateChannelAndConnectSuccessfully();
3151}
3152
3153// An invalid character must be detected even if split between frames.
3154TEST_F(WebSocketChannelReceiveUtf8Test, SplitInvalidCharacterReceived) {
3155 static const InitFrame frames[] = {
3156 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xe1"},
3157 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3158 NOT_MASKED, "\x80\xa0\xbf"}};
3159 static const InitFrame expected[] = {
3160 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3161 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3162 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3163 .WillOnce(ReturnFrames(&frames))
3164 .WillRepeatedly(Return(ERR_IO_PENDING));
3165 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3166 .WillOnce(Return(OK));
3167 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3168
3169 CreateChannelAndConnectSuccessfully();
3170}
3171
3172// An invalid character received in a continuation frame must be detected.
3173TEST_F(WebSocketChannelReceiveUtf8Test, InvalidReceivedIncontinuation) {
3174 static const InitFrame frames[] = {
3175 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
3176 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3177 NOT_MASKED, "bar"},
3178 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3179 NOT_MASKED, "\xff"}};
3180 static const InitFrame expected[] = {
3181 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
3182 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
3183 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3184 .WillOnce(ReturnFrames(&frames))
3185 .WillRepeatedly(Return(ERR_IO_PENDING));
3186 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3187 .WillOnce(Return(OK));
3188 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3189
3190 CreateChannelAndConnectSuccessfully();
3191}
3192
3193// Continuations of binary frames must not be tested for UTF-8 validity.
3194TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedBinaryNotUtf8Tested) {
3195 static const InitFrame frames[] = {
3196 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary, NOT_MASKED, "foo"},
3197 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3198 NOT_MASKED, "bar"},
3199 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3200 NOT_MASKED, "\xff"}};
3201 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3202 .WillOnce(ReturnFrames(&frames))
3203 .WillRepeatedly(Return(ERR_IO_PENDING));
3204
3205 CreateChannelAndConnectSuccessfully();
3206}
3207
3208// Multiple Text messages can be validated.
3209TEST_F(WebSocketChannelReceiveUtf8Test, ValidateMultipleReceived) {
3210 static const InitFrame frames[] = {
3211 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
3212 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "bar"}};
3213 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3214 .WillOnce(ReturnFrames(&frames))
3215 .WillRepeatedly(Return(ERR_IO_PENDING));
3216
3217 CreateChannelAndConnectSuccessfully();
3218}
3219
[email protected]4e4bbaae7e2014-02-19 08:28:533220// A new data message cannot start in the middle of another data message.
3221TEST_F(WebSocketChannelEventInterfaceTest, BogusContinuation) {
danakj9c5cab52016-04-16 00:54:333222 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]4e4bbaae7e2014-02-19 08:28:533223 new ReadableFakeWebSocketStream);
3224 static const InitFrame frames[] = {
3225 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary,
3226 NOT_MASKED, "frame1"},
3227 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
3228 NOT_MASKED, "frame2"}};
3229 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:483230 set_stream(std::move(stream));
[email protected]4e4bbaae7e2014-02-19 08:28:533231
tyoshinoc06da562015-03-06 06:02:423232 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]4e4bbaae7e2014-02-19 08:28:533233 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3234 EXPECT_CALL(
3235 *event_interface_,
3236 OnDataFrame(
3237 false, WebSocketFrameHeader::kOpCodeBinary, AsVector("frame1")));
3238 EXPECT_CALL(
3239 *event_interface_,
3240 OnFailChannel(
3241 "Received start of new message but previous message is unfinished."));
3242
3243 CreateChannelAndConnectSuccessfully();
3244}
3245
3246// A new message cannot start with a Continuation frame.
3247TEST_F(WebSocketChannelEventInterfaceTest, MessageStartingWithContinuation) {
danakj9c5cab52016-04-16 00:54:333248 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]4e4bbaae7e2014-02-19 08:28:533249 new ReadableFakeWebSocketStream);
3250 static const InitFrame frames[] = {
3251 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3252 NOT_MASKED, "continuation"}};
3253 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:483254 set_stream(std::move(stream));
[email protected]4e4bbaae7e2014-02-19 08:28:533255
tyoshinoc06da562015-03-06 06:02:423256 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]4e4bbaae7e2014-02-19 08:28:533257 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3258 EXPECT_CALL(*event_interface_,
3259 OnFailChannel("Received unexpected continuation frame."));
3260
3261 CreateChannelAndConnectSuccessfully();
3262}
3263
[email protected]326b8fb2014-02-21 21:14:003264// A frame passed to the renderer must be either non-empty or have the final bit
3265// set.
3266TEST_F(WebSocketChannelEventInterfaceTest, DataFramesNonEmptyOrFinal) {
danakj9c5cab52016-04-16 00:54:333267 std::unique_ptr<ReadableFakeWebSocketStream> stream(
[email protected]326b8fb2014-02-21 21:14:003268 new ReadableFakeWebSocketStream);
3269 static const InitFrame frames[] = {
3270 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, ""},
3271 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
3272 NOT_MASKED, ""},
3273 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
3274 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
dchengc7eeda422015-12-26 03:56:483275 set_stream(std::move(stream));
[email protected]326b8fb2014-02-21 21:14:003276
tyoshinoc06da562015-03-06 06:02:423277 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
[email protected]326b8fb2014-02-21 21:14:003278 EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
3279 EXPECT_CALL(
3280 *event_interface_,
3281 OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
3282
3283 CreateChannelAndConnectSuccessfully();
3284}
3285
[email protected]a62449522014-06-05 11:11:153286// Calls to OnSSLCertificateError() must be passed through to the event
3287// interface with the correct URL attached.
3288TEST_F(WebSocketChannelEventInterfaceTest, OnSSLCertificateErrorCalled) {
3289 const GURL wss_url("wss://example.com/sslerror");
3290 connect_data_.socket_url = wss_url;
3291 const SSLInfo ssl_info;
3292 const bool fatal = true;
danakj9c5cab52016-04-16 00:54:333293 std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> fake_callbacks(
[email protected]a62449522014-06-05 11:11:153294 new FakeSSLErrorCallbacks);
3295
3296 EXPECT_CALL(*event_interface_,
3297 OnSSLCertificateErrorCalled(NotNull(), wss_url, _, fatal));
3298
3299 CreateChannelAndConnect();
3300 connect_data_.creator.connect_delegate->OnSSLCertificateError(
dchengc7eeda422015-12-26 03:56:483301 std::move(fake_callbacks), ssl_info, fatal);
[email protected]a62449522014-06-05 11:11:153302}
3303
[email protected]c0d29c22013-07-26 20:40:413304// If we receive another frame after Close, it is not valid. It is not
3305// completely clear what behaviour is required from the standard in this case,
3306// but the current implementation fails the connection. Since a Close has
3307// already been sent, this just means closing the connection.
3308TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
[email protected]2f5d9f62013-09-26 12:14:283309 static const InitFrame frames[] = {
3310 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3311 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
3312 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
3313 NOT_MASKED, "Ping body"}};
3314 static const InitFrame expected[] = {
3315 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3316 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
[email protected]c0d29c22013-07-26 20:40:413317 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213318 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]c0d29c22013-07-26 20:40:413319 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
[email protected]2f5d9f62013-09-26 12:14:283320 .WillOnce(ReturnFrames(&frames))
[email protected]c0d29c22013-07-26 20:40:413321 .WillRepeatedly(Return(ERR_IO_PENDING));
3322 {
3323 // We only need to verify the relative order of WriteFrames() and
3324 // Close(). The current implementation calls WriteFrames() for the Close
3325 // frame before calling ReadFrames() again, but that is an implementation
3326 // detail and better not to consider required behaviour.
3327 InSequence s;
[email protected]2f5d9f62013-09-26 12:14:283328 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
[email protected]c0d29c22013-07-26 20:40:413329 .WillOnce(Return(OK));
3330 EXPECT_CALL(*mock_stream_, Close()).Times(1);
3331 }
3332
3333 CreateChannelAndConnectSuccessfully();
3334}
3335
[email protected]2f5d9f62013-09-26 12:14:283336// A protocol error from the remote server should result in a close frame with
3337// status 1002, followed by the connection closing.
3338TEST_F(WebSocketChannelStreamTest, ProtocolError) {
3339 static const InitFrame expected[] = {
3340 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3341 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}};
3342 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213343 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]2f5d9f62013-09-26 12:14:283344 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3345 .WillOnce(Return(ERR_WS_PROTOCOL_ERROR));
3346 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3347 .WillOnce(Return(OK));
3348 EXPECT_CALL(*mock_stream_, Close());
3349
3350 CreateChannelAndConnectSuccessfully();
3351}
3352
[email protected]3a266762013-10-23 08:15:103353// Set the closing handshake timeout to a very tiny value before connecting.
3354class WebSocketChannelStreamTimeoutTest : public WebSocketChannelStreamTest {
3355 protected:
3356 WebSocketChannelStreamTimeoutTest() {}
3357
dchengb03027d2014-10-21 12:00:203358 void CreateChannelAndConnectSuccessfully() override {
dchengc7eeda422015-12-26 03:56:483359 set_stream(std::move(mock_stream_));
[email protected]3a266762013-10-23 08:15:103360 CreateChannelAndConnect();
yhiranod2727df2016-04-11 05:32:493361 ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(kPlentyOfQuota));
[email protected]3a266762013-10-23 08:15:103362 channel_->SetClosingHandshakeTimeoutForTesting(
3363 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
tyoshinod4d1d302014-11-07 04:31:163364 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
3365 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
dchengc7eeda422015-12-26 03:56:483366 connect_data_.creator.connect_delegate->OnSuccess(std::move(stream_));
[email protected]3a266762013-10-23 08:15:103367 }
3368};
3369
3370// In this case the server initiates the closing handshake with a Close
3371// message. WebSocketChannel responds with a matching Close message, and waits
3372// for the server to close the TCP/IP connection. The server never closes the
3373// connection, so the closing handshake times out and WebSocketChannel closes
3374// the connection itself.
3375TEST_F(WebSocketChannelStreamTimeoutTest, ServerInitiatedCloseTimesOut) {
3376 static const InitFrame frames[] = {
3377 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3378 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3379 static const InitFrame expected[] = {
3380 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3381 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3382 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213383 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]3a266762013-10-23 08:15:103384 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3385 .WillOnce(ReturnFrames(&frames))
3386 .WillRepeatedly(Return(ERR_IO_PENDING));
[email protected]f485985e2013-10-24 13:47:443387 Checkpoint checkpoint;
[email protected]3a266762013-10-23 08:15:103388 TestClosure completion;
3389 {
3390 InSequence s;
3391 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3392 .WillOnce(Return(OK));
3393 EXPECT_CALL(checkpoint, Call(1));
3394 EXPECT_CALL(*mock_stream_, Close())
3395 .WillOnce(InvokeClosure(completion.closure()));
3396 }
3397
3398 CreateChannelAndConnectSuccessfully();
3399 checkpoint.Call(1);
3400 completion.WaitForResult();
3401}
3402
3403// In this case the client initiates the closing handshake by sending a Close
3404// message. WebSocketChannel waits for a Close message in response from the
3405// server. The server never responds to the Close message, so the closing
3406// handshake times out and WebSocketChannel closes the connection.
3407TEST_F(WebSocketChannelStreamTimeoutTest, ClientInitiatedCloseTimesOut) {
3408 static const InitFrame expected[] = {
3409 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3410 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3411 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213412 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]3a266762013-10-23 08:15:103413 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3414 .WillRepeatedly(Return(ERR_IO_PENDING));
3415 TestClosure completion;
3416 {
3417 InSequence s;
3418 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3419 .WillOnce(Return(OK));
3420 EXPECT_CALL(*mock_stream_, Close())
3421 .WillOnce(InvokeClosure(completion.closure()));
3422 }
3423
3424 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:493425 ASSERT_EQ(CHANNEL_ALIVE,
3426 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"));
[email protected]3a266762013-10-23 08:15:103427 completion.WaitForResult();
3428}
3429
3430// In this case the client initiates the closing handshake and the server
3431// responds with a matching Close message. WebSocketChannel waits for the server
3432// to close the TCP/IP connection, but it never does. The closing handshake
3433// times out and WebSocketChannel closes the connection.
3434TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) {
3435 static const InitFrame expected[] = {
3436 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3437 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3438 static const InitFrame frames[] = {
3439 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
3440 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
3441 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
[email protected]6c5d9f62014-01-27 15:05:213442 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
[email protected]3a266762013-10-23 08:15:103443 TestClosure completion;
danakj9c5cab52016-04-16 00:54:333444 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames = nullptr;
[email protected]3a266762013-10-23 08:15:103445 CompletionCallback read_callback;
3446 {
3447 InSequence s;
3448 // Copy the arguments to ReadFrames so that the test can call the callback
3449 // after it has send the close message.
3450 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3451 .WillOnce(DoAll(SaveArg<0>(&read_frames),
3452 SaveArg<1>(&read_callback),
3453 Return(ERR_IO_PENDING)));
3454 // The first real event that happens is the client sending the Close
3455 // message.
3456 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
3457 .WillOnce(Return(OK));
3458 // The |read_frames| callback is called (from this test case) at this
3459 // point. ReadFrames is called again by WebSocketChannel, waiting for
3460 // ERR_CONNECTION_CLOSED.
3461 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
3462 .WillOnce(Return(ERR_IO_PENDING));
3463 // The timeout happens and so WebSocketChannel closes the stream.
3464 EXPECT_CALL(*mock_stream_, Close())
3465 .WillOnce(InvokeClosure(completion.closure()));
3466 }
3467
3468 CreateChannelAndConnectSuccessfully();
yhiranod2727df2016-04-11 05:32:493469 ASSERT_EQ(CHANNEL_ALIVE,
3470 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"));
[email protected]3a266762013-10-23 08:15:103471 ASSERT_TRUE(read_frames);
3472 // Provide the "Close" message from the server.
3473 *read_frames = CreateFrameVector(frames);
3474 read_callback.Run(OK);
3475 completion.WaitForResult();
3476}
3477
ricea5858a5052016-01-06 04:57:383478// Verify that current_send_quota() returns a non-zero value for a newly
3479// connected channel.
3480TEST_F(WebSocketChannelTest, CurrentSendQuotaNonZero) {
3481 CreateChannelAndConnectSuccessfully();
3482 EXPECT_GT(channel_->current_send_quota(), 0);
3483}
3484
3485// Verify that current_send_quota() is updated when SendFrame() is called.
3486TEST_F(WebSocketChannelTest, CurrentSendQuotaUpdated) {
3487 const int kMessageSize = 5;
danakj9c5cab52016-04-16 00:54:333488 set_stream(base::WrapUnique(new WriteableFakeWebSocketStream));
ricea5858a5052016-01-06 04:57:383489 CreateChannelAndConnectSuccessfully();
3490
3491 int initial_send_quota = channel_->current_send_quota();
3492 EXPECT_GE(initial_send_quota, kMessageSize);
3493
3494 channel_->SendFrame(
3495 true, WebSocketFrameHeader::kOpCodeText,
3496 std::vector<char>(static_cast<size_t>(kMessageSize), 'a'));
3497 int new_send_quota = channel_->current_send_quota();
3498 EXPECT_EQ(kMessageSize, initial_send_quota - new_send_quota);
3499}
3500
[email protected]999bcaa2013-07-17 13:42:543501} // namespace
3502} // namespace net