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

Side by Side Diff: google_apis/gcm/engine/connection_factory_impl_unittest.cc

Issue 980433003: [GCM] Fix crash during connection races (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698