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" |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 base::TimeTicks NowTicks() override; | 125 base::TimeTicks NowTicks() override; |
126 | 126 |
127 // Helpers for verifying connection attempts are made. Connection results | 127 // Helpers for verifying connection attempts are made. Connection results |
128 // must be consumed. | 128 // must be consumed. |
129 void SetConnectResult(int connect_result); | 129 void SetConnectResult(int connect_result); |
130 void SetMultipleConnectResults(int connect_result, int num_expected_attempts); | 130 void SetMultipleConnectResults(int connect_result, int num_expected_attempts); |
131 | 131 |
132 // Force a login handshake to be delayed. | 132 // Force a login handshake to be delayed. |
133 void SetDelayLogin(bool delay_login); | 133 void SetDelayLogin(bool delay_login); |
134 | 134 |
| 135 // Simulate a socket error. |
| 136 void SetSocketError(); |
| 137 |
135 base::SimpleTestTickClock* tick_clock() { return &tick_clock_; } | 138 base::SimpleTestTickClock* tick_clock() { return &tick_clock_; } |
136 | 139 |
137 private: | 140 private: |
138 // Clock for controlling delay. | 141 // Clock for controlling delay. |
139 base::SimpleTestTickClock tick_clock_; | 142 base::SimpleTestTickClock tick_clock_; |
140 // The result to return on the next connect attempt. | 143 // The result to return on the next connect attempt. |
141 int connect_result_; | 144 int connect_result_; |
142 // The number of expected connection attempts; | 145 // The number of expected connection attempts; |
143 int num_expected_attempts_; | 146 int num_expected_attempts_; |
144 // Whether all expected connection attempts have been fulfilled since an | 147 // Whether all expected connection attempts have been fulfilled since an |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 // Set a non-null time. | 180 // Set a non-null time. |
178 tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); | 181 tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1)); |
179 } | 182 } |
180 | 183 |
181 TestConnectionFactoryImpl::~TestConnectionFactoryImpl() { | 184 TestConnectionFactoryImpl::~TestConnectionFactoryImpl() { |
182 EXPECT_EQ(0, num_expected_attempts_); | 185 EXPECT_EQ(0, num_expected_attempts_); |
183 } | 186 } |
184 | 187 |
185 void TestConnectionFactoryImpl::ConnectImpl() { | 188 void TestConnectionFactoryImpl::ConnectImpl() { |
186 ASSERT_GT(num_expected_attempts_, 0); | 189 ASSERT_GT(num_expected_attempts_, 0); |
| 190 ASSERT_FALSE(GetConnectionHandler()->CanSendMessage()); |
187 scoped_ptr<mcs_proto::LoginRequest> request(BuildLoginRequest(0, 0, "")); | 191 scoped_ptr<mcs_proto::LoginRequest> request(BuildLoginRequest(0, 0, "")); |
188 GetConnectionHandler()->Init(*request, NULL); | 192 GetConnectionHandler()->Init(*request, NULL); |
189 OnConnectDone(connect_result_); | 193 OnConnectDone(connect_result_); |
190 if (!NextRetryAttempt().is_null()) { | 194 if (!NextRetryAttempt().is_null()) { |
191 // Advance the time to the next retry time. | 195 // Advance the time to the next retry time. |
192 base::TimeDelta time_till_retry = | 196 base::TimeDelta time_till_retry = |
193 NextRetryAttempt() - tick_clock_.NowTicks(); | 197 NextRetryAttempt() - tick_clock_.NowTicks(); |
194 tick_clock_.Advance(time_till_retry); | 198 tick_clock_.Advance(time_till_retry); |
195 } | 199 } |
196 --num_expected_attempts_; | 200 --num_expected_attempts_; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 fake_handler_->ExpectOutgoingMessage( | 252 fake_handler_->ExpectOutgoingMessage( |
249 MCSMessage(kLoginRequestTag, BuildLoginRequest(0, 0, ""))); | 253 MCSMessage(kLoginRequestTag, BuildLoginRequest(0, 0, ""))); |
250 } | 254 } |
251 } | 255 } |
252 | 256 |
253 void TestConnectionFactoryImpl::SetDelayLogin(bool delay_login) { | 257 void TestConnectionFactoryImpl::SetDelayLogin(bool delay_login) { |
254 delay_login_ = delay_login; | 258 delay_login_ = delay_login; |
255 fake_handler_->set_fail_login(delay_login_); | 259 fake_handler_->set_fail_login(delay_login_); |
256 } | 260 } |
257 | 261 |
| 262 void TestConnectionFactoryImpl::SetSocketError() { |
| 263 fake_handler_->set_had_error(true); |
| 264 } |
| 265 |
258 } // namespace | 266 } // namespace |
259 | 267 |
260 class ConnectionFactoryImplTest | 268 class ConnectionFactoryImplTest |
261 : public testing::Test, | 269 : public testing::Test, |
262 public ConnectionFactory::ConnectionListener { | 270 public ConnectionFactory::ConnectionListener { |
263 public: | 271 public: |
264 ConnectionFactoryImplTest(); | 272 ConnectionFactoryImplTest(); |
265 ~ConnectionFactoryImplTest() override; | 273 ~ConnectionFactoryImplTest() override; |
266 | 274 |
267 TestConnectionFactoryImpl* factory() { return &factory_; } | 275 TestConnectionFactoryImpl* factory() { return &factory_; } |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 // Receiving a network change event before the initial connection should have | 562 // Receiving a network change event before the initial connection should have |
555 // no effect. | 563 // no effect. |
556 TEST_F(ConnectionFactoryImplTest, NetworkChangeBeforeFirstConnection) { | 564 TEST_F(ConnectionFactoryImplTest, NetworkChangeBeforeFirstConnection) { |
557 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_4G); | 565 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_4G); |
558 factory()->SetConnectResult(net::OK); | 566 factory()->SetConnectResult(net::OK); |
559 factory()->Connect(); | 567 factory()->Connect(); |
560 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); | 568 EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); |
561 EXPECT_TRUE(factory()->IsEndpointReachable()); | 569 EXPECT_TRUE(factory()->IsEndpointReachable()); |
562 } | 570 } |
563 | 571 |
| 572 // Test that if the client attempts to reconnect while a connection is already |
| 573 // open, we don't crash. |
| 574 TEST_F(ConnectionFactoryImplTest, ConnectionResetRace) { |
| 575 // Initial successful connection. |
| 576 factory()->SetConnectResult(net::OK); |
| 577 factory()->Connect(); |
| 578 WaitForConnections(); |
| 579 EXPECT_TRUE(factory()->IsEndpointReachable()); |
| 580 |
| 581 // Trigger a connection error under the hood. |
| 582 factory()->SetSocketError(); |
| 583 EXPECT_FALSE(factory()->IsEndpointReachable()); |
| 584 |
| 585 // Now trigger force a re-connection. |
| 586 factory()->SetConnectResult(net::OK); |
| 587 factory()->Connect(); |
| 588 WaitForConnections(); |
| 589 |
| 590 // Re-connection should succeed. |
| 591 EXPECT_TRUE(factory()->IsEndpointReachable()); |
| 592 } |
| 593 |
564 } // namespace gcm | 594 } // namespace gcm |
OLD | NEW |