Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: net/websockets/websocket_stream_test.cc

Issue 565573002: Implement handshake timeout on WebSocket (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/websockets/websocket_stream.cc ('k') | net/websockets/websocket_test_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/websockets/websocket_stream.h" 5 #include "net/websockets/websocket_stream.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/memory/scoped_vector.h" 13 #include "base/memory/scoped_vector.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/metrics/histogram_samples.h" 15 #include "base/metrics/histogram_samples.h"
16 #include "base/metrics/statistics_recorder.h" 16 #include "base/metrics/statistics_recorder.h"
17 #include "base/run_loop.h" 17 #include "base/run_loop.h"
18 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
19 #include "base/timer/mock_timer.h"
20 #include "base/timer/timer.h"
19 #include "net/base/net_errors.h" 21 #include "net/base/net_errors.h"
20 #include "net/base/test_data_directory.h" 22 #include "net/base/test_data_directory.h"
21 #include "net/http/http_request_headers.h" 23 #include "net/http/http_request_headers.h"
22 #include "net/http/http_response_headers.h" 24 #include "net/http/http_response_headers.h"
23 #include "net/socket/client_socket_handle.h" 25 #include "net/socket/client_socket_handle.h"
24 #include "net/socket/socket_test_util.h" 26 #include "net/socket/socket_test_util.h"
25 #include "net/test/cert_test_util.h" 27 #include "net/test/cert_test_util.h"
26 #include "net/url_request/url_request_test_util.h" 28 #include "net/url_request/url_request_test_util.h"
27 #include "net/websockets/websocket_basic_handshake_stream.h" 29 #include "net/websockets/websocket_basic_handshake_stream.h"
28 #include "net/websockets/websocket_frame.h" 30 #include "net/websockets/websocket_frame.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 socket_data->SetStop(reads_count + writes_count); 74 socket_data->SetStop(reads_count + writes_count);
73 return socket_data.Pass(); 75 return socket_data.Pass();
74 } 76 }
75 77
76 // Builder for a DeterministicSocketData that expects nothing. This does not 78 // Builder for a DeterministicSocketData that expects nothing. This does not
77 // set the connect data, so the calling code must do that explicitly. 79 // set the connect data, so the calling code must do that explicitly.
78 scoped_ptr<DeterministicSocketData> BuildNullSocketData() { 80 scoped_ptr<DeterministicSocketData> BuildNullSocketData() {
79 return make_scoped_ptr(new DeterministicSocketData(NULL, 0, NULL, 0)); 81 return make_scoped_ptr(new DeterministicSocketData(NULL, 0, NULL, 0));
80 } 82 }
81 83
84 class MockWeakTimer : public base::MockTimer,
85 public base::SupportsWeakPtr<MockWeakTimer> {
86 public:
87 MockWeakTimer(bool retain_user_task, bool is_repeating)
88 : MockTimer(retain_user_task, is_repeating) {}
89 };
90
82 // A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a 91 // A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a
83 // deterministic key to use in the WebSocket handshake. 92 // deterministic key to use in the WebSocket handshake.
84 class DeterministicKeyWebSocketHandshakeStreamCreateHelper 93 class DeterministicKeyWebSocketHandshakeStreamCreateHelper
85 : public WebSocketHandshakeStreamCreateHelper { 94 : public WebSocketHandshakeStreamCreateHelper {
86 public: 95 public:
87 DeterministicKeyWebSocketHandshakeStreamCreateHelper( 96 DeterministicKeyWebSocketHandshakeStreamCreateHelper(
88 WebSocketStream::ConnectDelegate* connect_delegate, 97 WebSocketStream::ConnectDelegate* connect_delegate,
89 const std::vector<std::string>& requested_subprotocols) 98 const std::vector<std::string>& requested_subprotocols)
90 : WebSocketHandshakeStreamCreateHelper(connect_delegate, 99 : WebSocketHandshakeStreamCreateHelper(connect_delegate,
91 requested_subprotocols) {} 100 requested_subprotocols) {}
92 101
93 virtual void OnStreamCreated(WebSocketBasicHandshakeStream* stream) OVERRIDE { 102 virtual void OnStreamCreated(WebSocketBasicHandshakeStream* stream) OVERRIDE {
94 stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); 103 stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ==");
95 } 104 }
96 }; 105 };
97 106
98 class WebSocketStreamCreateTest : public ::testing::Test { 107 class WebSocketStreamCreateTest : public ::testing::Test {
99 public: 108 public:
100 WebSocketStreamCreateTest() : has_failed_(false), ssl_fatal_(false) {} 109 WebSocketStreamCreateTest() : has_failed_(false), ssl_fatal_(false) {}
101 110
102 void CreateAndConnectCustomResponse( 111 void CreateAndConnectCustomResponse(
103 const std::string& socket_url, 112 const std::string& socket_url,
104 const std::string& socket_path, 113 const std::string& socket_path,
105 const std::vector<std::string>& sub_protocols, 114 const std::vector<std::string>& sub_protocols,
106 const std::string& origin, 115 const std::string& origin,
107 const std::string& extra_request_headers, 116 const std::string& extra_request_headers,
108 const std::string& response_body) { 117 const std::string& response_body,
118 scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) {
109 url_request_context_host_.SetExpectations( 119 url_request_context_host_.SetExpectations(
110 WebSocketStandardRequest(socket_path, origin, extra_request_headers), 120 WebSocketStandardRequest(socket_path, origin, extra_request_headers),
111 response_body); 121 response_body);
112 CreateAndConnectStream(socket_url, sub_protocols, origin); 122 CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass());
113 } 123 }
114 124
115 // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or 125 // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or
116 // errors like "Unable to perform synchronous IO while stopped" will occur. 126 // errors like "Unable to perform synchronous IO while stopped" will occur.
117 void CreateAndConnectStandard(const std::string& socket_url, 127 void CreateAndConnectStandard(const std::string& socket_url,
118 const std::string& socket_path, 128 const std::string& socket_path,
119 const std::vector<std::string>& sub_protocols, 129 const std::vector<std::string>& sub_protocols,
120 const std::string& origin, 130 const std::string& origin,
121 const std::string& extra_request_headers, 131 const std::string& extra_request_headers,
122 const std::string& extra_response_headers) { 132 const std::string& extra_response_headers,
133 scoped_ptr<base::Timer> timer =
134 scoped_ptr<base::Timer>()) {
123 CreateAndConnectCustomResponse( 135 CreateAndConnectCustomResponse(
124 socket_url, 136 socket_url,
125 socket_path, 137 socket_path,
126 sub_protocols, 138 sub_protocols,
127 origin, 139 origin,
128 extra_request_headers, 140 extra_request_headers,
129 WebSocketStandardResponse(extra_response_headers)); 141 WebSocketStandardResponse(extra_response_headers),
142 timer.Pass());
130 } 143 }
131 144
132 void CreateAndConnectRawExpectations( 145 void CreateAndConnectRawExpectations(
133 const std::string& socket_url, 146 const std::string& socket_url,
134 const std::vector<std::string>& sub_protocols, 147 const std::vector<std::string>& sub_protocols,
135 const std::string& origin, 148 const std::string& origin,
136 scoped_ptr<DeterministicSocketData> socket_data) { 149 scoped_ptr<DeterministicSocketData> socket_data,
150 scoped_ptr<base::Timer> timer = scoped_ptr<base::Timer>()) {
137 AddRawExpectations(socket_data.Pass()); 151 AddRawExpectations(socket_data.Pass());
138 CreateAndConnectStream(socket_url, sub_protocols, origin); 152 CreateAndConnectStream(socket_url, sub_protocols, origin, timer.Pass());
139 } 153 }
140 154
141 // Add additional raw expectations for sockets created before the final one. 155 // Add additional raw expectations for sockets created before the final one.
142 void AddRawExpectations(scoped_ptr<DeterministicSocketData> socket_data) { 156 void AddRawExpectations(scoped_ptr<DeterministicSocketData> socket_data) {
143 url_request_context_host_.AddRawExpectations(socket_data.Pass()); 157 url_request_context_host_.AddRawExpectations(socket_data.Pass());
144 } 158 }
145 159
146 // A wrapper for CreateAndConnectStreamForTesting that knows about our default 160 // A wrapper for CreateAndConnectStreamForTesting that knows about our default
147 // parameters. 161 // parameters.
148 void CreateAndConnectStream(const std::string& socket_url, 162 void CreateAndConnectStream(const std::string& socket_url,
149 const std::vector<std::string>& sub_protocols, 163 const std::vector<std::string>& sub_protocols,
150 const std::string& origin) { 164 const std::string& origin,
165 scoped_ptr<base::Timer> timer) {
151 for (size_t i = 0; i < ssl_data_.size(); ++i) { 166 for (size_t i = 0; i < ssl_data_.size(); ++i) {
152 scoped_ptr<SSLSocketDataProvider> ssl_data(ssl_data_[i]); 167 scoped_ptr<SSLSocketDataProvider> ssl_data(ssl_data_[i]);
153 ssl_data_[i] = NULL; 168 ssl_data_[i] = NULL;
154 url_request_context_host_.AddSSLSocketDataProvider(ssl_data.Pass()); 169 url_request_context_host_.AddSSLSocketDataProvider(ssl_data.Pass());
155 } 170 }
156 ssl_data_.clear(); 171 ssl_data_.clear();
157 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate( 172 scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate(
158 new TestConnectDelegate(this)); 173 new TestConnectDelegate(this));
159 WebSocketStream::ConnectDelegate* delegate = connect_delegate.get(); 174 WebSocketStream::ConnectDelegate* delegate = connect_delegate.get();
160 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper( 175 scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper(
161 new DeterministicKeyWebSocketHandshakeStreamCreateHelper( 176 new DeterministicKeyWebSocketHandshakeStreamCreateHelper(
162 delegate, sub_protocols)); 177 delegate, sub_protocols));
163 stream_request_ = ::net::CreateAndConnectStreamForTesting( 178 stream_request_ = ::net::CreateAndConnectStreamForTesting(
164 GURL(socket_url), 179 GURL(socket_url),
165 create_helper.Pass(), 180 create_helper.Pass(),
166 url::Origin(origin), 181 url::Origin(origin),
167 url_request_context_host_.GetURLRequestContext(), 182 url_request_context_host_.GetURLRequestContext(),
168 BoundNetLog(), 183 BoundNetLog(),
169 connect_delegate.Pass()); 184 connect_delegate.Pass(),
185 timer ? timer.Pass() : scoped_ptr<base::Timer>(
186 new base::Timer(false, false)));
170 } 187 }
171 188
172 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } 189 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
173 190
174 // A simple function to make the tests more readable. Creates an empty vector. 191 // A simple function to make the tests more readable. Creates an empty vector.
175 static std::vector<std::string> NoSubProtocols() { 192 static std::vector<std::string> NoSubProtocols() {
176 return std::vector<std::string>(); 193 return std::vector<std::string>();
177 } 194 }
178 195
179 const std::string& failure_message() const { return failure_message_; } 196 const std::string& failure_message() const { return failure_message_; }
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 socket_data->set_connect_data( 1108 socket_data->set_connect_data(
1092 MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); 1109 MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT));
1093 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 1110 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
1094 "http://localhost", socket_data.Pass()); 1111 "http://localhost", socket_data.Pass());
1095 RunUntilIdle(); 1112 RunUntilIdle();
1096 EXPECT_TRUE(has_failed()); 1113 EXPECT_TRUE(has_failed());
1097 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", 1114 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT",
1098 failure_message()); 1115 failure_message());
1099 } 1116 }
1100 1117
1118 // The server doesn't respond to the opening handshake.
1119 TEST_F(WebSocketStreamCreateTest, HandshakeTimeout) {
1120 scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData());
1121 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
1122 scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false));
1123 base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
1124 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
1125 "http://localhost", socket_data.Pass(),
1126 timer.PassAs<base::Timer>());
1127 EXPECT_FALSE(has_failed());
1128 ASSERT_TRUE(weak_timer.get());
1129 EXPECT_TRUE(weak_timer->IsRunning());
1130
1131 weak_timer->Fire();
1132 RunUntilIdle();
1133
1134 EXPECT_TRUE(has_failed());
1135 EXPECT_EQ("WebSocket opening handshake timed out", failure_message());
1136 ASSERT_TRUE(weak_timer.get());
1137 EXPECT_FALSE(weak_timer->IsRunning());
1138 }
1139
1140 // When the connection establishes the timer should be stopped.
1141 TEST_F(WebSocketStreamCreateTest, HandshakeTimerOnSuccess) {
1142 scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false));
1143 base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
1144
1145 CreateAndConnectStandard(
1146 "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", "",
1147 timer.PassAs<base::Timer>());
1148 EXPECT_FALSE(request_info_);
Adam Rice 2014/09/11 09:47:39 I think you should remove these two assertions as
yhirano 2014/09/11 10:46:49 Done.
1149 EXPECT_FALSE(response_info_);
1150 ASSERT_TRUE(weak_timer);
1151 EXPECT_TRUE(weak_timer->IsRunning());
1152
1153 RunUntilIdle();
1154 EXPECT_FALSE(has_failed());
1155 EXPECT_TRUE(stream_);
Adam Rice 2014/09/11 09:47:39 Also please remove these three assertions as above
yhirano 2014/09/11 10:46:49 I want to make sure the operation succeeds. So I'd
1156 EXPECT_TRUE(request_info_);
1157 EXPECT_TRUE(response_info_);
1158 ASSERT_TRUE(weak_timer);
1159 EXPECT_FALSE(weak_timer->IsRunning());
1160 }
1161
1162 // When the connection fails the timer should be stopped.
1163 TEST_F(WebSocketStreamCreateTest, HandshakeTimerOnFailure) {
1164 scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData());
1165 socket_data->set_connect_data(
1166 MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1167 scoped_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false));
1168 base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
1169 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
1170 "http://localhost", socket_data.Pass(),
1171 timer.PassAs<base::Timer>());
1172 ASSERT_TRUE(weak_timer.get());
1173 EXPECT_TRUE(weak_timer->IsRunning());
1174
1175 RunUntilIdle();
1176 EXPECT_TRUE(has_failed());
1177 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED",
1178 failure_message());
1179 ASSERT_TRUE(weak_timer.get());
1180 EXPECT_FALSE(weak_timer->IsRunning());
1181 }
1182
1101 // Cancellation during connect works. 1183 // Cancellation during connect works.
1102 TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { 1184 TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) {
1103 scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); 1185 scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData());
1104 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); 1186 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
1105 CreateAndConnectRawExpectations("ws://localhost/", 1187 CreateAndConnectRawExpectations("ws://localhost/",
1106 NoSubProtocols(), 1188 NoSubProtocols(),
1107 "http://localhost", 1189 "http://localhost",
1108 socket_data.Pass()); 1190 socket_data.Pass());
1109 stream_request_.reset(); 1191 stream_request_.reset();
1110 RunUntilIdle(); 1192 RunUntilIdle();
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 if (original) { 1449 if (original) {
1368 samples->Subtract(*original); // Cancel the original values. 1450 samples->Subtract(*original); // Cancel the original values.
1369 } 1451 }
1370 EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); 1452 EXPECT_EQ(1, samples->GetCount(INCOMPLETE));
1371 EXPECT_EQ(0, samples->GetCount(CONNECTED)); 1453 EXPECT_EQ(0, samples->GetCount(CONNECTED));
1372 EXPECT_EQ(0, samples->GetCount(FAILED)); 1454 EXPECT_EQ(0, samples->GetCount(FAILED));
1373 } 1455 }
1374 1456
1375 } // namespace 1457 } // namespace
1376 } // namespace net 1458 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_stream.cc ('k') | net/websockets/websocket_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698