OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "google_apis/gcm/engine/connection_factory_impl.h" | 5 #include "google_apis/gcm/engine/connection_factory_impl.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
11 #include "base/test/simple_test_tick_clock.h" | 11 #include "base/test/simple_test_tick_clock.h" |
| 12 #include "google_apis/gcm/base/mcs_util.h" |
| 13 #include "google_apis/gcm/engine/fake_connection_handler.h" |
12 #include "net/base/backoff_entry.h" | 14 #include "net/base/backoff_entry.h" |
13 #include "net/http/http_network_session.h" | 15 #include "net/http/http_network_session.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
15 | 17 |
16 class Policy; | 18 class Policy; |
17 | 19 |
18 namespace gcm { | 20 namespace gcm { |
19 namespace { | 21 namespace { |
20 | 22 |
21 const char kMCSEndpoint[] = "http://my.server"; | 23 const char kMCSEndpoint[] = "http://my.server"; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 double CalculateBackoff(int num_attempts) { | 65 double CalculateBackoff(int num_attempts) { |
64 double delay = kBackoffDelayMs; | 66 double delay = kBackoffDelayMs; |
65 for (int i = 1; i < num_attempts; ++i) { | 67 for (int i = 1; i < num_attempts; ++i) { |
66 delay += kBackoffDelayMs * pow(static_cast<double>(kBackoffMultiplier), | 68 delay += kBackoffDelayMs * pow(static_cast<double>(kBackoffMultiplier), |
67 i - 1); | 69 i - 1); |
68 } | 70 } |
69 DVLOG(1) << "Expected backoff " << delay << " milliseconds."; | 71 DVLOG(1) << "Expected backoff " << delay << " milliseconds."; |
70 return delay; | 72 return delay; |
71 } | 73 } |
72 | 74 |
73 // Helper methods that should never actually be called due to real connections | |
74 // being stubbed out. | |
75 void ReadContinuation( | 75 void ReadContinuation( |
76 scoped_ptr<google::protobuf::MessageLite> message) { | 76 scoped_ptr<google::protobuf::MessageLite> message) { |
77 ADD_FAILURE(); | |
78 } | 77 } |
79 | 78 |
80 void WriteContinuation() { | 79 void WriteContinuation() { |
81 ADD_FAILURE(); | |
82 } | 80 } |
83 | 81 |
84 class TestBackoffEntry : public net::BackoffEntry { | 82 class TestBackoffEntry : public net::BackoffEntry { |
85 public: | 83 public: |
86 explicit TestBackoffEntry(base::SimpleTestTickClock* tick_clock); | 84 explicit TestBackoffEntry(base::SimpleTestTickClock* tick_clock); |
87 virtual ~TestBackoffEntry(); | 85 virtual ~TestBackoffEntry(); |
88 | 86 |
89 virtual base::TimeTicks ImplGetTimeNow() const OVERRIDE; | 87 virtual base::TimeTicks ImplGetTimeNow() const OVERRIDE; |
90 | 88 |
91 private: | 89 private: |
(...skipping 11 matching lines...) Expand all Loading... |
103 return tick_clock_->NowTicks(); | 101 return tick_clock_->NowTicks(); |
104 } | 102 } |
105 | 103 |
106 // A connection factory that stubs out network requests and overrides the | 104 // A connection factory that stubs out network requests and overrides the |
107 // backoff policy. | 105 // backoff policy. |
108 class TestConnectionFactoryImpl : public ConnectionFactoryImpl { | 106 class TestConnectionFactoryImpl : public ConnectionFactoryImpl { |
109 public: | 107 public: |
110 TestConnectionFactoryImpl(const base::Closure& finished_callback); | 108 TestConnectionFactoryImpl(const base::Closure& finished_callback); |
111 virtual ~TestConnectionFactoryImpl(); | 109 virtual ~TestConnectionFactoryImpl(); |
112 | 110 |
| 111 void InitializeFactory(); |
| 112 |
113 // Overridden stubs. | 113 // Overridden stubs. |
114 virtual void ConnectImpl() OVERRIDE; | 114 virtual void ConnectImpl() OVERRIDE; |
115 virtual void InitHandler() OVERRIDE; | 115 virtual void InitHandler() OVERRIDE; |
116 virtual scoped_ptr<net::BackoffEntry> CreateBackoffEntry( | 116 virtual scoped_ptr<net::BackoffEntry> CreateBackoffEntry( |
117 const net::BackoffEntry::Policy* const policy) OVERRIDE; | 117 const net::BackoffEntry::Policy* const policy) OVERRIDE; |
| 118 virtual scoped_ptr<ConnectionHandler> CreateConnectionHandler( |
| 119 base::TimeDelta read_timeout, |
| 120 const ConnectionHandler::ProtoReceivedCallback& read_callback, |
| 121 const ConnectionHandler::ProtoSentCallback& write_callback, |
| 122 const ConnectionHandler::ConnectionChangedCallback& connection_callback) |
| 123 OVERRIDE; |
118 virtual base::TimeTicks NowTicks() OVERRIDE; | 124 virtual base::TimeTicks NowTicks() OVERRIDE; |
119 | 125 |
120 // Helpers for verifying connection attempts are made. Connection results | 126 // Helpers for verifying connection attempts are made. Connection results |
121 // must be consumed. | 127 // must be consumed. |
122 void SetConnectResult(int connect_result); | 128 void SetConnectResult(int connect_result); |
123 void SetMultipleConnectResults(int connect_result, int num_expected_attempts); | 129 void SetMultipleConnectResults(int connect_result, int num_expected_attempts); |
124 | 130 |
125 base::SimpleTestTickClock* tick_clock() { return &tick_clock_; } | 131 base::SimpleTestTickClock* tick_clock() { return &tick_clock_; } |
126 | 132 |
127 private: | 133 private: |
128 // Clock for controlling delay. | 134 // Clock for controlling delay. |
129 base::SimpleTestTickClock tick_clock_; | 135 base::SimpleTestTickClock tick_clock_; |
130 // The result to return on the next connect attempt. | 136 // The result to return on the next connect attempt. |
131 int connect_result_; | 137 int connect_result_; |
132 // The number of expected connection attempts; | 138 // The number of expected connection attempts; |
133 int num_expected_attempts_; | 139 int num_expected_attempts_; |
134 // Whether all expected connection attempts have been fulfilled since an | 140 // Whether all expected connection attempts have been fulfilled since an |
135 // expectation was last set. | 141 // expectation was last set. |
136 bool connections_fulfilled_; | 142 bool connections_fulfilled_; |
137 // Callback to invoke when all connection attempts have been made. | 143 // Callback to invoke when all connection attempts have been made. |
138 base::Closure finished_callback_; | 144 base::Closure finished_callback_; |
| 145 // The current fake connection handler.. |
| 146 FakeConnectionHandler* fake_handler_; |
139 }; | 147 }; |
140 | 148 |
141 TestConnectionFactoryImpl::TestConnectionFactoryImpl( | 149 TestConnectionFactoryImpl::TestConnectionFactoryImpl( |
142 const base::Closure& finished_callback) | 150 const base::Closure& finished_callback) |
143 : ConnectionFactoryImpl(BuildEndpoints(), | 151 : ConnectionFactoryImpl(BuildEndpoints(), |
144 net::BackoffEntry::Policy(), | 152 net::BackoffEntry::Policy(), |
145 NULL, | 153 NULL, |
146 NULL), | 154 NULL), |
147 connect_result_(net::ERR_UNEXPECTED), | 155 connect_result_(net::ERR_UNEXPECTED), |
148 num_expected_attempts_(0), | 156 num_expected_attempts_(0), |
149 connections_fulfilled_(true), | 157 connections_fulfilled_(true), |
150 finished_callback_(finished_callback) { | 158 finished_callback_(finished_callback), |
| 159 fake_handler_(NULL) { |
151 // Set a non-null time. | 160 // Set a non-null time. |
152 tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); | 161 tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); |
153 } | 162 } |
154 | 163 |
155 TestConnectionFactoryImpl::~TestConnectionFactoryImpl() { | 164 TestConnectionFactoryImpl::~TestConnectionFactoryImpl() { |
156 EXPECT_EQ(0, num_expected_attempts_); | 165 EXPECT_EQ(0, num_expected_attempts_); |
157 } | 166 } |
158 | 167 |
159 void TestConnectionFactoryImpl::ConnectImpl() { | 168 void TestConnectionFactoryImpl::ConnectImpl() { |
160 ASSERT_GT(num_expected_attempts_, 0); | 169 ASSERT_GT(num_expected_attempts_, 0); |
161 | 170 scoped_ptr<mcs_proto::LoginRequest> request(BuildLoginRequest(0, 0, "")); |
| 171 GetConnectionHandler()->Init(*request, NULL); |
162 OnConnectDone(connect_result_); | 172 OnConnectDone(connect_result_); |
163 if (!NextRetryAttempt().is_null()) { | 173 if (!NextRetryAttempt().is_null()) { |
164 // Advance the time to the next retry time. | 174 // Advance the time to the next retry time. |
165 base::TimeDelta time_till_retry = | 175 base::TimeDelta time_till_retry = |
166 NextRetryAttempt() - tick_clock_.NowTicks(); | 176 NextRetryAttempt() - tick_clock_.NowTicks(); |
167 tick_clock_.Advance(time_till_retry); | 177 tick_clock_.Advance(time_till_retry); |
168 } | 178 } |
169 --num_expected_attempts_; | 179 --num_expected_attempts_; |
170 if (num_expected_attempts_ == 0) { | 180 if (num_expected_attempts_ == 0) { |
171 connect_result_ = net::ERR_UNEXPECTED; | 181 connect_result_ = net::ERR_UNEXPECTED; |
172 connections_fulfilled_ = true; | 182 connections_fulfilled_ = true; |
173 finished_callback_.Run(); | 183 finished_callback_.Run(); |
174 } | 184 } |
175 } | 185 } |
176 | 186 |
177 void TestConnectionFactoryImpl::InitHandler() { | 187 void TestConnectionFactoryImpl::InitHandler() { |
178 EXPECT_NE(connect_result_, net::ERR_UNEXPECTED); | 188 EXPECT_NE(connect_result_, net::ERR_UNEXPECTED); |
179 ConnectionHandlerCallback(net::OK); | 189 ConnectionHandlerCallback(net::OK); |
180 } | 190 } |
181 | 191 |
182 scoped_ptr<net::BackoffEntry> TestConnectionFactoryImpl::CreateBackoffEntry( | 192 scoped_ptr<net::BackoffEntry> TestConnectionFactoryImpl::CreateBackoffEntry( |
183 const net::BackoffEntry::Policy* const policy) { | 193 const net::BackoffEntry::Policy* const policy) { |
184 return scoped_ptr<net::BackoffEntry>(new TestBackoffEntry(&tick_clock_)); | 194 return scoped_ptr<net::BackoffEntry>(new TestBackoffEntry(&tick_clock_)); |
185 } | 195 } |
186 | 196 |
| 197 scoped_ptr<ConnectionHandler> |
| 198 TestConnectionFactoryImpl::CreateConnectionHandler( |
| 199 base::TimeDelta read_timeout, |
| 200 const ConnectionHandler::ProtoReceivedCallback& read_callback, |
| 201 const ConnectionHandler::ProtoSentCallback& write_callback, |
| 202 const ConnectionHandler::ConnectionChangedCallback& connection_callback) { |
| 203 fake_handler_ = new FakeConnectionHandler( |
| 204 base::Bind(&ReadContinuation), |
| 205 base::Bind(&WriteContinuation)); |
| 206 return make_scoped_ptr<ConnectionHandler>(fake_handler_); |
| 207 } |
| 208 |
187 base::TimeTicks TestConnectionFactoryImpl::NowTicks() { | 209 base::TimeTicks TestConnectionFactoryImpl::NowTicks() { |
188 return tick_clock_.NowTicks(); | 210 return tick_clock_.NowTicks(); |
189 } | 211 } |
190 | 212 |
191 void TestConnectionFactoryImpl::SetConnectResult(int connect_result) { | 213 void TestConnectionFactoryImpl::SetConnectResult(int connect_result) { |
192 DCHECK_NE(connect_result, net::ERR_UNEXPECTED); | 214 DCHECK_NE(connect_result, net::ERR_UNEXPECTED); |
193 ASSERT_EQ(0, num_expected_attempts_); | 215 ASSERT_EQ(0, num_expected_attempts_); |
194 connections_fulfilled_ = false; | 216 connections_fulfilled_ = false; |
195 connect_result_ = connect_result; | 217 connect_result_ = connect_result; |
196 num_expected_attempts_ = 1; | 218 num_expected_attempts_ = 1; |
| 219 fake_handler_->ExpectOutgoingMessage( |
| 220 MCSMessage(kLoginRequestTag, |
| 221 BuildLoginRequest(0, 0, "").PassAs< |
| 222 const google::protobuf::MessageLite>())); |
197 } | 223 } |
198 | 224 |
199 void TestConnectionFactoryImpl::SetMultipleConnectResults( | 225 void TestConnectionFactoryImpl::SetMultipleConnectResults( |
200 int connect_result, | 226 int connect_result, |
201 int num_expected_attempts) { | 227 int num_expected_attempts) { |
202 DCHECK_NE(connect_result, net::ERR_UNEXPECTED); | 228 DCHECK_NE(connect_result, net::ERR_UNEXPECTED); |
203 DCHECK_GT(num_expected_attempts, 0); | 229 DCHECK_GT(num_expected_attempts, 0); |
204 ASSERT_EQ(0, num_expected_attempts_); | 230 ASSERT_EQ(0, num_expected_attempts_); |
205 connections_fulfilled_ = false; | 231 connections_fulfilled_ = false; |
206 connect_result_ = connect_result; | 232 connect_result_ = connect_result; |
207 num_expected_attempts_ = num_expected_attempts; | 233 num_expected_attempts_ = num_expected_attempts; |
| 234 for (int i = 0 ; i < num_expected_attempts; ++i) { |
| 235 fake_handler_->ExpectOutgoingMessage( |
| 236 MCSMessage(kLoginRequestTag, |
| 237 BuildLoginRequest(0, 0, "").PassAs< |
| 238 const google::protobuf::MessageLite>())); |
| 239 } |
208 } | 240 } |
209 | 241 |
210 class ConnectionFactoryImplTest : public testing::Test { | 242 class ConnectionFactoryImplTest : public testing::Test { |
211 public: | 243 public: |
212 ConnectionFactoryImplTest(); | 244 ConnectionFactoryImplTest(); |
213 virtual ~ConnectionFactoryImplTest(); | 245 virtual ~ConnectionFactoryImplTest(); |
214 | 246 |
215 TestConnectionFactoryImpl* factory() { return &factory_; } | 247 TestConnectionFactoryImpl* factory() { return &factory_; } |
216 | 248 |
217 void WaitForConnections(); | 249 void WaitForConnections(); |
218 | 250 |
219 private: | 251 private: |
220 void ConnectionsComplete(); | 252 void ConnectionsComplete(); |
221 | 253 |
222 TestConnectionFactoryImpl factory_; | 254 TestConnectionFactoryImpl factory_; |
223 base::MessageLoop message_loop_; | 255 base::MessageLoop message_loop_; |
224 scoped_ptr<base::RunLoop> run_loop_; | 256 scoped_ptr<base::RunLoop> run_loop_; |
225 }; | 257 }; |
226 | 258 |
227 ConnectionFactoryImplTest::ConnectionFactoryImplTest() | 259 ConnectionFactoryImplTest::ConnectionFactoryImplTest() |
228 : factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete, | 260 : factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete, |
229 base::Unretained(this))), | 261 base::Unretained(this))), |
230 run_loop_(new base::RunLoop()) {} | 262 run_loop_(new base::RunLoop()) { |
| 263 factory()->Initialize( |
| 264 ConnectionFactory::BuildLoginRequestCallback(), |
| 265 ConnectionHandler::ProtoReceivedCallback(), |
| 266 ConnectionHandler::ProtoSentCallback()); |
| 267 } |
231 ConnectionFactoryImplTest::~ConnectionFactoryImplTest() {} | 268 ConnectionFactoryImplTest::~ConnectionFactoryImplTest() {} |
232 | 269 |
233 void ConnectionFactoryImplTest::WaitForConnections() { | 270 void ConnectionFactoryImplTest::WaitForConnections() { |
234 run_loop_->Run(); | 271 run_loop_->Run(); |
235 run_loop_.reset(new base::RunLoop()); | 272 run_loop_.reset(new base::RunLoop()); |
236 } | 273 } |
237 | 274 |
238 void ConnectionFactoryImplTest::ConnectionsComplete() { | 275 void ConnectionFactoryImplTest::ConnectionsComplete() { |
239 if (!run_loop_) | 276 if (!run_loop_) |
240 return; | 277 return; |
241 run_loop_->Quit(); | 278 run_loop_->Quit(); |
242 } | 279 } |
243 | 280 |
244 // Verify building a connection handler works. | 281 // Verify building a connection handler works. |
245 TEST_F(ConnectionFactoryImplTest, Initialize) { | 282 TEST_F(ConnectionFactoryImplTest, Initialize) { |
246 EXPECT_FALSE(factory()->IsEndpointReachable()); | |
247 factory()->Initialize( | |
248 ConnectionFactory::BuildLoginRequestCallback(), | |
249 base::Bind(&ReadContinuation), | |
250 base::Bind(&WriteContinuation)); | |
251 ConnectionHandler* handler = factory()->GetConnectionHandler(); | 283 ConnectionHandler* handler = factory()->GetConnectionHandler(); |
252 ASSERT_TRUE(handler); | 284 ASSERT_TRUE(handler); |
253 EXPECT_FALSE(factory()->IsEndpointReachable()); | 285 EXPECT_FALSE(factory()->IsEndpointReachable()); |
254 } | 286 } |
255 | 287 |
256 // An initial successful connection should not result in backoff. | 288 // An initial successful connection should not result in backoff. |
257 TEST_F(ConnectionFactoryImplTest, ConnectSuccess) { | 289 TEST_F(ConnectionFactoryImplTest, ConnectSuccess) { |
258 factory()->Initialize( | |
259 ConnectionFactory::BuildLoginRequestCallback(), | |
260 ConnectionHandler::ProtoReceivedCallback(), | |
261 ConnectionHandler::ProtoSentCallback()); | |
262 factory()->SetConnectResult(net::OK); | 290 factory()->SetConnectResult(net::OK); |
263 factory()->Connect(); | 291 factory()->Connect(); |
264 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 292 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
265 EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]); | 293 EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]); |
| 294 EXPECT_TRUE(factory()->IsEndpointReachable()); |
266 } | 295 } |
267 | 296 |
268 // A connection failure should result in backoff, and attempting the fallback | 297 // A connection failure should result in backoff, and attempting the fallback |
269 // endpoint next. | 298 // endpoint next. |
270 TEST_F(ConnectionFactoryImplTest, ConnectFail) { | 299 TEST_F(ConnectionFactoryImplTest, ConnectFail) { |
271 factory()->Initialize( | |
272 ConnectionFactory::BuildLoginRequestCallback(), | |
273 ConnectionHandler::ProtoReceivedCallback(), | |
274 ConnectionHandler::ProtoSentCallback()); | |
275 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); | 300 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); |
276 factory()->Connect(); | 301 factory()->Connect(); |
277 EXPECT_FALSE(factory()->NextRetryAttempt().is_null()); | 302 EXPECT_FALSE(factory()->NextRetryAttempt().is_null()); |
278 EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]); | 303 EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]); |
| 304 EXPECT_FALSE(factory()->IsEndpointReachable()); |
279 } | 305 } |
280 | 306 |
281 // A connection success after a failure should reset backoff. | 307 // A connection success after a failure should reset backoff. |
282 TEST_F(ConnectionFactoryImplTest, FailThenSucceed) { | 308 TEST_F(ConnectionFactoryImplTest, FailThenSucceed) { |
283 factory()->Initialize( | |
284 ConnectionFactory::BuildLoginRequestCallback(), | |
285 ConnectionHandler::ProtoReceivedCallback(), | |
286 ConnectionHandler::ProtoSentCallback()); | |
287 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); | 309 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); |
288 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks(); | 310 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks(); |
289 factory()->Connect(); | 311 factory()->Connect(); |
290 WaitForConnections(); | 312 WaitForConnections(); |
| 313 EXPECT_FALSE(factory()->IsEndpointReachable()); |
291 base::TimeTicks retry_time = factory()->NextRetryAttempt(); | 314 base::TimeTicks retry_time = factory()->NextRetryAttempt(); |
292 EXPECT_FALSE(retry_time.is_null()); | 315 EXPECT_FALSE(retry_time.is_null()); |
293 EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1)); | 316 EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1)); |
294 factory()->SetConnectResult(net::OK); | 317 factory()->SetConnectResult(net::OK); |
295 WaitForConnections(); | 318 WaitForConnections(); |
296 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 319 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
| 320 EXPECT_TRUE(factory()->IsEndpointReachable()); |
297 } | 321 } |
298 | 322 |
299 // Multiple connection failures should retry with an exponentially increasing | 323 // Multiple connection failures should retry with an exponentially increasing |
300 // backoff, then reset on success. | 324 // backoff, then reset on success. |
301 TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) { | 325 TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) { |
302 factory()->Initialize( | |
303 ConnectionFactory::BuildLoginRequestCallback(), | |
304 ConnectionHandler::ProtoReceivedCallback(), | |
305 ConnectionHandler::ProtoSentCallback()); | |
306 | 326 |
307 const int kNumAttempts = 5; | 327 const int kNumAttempts = 5; |
308 factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED, | 328 factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED, |
309 kNumAttempts); | 329 kNumAttempts); |
310 | 330 |
311 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks(); | 331 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks(); |
312 factory()->Connect(); | 332 factory()->Connect(); |
313 WaitForConnections(); | 333 WaitForConnections(); |
| 334 EXPECT_FALSE(factory()->IsEndpointReachable()); |
314 base::TimeTicks retry_time = factory()->NextRetryAttempt(); | 335 base::TimeTicks retry_time = factory()->NextRetryAttempt(); |
315 EXPECT_FALSE(retry_time.is_null()); | 336 EXPECT_FALSE(retry_time.is_null()); |
316 EXPECT_GE((retry_time - connect_time).InMilliseconds(), | 337 EXPECT_GE((retry_time - connect_time).InMilliseconds(), |
317 CalculateBackoff(kNumAttempts)); | 338 CalculateBackoff(kNumAttempts)); |
318 | 339 |
319 factory()->SetConnectResult(net::OK); | 340 factory()->SetConnectResult(net::OK); |
320 WaitForConnections(); | 341 WaitForConnections(); |
321 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 342 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
| 343 EXPECT_TRUE(factory()->IsEndpointReachable()); |
322 } | 344 } |
323 | 345 |
324 // IP events should reset backoff. | 346 // IP events should trigger canary connections. |
325 TEST_F(ConnectionFactoryImplTest, FailThenIPEvent) { | 347 TEST_F(ConnectionFactoryImplTest, FailThenIPEvent) { |
326 factory()->Initialize( | |
327 ConnectionFactory::BuildLoginRequestCallback(), | |
328 ConnectionHandler::ProtoReceivedCallback(), | |
329 ConnectionHandler::ProtoSentCallback()); | |
330 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); | 348 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); |
331 factory()->Connect(); | 349 factory()->Connect(); |
332 WaitForConnections(); | 350 WaitForConnections(); |
333 EXPECT_FALSE(factory()->NextRetryAttempt().is_null()); | 351 base::TimeTicks initial_backoff = factory()->NextRetryAttempt(); |
| 352 EXPECT_FALSE(initial_backoff.is_null()); |
334 | 353 |
| 354 factory()->SetConnectResult(net::ERR_FAILED); |
335 factory()->OnIPAddressChanged(); | 355 factory()->OnIPAddressChanged(); |
336 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 356 WaitForConnections(); |
| 357 |
| 358 // Backoff should increase. |
| 359 base::TimeTicks next_backoff = factory()->NextRetryAttempt(); |
| 360 EXPECT_GT(next_backoff, initial_backoff); |
| 361 EXPECT_FALSE(factory()->IsEndpointReachable()); |
337 } | 362 } |
338 | 363 |
339 // Connection type events should reset backoff. | 364 // Connection type events should trigger canary connections. |
340 TEST_F(ConnectionFactoryImplTest, FailThenConnectionTypeEvent) { | 365 TEST_F(ConnectionFactoryImplTest, FailThenConnectionTypeEvent) { |
341 factory()->Initialize( | |
342 ConnectionFactory::BuildLoginRequestCallback(), | |
343 ConnectionHandler::ProtoReceivedCallback(), | |
344 ConnectionHandler::ProtoSentCallback()); | |
345 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); | 366 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); |
346 factory()->Connect(); | 367 factory()->Connect(); |
347 WaitForConnections(); | 368 WaitForConnections(); |
348 EXPECT_FALSE(factory()->NextRetryAttempt().is_null()); | 369 base::TimeTicks initial_backoff = factory()->NextRetryAttempt(); |
| 370 EXPECT_FALSE(initial_backoff.is_null()); |
349 | 371 |
| 372 factory()->SetConnectResult(net::ERR_FAILED); |
350 factory()->OnConnectionTypeChanged( | 373 factory()->OnConnectionTypeChanged( |
351 net::NetworkChangeNotifier::CONNECTION_WIFI); | 374 net::NetworkChangeNotifier::CONNECTION_WIFI); |
352 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 375 WaitForConnections(); |
| 376 |
| 377 // Backoff should increase. |
| 378 base::TimeTicks next_backoff = factory()->NextRetryAttempt(); |
| 379 EXPECT_GT(next_backoff, initial_backoff); |
| 380 EXPECT_FALSE(factory()->IsEndpointReachable()); |
| 381 } |
| 382 |
| 383 // Verify that we reconnect even if a canary succeeded then disconnected while |
| 384 // a backoff was pending. |
| 385 TEST_F(ConnectionFactoryImplTest, CanarySucceedsThenDisconnects) { |
| 386 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); |
| 387 factory()->Connect(); |
| 388 WaitForConnections(); |
| 389 base::TimeTicks initial_backoff = factory()->NextRetryAttempt(); |
| 390 EXPECT_FALSE(initial_backoff.is_null()); |
| 391 |
| 392 factory()->SetConnectResult(net::OK); |
| 393 factory()->OnConnectionTypeChanged( |
| 394 net::NetworkChangeNotifier::CONNECTION_WIFI); |
| 395 WaitForConnections(); |
| 396 EXPECT_TRUE(factory()->IsEndpointReachable()); |
| 397 |
| 398 factory()->SetConnectResult(net::OK); |
| 399 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); |
| 400 EXPECT_FALSE(factory()->IsEndpointReachable()); |
| 401 WaitForConnections(); |
| 402 EXPECT_TRUE(factory()->IsEndpointReachable()); |
353 } | 403 } |
354 | 404 |
355 // Fail after successful connection via signal reset. | 405 // Fail after successful connection via signal reset. |
356 TEST_F(ConnectionFactoryImplTest, FailViaSignalReset) { | 406 TEST_F(ConnectionFactoryImplTest, FailViaSignalReset) { |
357 factory()->Initialize( | |
358 ConnectionFactory::BuildLoginRequestCallback(), | |
359 ConnectionHandler::ProtoReceivedCallback(), | |
360 ConnectionHandler::ProtoSentCallback()); | |
361 factory()->SetConnectResult(net::OK); | 407 factory()->SetConnectResult(net::OK); |
362 factory()->Connect(); | 408 factory()->Connect(); |
363 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 409 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
364 | 410 |
365 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); | 411 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); |
366 EXPECT_FALSE(factory()->NextRetryAttempt().is_null()); | 412 EXPECT_FALSE(factory()->NextRetryAttempt().is_null()); |
367 EXPECT_FALSE(factory()->GetConnectionHandler()->CanSendMessage()); | 413 EXPECT_FALSE(factory()->IsEndpointReachable()); |
368 } | 414 } |
369 | 415 |
370 TEST_F(ConnectionFactoryImplTest, IgnoreResetWhileConnecting) { | 416 TEST_F(ConnectionFactoryImplTest, IgnoreResetWhileConnecting) { |
371 factory()->Initialize( | |
372 ConnectionFactory::BuildLoginRequestCallback(), | |
373 ConnectionHandler::ProtoReceivedCallback(), | |
374 ConnectionHandler::ProtoSentCallback()); | |
375 factory()->SetConnectResult(net::OK); | 417 factory()->SetConnectResult(net::OK); |
376 factory()->Connect(); | 418 factory()->Connect(); |
377 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 419 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
378 | 420 |
379 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); | 421 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); |
380 base::TimeTicks retry_time = factory()->NextRetryAttempt(); | 422 base::TimeTicks retry_time = factory()->NextRetryAttempt(); |
381 EXPECT_FALSE(retry_time.is_null()); | 423 EXPECT_FALSE(retry_time.is_null()); |
| 424 EXPECT_FALSE(factory()->IsEndpointReachable()); |
382 | 425 |
383 const int kNumAttempts = 5; | 426 const int kNumAttempts = 5; |
384 for (int i = 0; i < kNumAttempts; ++i) | 427 for (int i = 0; i < kNumAttempts; ++i) |
385 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); | 428 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); |
386 EXPECT_EQ(retry_time, factory()->NextRetryAttempt()); | 429 EXPECT_EQ(retry_time, factory()->NextRetryAttempt()); |
| 430 EXPECT_FALSE(factory()->IsEndpointReachable()); |
387 } | 431 } |
388 | 432 |
389 // Go into backoff due to connection failure. On successful connection, receive | 433 // Go into backoff due to connection failure. On successful connection, receive |
390 // a signal reset. The original backoff should be restored and extended, rather | 434 // a signal reset. The original backoff should be restored and extended, rather |
391 // than a new backoff starting from scratch. | 435 // than a new backoff starting from scratch. |
392 TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) { | 436 TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) { |
393 factory()->Initialize( | |
394 ConnectionFactory::BuildLoginRequestCallback(), | |
395 ConnectionHandler::ProtoReceivedCallback(), | |
396 ConnectionHandler::ProtoSentCallback()); | |
397 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); | 437 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED); |
398 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks(); | 438 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks(); |
399 factory()->Connect(); | 439 factory()->Connect(); |
400 WaitForConnections(); | 440 WaitForConnections(); |
401 base::TimeTicks retry_time = factory()->NextRetryAttempt(); | 441 base::TimeTicks retry_time = factory()->NextRetryAttempt(); |
402 EXPECT_FALSE(retry_time.is_null()); | 442 EXPECT_FALSE(retry_time.is_null()); |
403 | 443 |
404 factory()->SetConnectResult(net::OK); | 444 factory()->SetConnectResult(net::OK); |
405 connect_time = factory()->tick_clock()->NowTicks(); | 445 connect_time = factory()->tick_clock()->NowTicks(); |
406 WaitForConnections(); | 446 WaitForConnections(); |
407 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 447 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
408 | 448 |
409 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); | 449 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); |
410 EXPECT_FALSE(factory()->GetConnectionHandler()->CanSendMessage()); | 450 EXPECT_FALSE(factory()->IsEndpointReachable()); |
411 EXPECT_NE(retry_time, factory()->NextRetryAttempt()); | 451 EXPECT_NE(retry_time, factory()->NextRetryAttempt()); |
412 retry_time = factory()->NextRetryAttempt(); | 452 retry_time = factory()->NextRetryAttempt(); |
413 EXPECT_FALSE(retry_time.is_null()); | 453 EXPECT_FALSE(retry_time.is_null()); |
414 EXPECT_GE((retry_time - connect_time).InMilliseconds(), | 454 EXPECT_GE((retry_time - connect_time).InMilliseconds(), |
415 CalculateBackoff(2)); | 455 CalculateBackoff(2)); |
416 | 456 |
417 factory()->SetConnectResult(net::OK); | 457 factory()->SetConnectResult(net::OK); |
418 connect_time = factory()->tick_clock()->NowTicks(); | 458 connect_time = factory()->tick_clock()->NowTicks(); |
419 factory()->tick_clock()->Advance( | 459 factory()->tick_clock()->Advance( |
420 factory()->NextRetryAttempt() - connect_time); | 460 factory()->NextRetryAttempt() - connect_time); |
421 WaitForConnections(); | 461 WaitForConnections(); |
422 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 462 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
| 463 EXPECT_TRUE(factory()->IsEndpointReachable()); |
423 | 464 |
424 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); | 465 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); |
425 EXPECT_NE(retry_time, factory()->NextRetryAttempt()); | 466 EXPECT_NE(retry_time, factory()->NextRetryAttempt()); |
426 retry_time = factory()->NextRetryAttempt(); | 467 retry_time = factory()->NextRetryAttempt(); |
427 EXPECT_FALSE(retry_time.is_null()); | 468 EXPECT_FALSE(retry_time.is_null()); |
428 EXPECT_GE((retry_time - connect_time).InMilliseconds(), | 469 EXPECT_GE((retry_time - connect_time).InMilliseconds(), |
429 CalculateBackoff(3)); | 470 CalculateBackoff(3)); |
| 471 EXPECT_FALSE(factory()->IsEndpointReachable()); |
430 } | 472 } |
431 | 473 |
432 } // namespace | 474 } // namespace |
433 } // namespace gcm | 475 } // namespace gcm |
OLD | NEW |