| 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 |