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
3 // found in the LICENSE file.
4 
5 #include "google_apis/gcm/engine/connection_factory_impl.h"
6 
7 #include <cmath>
8 #include <memory>
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/optional.h"
13 #include "base/run_loop.h"
14 #include "base/test/simple_test_tick_clock.h"
15 #include "base/test/task_environment.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "google_apis/gcm/base/mcs_util.h"
18 #include "google_apis/gcm/engine/fake_connection_handler.h"
19 #include "google_apis/gcm/monitoring/fake_gcm_stats_recorder.h"
20 #include "mojo/public/cpp/bindings/pending_receiver.h"
21 #include "net/base/backoff_entry.h"
22 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
23 #include "net/url_request/url_request_test_util.h"
24 #include "services/network/network_context.h"
25 #include "services/network/network_service.h"
26 #include "services/network/public/mojom/proxy_resolving_socket.mojom.h"
27 #include "services/network/test/fake_test_cert_verifier_params_factory.h"
28 #include "services/network/test/test_network_connection_tracker.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 
31 class Policy;
32 
33 namespace gcm {
34 namespace {
35 
36 const char kMCSEndpoint[] = "http://my.server";
37 const char kMCSEndpoint2[] = "http://my.alt.server";
38 
39 const int kBackoffDelayMs = 1;
40 const int kBackoffMultiplier = 2;
41 
42 // A backoff policy with small enough delays that tests aren't burdened.
43 const net::BackoffEntry::Policy kTestBackoffPolicy = {
44   // Number of initial errors (in sequence) to ignore before applying
45   // exponential back-off rules.
46   0,
47 
48   // Initial delay for exponential back-off in ms.
49   kBackoffDelayMs,
50 
51   // Factor by which the waiting time will be multiplied.
52   kBackoffMultiplier,
53 
54   // Fuzzing percentage. ex: 10% will spread requests randomly
55   // between 90%-100% of the calculated time.
56   0,
57 
58   // Maximum amount of time we are willing to delay our request in ms.
59   10,
60 
61   // Time to keep an entry from being discarded even when it
62   // has no significant state, -1 to never discard.
63   -1,
64 
65   // Don't use initial delay unless the last request was an error.
66   false,
67 };
68 
BuildEndpoints()69 std::vector<GURL> BuildEndpoints() {
70   std::vector<GURL> endpoints;
71   endpoints.push_back(GURL(kMCSEndpoint));
72   endpoints.push_back(GURL(kMCSEndpoint2));
73   return endpoints;
74 }
75 
76 // Helper for calculating total expected exponential backoff delay given an
77 // arbitrary number of failed attempts. See BackoffEntry::CalculateReleaseTime.
CalculateBackoff(int num_attempts)78 double CalculateBackoff(int num_attempts) {
79   double delay = kBackoffDelayMs;
80   for (int i = 1; i < num_attempts; ++i) {
81     delay += kBackoffDelayMs * pow(static_cast<double>(kBackoffMultiplier),
82                                    i - 1);
83   }
84   DVLOG(1) << "Expected backoff " << delay << " milliseconds.";
85   return delay;
86 }
87 
ReadContinuation(std::unique_ptr<google::protobuf::MessageLite> message)88 void ReadContinuation(std::unique_ptr<google::protobuf::MessageLite> message) {}
89 
WriteContinuation()90 void WriteContinuation() {
91 }
92 
93 // A connection factory that stubs out network requests and overrides the
94 // backoff policy.
95 class TestConnectionFactoryImpl : public ConnectionFactoryImpl {
96  public:
97   TestConnectionFactoryImpl(
98       GetProxyResolvingFactoryCallback get_socket_factory_callback,
99       base::RepeatingClosure finished_callback);
100   ~TestConnectionFactoryImpl() override;
101 
102   void InitializeFactory();
103 
104   // Overridden stubs.
105   void StartConnection() override;
106   void InitHandler(mojo::ScopedDataPipeConsumerHandle receive_stream,
107                    mojo::ScopedDataPipeProducerHandle send_stream) override;
108   std::unique_ptr<net::BackoffEntry> CreateBackoffEntry(
109       const net::BackoffEntry::Policy* const policy) override;
110   std::unique_ptr<ConnectionHandler> CreateConnectionHandler(
111       base::TimeDelta read_timeout,
112       const ConnectionHandler::ProtoReceivedCallback& read_callback,
113       const ConnectionHandler::ProtoSentCallback& write_callback,
114       const ConnectionHandler::ConnectionChangedCallback& connection_callback)
115       override;
116   base::TimeTicks NowTicks() override;
117 
118   // Helpers for verifying connection attempts are made. Connection results
119   // must be consumed.
120   void SetConnectResult(int connect_result);
121   void SetMultipleConnectResults(int connect_result, int num_expected_attempts);
122 
123   // Force a login handshake to be delayed.
124   void SetDelayLogin(bool delay_login);
125 
126   // Simulate a socket error.
127   void SetSocketError();
128 
tick_clock()129   base::SimpleTestTickClock* tick_clock() { return &tick_clock_; }
130 
131  private:
132   // Clock for controlling delay.
133   base::SimpleTestTickClock tick_clock_;
134   // The result to return on the next connect attempt.
135   int connect_result_;
136   // The number of expected connection attempts;
137   int num_expected_attempts_;
138   // Whether all expected connection attempts have been fulfilled since an
139   // expectation was last set.
140   bool connections_fulfilled_;
141   // Whether to delay a login handshake completion or not.
142   bool delay_login_;
143   // Callback to invoke when all connection attempts have been made.
144   base::RepeatingClosure finished_callback_;
145   // A temporary scoped pointer to make sure we don't leak the handler in the
146   // cases it's never consumed by the ConnectionFactory.
147   std::unique_ptr<FakeConnectionHandler> scoped_handler_;
148   // The current fake connection handler..
149   FakeConnectionHandler* fake_handler_;
150   // Dummy GCM Stats recorder.
151   FakeGCMStatsRecorder dummy_recorder_;
152   // Dummy mojo pipes.
153   mojo::DataPipe receive_pipe_;
154   mojo::DataPipe send_pipe_;
155 };
156 
TestConnectionFactoryImpl(GetProxyResolvingFactoryCallback get_socket_factory_callback,base::RepeatingClosure finished_callback)157 TestConnectionFactoryImpl::TestConnectionFactoryImpl(
158     GetProxyResolvingFactoryCallback get_socket_factory_callback,
159     base::RepeatingClosure finished_callback)
160     : ConnectionFactoryImpl(
161           BuildEndpoints(),
162           net::BackoffEntry::Policy(),
163           get_socket_factory_callback,
164           base::ThreadTaskRunnerHandle::Get(),
165           &dummy_recorder_,
166           network::TestNetworkConnectionTracker::GetInstance()),
167       connect_result_(net::ERR_UNEXPECTED),
168       num_expected_attempts_(0),
169       connections_fulfilled_(true),
170       delay_login_(false),
171       finished_callback_(finished_callback),
172       scoped_handler_(std::make_unique<FakeConnectionHandler>(
173           base::BindRepeating(&ReadContinuation),
174           base::BindRepeating(&WriteContinuation))),
175       fake_handler_(scoped_handler_.get()) {
176   // Set a non-null time.
177   tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1));
178 }
179 
~TestConnectionFactoryImpl()180 TestConnectionFactoryImpl::~TestConnectionFactoryImpl() {
181   EXPECT_EQ(0, num_expected_attempts_);
182 }
183 
StartConnection()184 void TestConnectionFactoryImpl::StartConnection() {
185   ASSERT_GT(num_expected_attempts_, 0);
186   ASSERT_FALSE(GetConnectionHandler()->CanSendMessage());
187   std::unique_ptr<mcs_proto::LoginRequest> request(BuildLoginRequest(0, 0, ""));
188   GetConnectionHandler()->Init(*request,
189                                std::move(receive_pipe_.consumer_handle),
190                                std::move(send_pipe_.producer_handle));
191   OnConnectDone(connect_result_, net::IPEndPoint(), net::IPEndPoint(),
192                 mojo::ScopedDataPipeConsumerHandle(),
193                 mojo::ScopedDataPipeProducerHandle());
194   if (!NextRetryAttempt().is_null()) {
195     // Advance the time to the next retry time.
196     base::TimeDelta time_till_retry =
197         NextRetryAttempt() - tick_clock_.NowTicks();
198     tick_clock_.Advance(time_till_retry);
199   }
200   --num_expected_attempts_;
201   if (num_expected_attempts_ == 0) {
202     connect_result_ = net::ERR_UNEXPECTED;
203     connections_fulfilled_ = true;
204     finished_callback_.Run();
205   }
206 }
207 
InitHandler(mojo::ScopedDataPipeConsumerHandle receive_stream,mojo::ScopedDataPipeProducerHandle send_stream)208 void TestConnectionFactoryImpl::InitHandler(
209     mojo::ScopedDataPipeConsumerHandle receive_stream,
210     mojo::ScopedDataPipeProducerHandle send_stream) {
211   EXPECT_NE(connect_result_, net::ERR_UNEXPECTED);
212   if (!delay_login_)
213     ConnectionHandlerCallback(net::OK);
214 }
215 
216 std::unique_ptr<net::BackoffEntry>
CreateBackoffEntry(const net::BackoffEntry::Policy * const policy)217 TestConnectionFactoryImpl::CreateBackoffEntry(
218     const net::BackoffEntry::Policy* const policy) {
219   return std::make_unique<net::BackoffEntry>(&kTestBackoffPolicy, &tick_clock_);
220 }
221 
222 std::unique_ptr<ConnectionHandler>
CreateConnectionHandler(base::TimeDelta read_timeout,const ConnectionHandler::ProtoReceivedCallback & read_callback,const ConnectionHandler::ProtoSentCallback & write_callback,const ConnectionHandler::ConnectionChangedCallback & connection_callback)223 TestConnectionFactoryImpl::CreateConnectionHandler(
224     base::TimeDelta read_timeout,
225     const ConnectionHandler::ProtoReceivedCallback& read_callback,
226     const ConnectionHandler::ProtoSentCallback& write_callback,
227     const ConnectionHandler::ConnectionChangedCallback& connection_callback) {
228   return std::move(scoped_handler_);
229 }
230 
NowTicks()231 base::TimeTicks TestConnectionFactoryImpl::NowTicks() {
232   return tick_clock_.NowTicks();
233 }
234 
SetConnectResult(int connect_result)235 void TestConnectionFactoryImpl::SetConnectResult(int connect_result) {
236   DCHECK_NE(connect_result, net::ERR_UNEXPECTED);
237   ASSERT_EQ(0, num_expected_attempts_);
238   connections_fulfilled_ = false;
239   connect_result_ = connect_result;
240   num_expected_attempts_ = 1;
241   fake_handler_->ExpectOutgoingMessage(
242       MCSMessage(kLoginRequestTag, BuildLoginRequest(0, 0, "")));
243 }
244 
SetMultipleConnectResults(int connect_result,int num_expected_attempts)245 void TestConnectionFactoryImpl::SetMultipleConnectResults(
246     int connect_result,
247     int num_expected_attempts) {
248   DCHECK_NE(connect_result, net::ERR_UNEXPECTED);
249   DCHECK_GT(num_expected_attempts, 0);
250   ASSERT_EQ(0, num_expected_attempts_);
251   connections_fulfilled_ = false;
252   connect_result_ = connect_result;
253   num_expected_attempts_ = num_expected_attempts;
254   for (int i = 0 ; i < num_expected_attempts; ++i) {
255     fake_handler_->ExpectOutgoingMessage(
256         MCSMessage(kLoginRequestTag, BuildLoginRequest(0, 0, "")));
257   }
258 }
259 
SetDelayLogin(bool delay_login)260 void TestConnectionFactoryImpl::SetDelayLogin(bool delay_login) {
261   delay_login_ = delay_login;
262   fake_handler_->set_fail_login(delay_login_);
263 }
264 
SetSocketError()265 void TestConnectionFactoryImpl::SetSocketError() {
266   fake_handler_->set_had_error(true);
267 }
268 
269 }  // namespace
270 
271 class ConnectionFactoryImplTest
272     : public testing::Test,
273       public ConnectionFactory::ConnectionListener {
274  public:
275   ConnectionFactoryImplTest();
276   ~ConnectionFactoryImplTest() override;
277 
factory()278   TestConnectionFactoryImpl* factory() { return &factory_; }
connected_server()279   GURL& connected_server() { return connected_server_; }
280 
281   void WaitForConnections();
282 
283   // ConnectionFactory::ConnectionListener
284   void OnConnected(const GURL& current_server,
285                    const net::IPEndPoint& ip_endpoint) override;
286   void OnDisconnected() override;
287 
288   // Get the client events recorded by the event tracker.
289   const google::protobuf::RepeatedPtrField<mcs_proto::ClientEvent>
GetClientEvents()290   GetClientEvents() {
291     mcs_proto::LoginRequest login_request;
292     factory()->event_tracker_.WriteToLoginRequest(&login_request);
293     return login_request.client_event();
294   }
295 
GetRunLoop()296   base::RunLoop* GetRunLoop() { return run_loop_.get(); }
297 
298  private:
GetProxyResolvingSocketFactory(mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory> receiver)299   void GetProxyResolvingSocketFactory(
300       mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory>
301           receiver) {
302     network_context_->CreateProxyResolvingSocketFactory(std::move(receiver));
303   }
304   void ConnectionsComplete();
305 
306   std::unique_ptr<network::TestNetworkConnectionTracker>
307       network_connection_tracker_;
308   base::test::TaskEnvironment task_environment_;
309   TestConnectionFactoryImpl factory_;
310   std::unique_ptr<base::RunLoop> run_loop_;
311 
312   GURL connected_server_;
313   std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
314   std::unique_ptr<network::NetworkService> network_service_;
315   mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
316   std::unique_ptr<network::NetworkContext> network_context_;
317 };
318 
ConnectionFactoryImplTest()319 ConnectionFactoryImplTest::ConnectionFactoryImplTest()
320     : network_connection_tracker_(
321           network::TestNetworkConnectionTracker::CreateInstance()),
322       task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
323       factory_(
324           base::BindRepeating(
325               &ConnectionFactoryImplTest::GetProxyResolvingSocketFactory,
326               base::Unretained(this)),
327           base::BindRepeating(&ConnectionFactoryImplTest::ConnectionsComplete,
328                               base::Unretained(this))),
329       run_loop_(new base::RunLoop()),
330       network_change_notifier_(
331           net::NetworkChangeNotifier::CreateMockIfNeeded()),
332       network_service_(network::NetworkService::CreateForTesting()) {
333   network::mojom::NetworkContextParamsPtr params =
334       network::mojom::NetworkContextParams::New();
335   // Use a dummy CertVerifier that always passes cert verification, since
336   // these unittests don't need to test CertVerifier behavior.
337   params->cert_verifier_params =
338       network::FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
339   // Use a fixed proxy config, to avoid dependencies on local network
340   // configuration.
341   params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();
342   network_context_ = std::make_unique<network::NetworkContext>(
343       network_service_.get(),
344       network_context_remote_.BindNewPipeAndPassReceiver(), std::move(params));
345   factory()->SetConnectionListener(this);
346   factory()->Initialize(ConnectionFactory::BuildLoginRequestCallback(),
347                         ConnectionHandler::ProtoReceivedCallback(),
348                         ConnectionHandler::ProtoSentCallback());
349 }
~ConnectionFactoryImplTest()350 ConnectionFactoryImplTest::~ConnectionFactoryImplTest() {}
351 
WaitForConnections()352 void ConnectionFactoryImplTest::WaitForConnections() {
353   run_loop_->Run();
354   run_loop_.reset(new base::RunLoop());
355 }
356 
ConnectionsComplete()357 void ConnectionFactoryImplTest::ConnectionsComplete() {
358   if (!run_loop_)
359     return;
360   run_loop_->Quit();
361 }
362 
OnConnected(const GURL & current_server,const net::IPEndPoint & ip_endpoint)363 void ConnectionFactoryImplTest::OnConnected(
364     const GURL& current_server,
365     const net::IPEndPoint& ip_endpoint) {
366   connected_server_ = current_server;
367 }
368 
OnDisconnected()369 void ConnectionFactoryImplTest::OnDisconnected() {
370   connected_server_ = GURL();
371 }
372 
373 // Verify building a connection handler works.
TEST_F(ConnectionFactoryImplTest,Initialize)374 TEST_F(ConnectionFactoryImplTest, Initialize) {
375   ASSERT_FALSE(factory()->GetConnectionHandler());
376   EXPECT_FALSE(factory()->IsEndpointReachable());
377   EXPECT_FALSE(connected_server().is_valid());
378 }
379 
380 // An initial successful connection should not result in backoff.
TEST_F(ConnectionFactoryImplTest,ConnectSuccess)381 TEST_F(ConnectionFactoryImplTest, ConnectSuccess) {
382   factory()->SetConnectResult(net::OK);
383   factory()->Connect();
384   ASSERT_TRUE(factory()->GetConnectionHandler());
385   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
386   EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]);
387   EXPECT_TRUE(factory()->IsEndpointReachable());
388   EXPECT_TRUE(connected_server().is_valid());
389 }
390 
391 // A connection failure should result in backoff, and attempting the fallback
392 // endpoint next.
TEST_F(ConnectionFactoryImplTest,ConnectFail)393 TEST_F(ConnectionFactoryImplTest, ConnectFail) {
394   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
395   factory()->Connect();
396   EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
397   EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]);
398   EXPECT_FALSE(factory()->IsEndpointReachable());
399   EXPECT_FALSE(connected_server().is_valid());
400 }
401 
402 // A connection success after a failure should reset backoff.
TEST_F(ConnectionFactoryImplTest,FailThenSucceed)403 TEST_F(ConnectionFactoryImplTest, FailThenSucceed) {
404   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
405   base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
406   factory()->Connect();
407   WaitForConnections();
408   EXPECT_FALSE(factory()->IsEndpointReachable());
409   EXPECT_FALSE(connected_server().is_valid());
410   base::TimeTicks retry_time = factory()->NextRetryAttempt();
411   EXPECT_FALSE(retry_time.is_null());
412   EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1));
413   factory()->SetConnectResult(net::OK);
414   WaitForConnections();
415   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
416   EXPECT_TRUE(factory()->IsEndpointReachable());
417   EXPECT_TRUE(connected_server().is_valid());
418 }
419 
420 // Multiple connection failures should retry with an exponentially increasing
421 // backoff, then reset on success.
TEST_F(ConnectionFactoryImplTest,MultipleFailuresThenSucceed)422 TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
423   const int kNumAttempts = 5;
424   factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED,
425                                        kNumAttempts);
426 
427   base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
428   factory()->Connect();
429   WaitForConnections();
430   EXPECT_FALSE(factory()->IsEndpointReachable());
431   EXPECT_FALSE(connected_server().is_valid());
432   base::TimeTicks retry_time = factory()->NextRetryAttempt();
433   EXPECT_FALSE(retry_time.is_null());
434   EXPECT_GE((retry_time - connect_time).InMilliseconds(),
435             CalculateBackoff(kNumAttempts));
436 
437   // There should be one failed client event for each failed connection.
438   const auto client_events = GetClientEvents();
439   ASSERT_EQ(kNumAttempts, client_events.size());
440 
441   for (const auto& client_event : client_events) {
442     EXPECT_EQ(mcs_proto::ClientEvent::FAILED_CONNECTION, client_event.type());
443     EXPECT_EQ(net::ERR_CONNECTION_FAILED, client_event.error_code());
444   }
445 
446   factory()->SetConnectResult(net::OK);
447   WaitForConnections();
448   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
449   EXPECT_TRUE(factory()->IsEndpointReachable());
450   EXPECT_TRUE(connected_server().is_valid());
451 
452   // Old client events should have been reset after the successful connection.
453   const auto new_client_events = GetClientEvents();
454   ASSERT_EQ(0, new_client_events.size());
455 }
456 
457 // Network change events should trigger canary connections.
TEST_F(ConnectionFactoryImplTest,FailThenNetworkChangeEvent)458 TEST_F(ConnectionFactoryImplTest, FailThenNetworkChangeEvent) {
459   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
460   factory()->Connect();
461   WaitForConnections();
462   base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
463   EXPECT_FALSE(initial_backoff.is_null());
464 
465   factory()->SetConnectResult(net::ERR_FAILED);
466   factory()->OnConnectionChanged(
467       network::mojom::ConnectionType::CONNECTION_WIFI);
468   WaitForConnections();
469 
470   // Backoff should increase.
471   base::TimeTicks next_backoff = factory()->NextRetryAttempt();
472   EXPECT_GT(next_backoff, initial_backoff);
473   EXPECT_FALSE(factory()->IsEndpointReachable());
474 }
475 
476 // Verify that we reconnect even if a canary succeeded then disconnected while
477 // a backoff was pending.
TEST_F(ConnectionFactoryImplTest,CanarySucceedsThenDisconnects)478 TEST_F(ConnectionFactoryImplTest, CanarySucceedsThenDisconnects) {
479   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
480   factory()->Connect();
481   WaitForConnections();
482   base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
483   EXPECT_FALSE(initial_backoff.is_null());
484 
485   factory()->SetConnectResult(net::OK);
486   factory()->OnConnectionChanged(
487       network::mojom::ConnectionType::CONNECTION_ETHERNET);
488   WaitForConnections();
489   EXPECT_TRUE(factory()->IsEndpointReachable());
490   EXPECT_TRUE(connected_server().is_valid());
491 
492   factory()->SetConnectResult(net::OK);
493   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
494   EXPECT_FALSE(factory()->IsEndpointReachable());
495   EXPECT_FALSE(connected_server().is_valid());
496   WaitForConnections();
497   EXPECT_TRUE(factory()->IsEndpointReachable());
498   EXPECT_TRUE(connected_server().is_valid());
499 }
500 
501 // Verify that if a canary connects, but hasn't finished the handshake, a
502 // pending backoff attempt doesn't interrupt the connection.
TEST_F(ConnectionFactoryImplTest,CanarySucceedsRetryDuringLogin)503 TEST_F(ConnectionFactoryImplTest, CanarySucceedsRetryDuringLogin) {
504   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
505   factory()->Connect();
506   WaitForConnections();
507   base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
508   EXPECT_FALSE(initial_backoff.is_null());
509 
510   factory()->SetDelayLogin(true);
511   factory()->SetConnectResult(net::OK);
512   factory()->OnConnectionChanged(
513       network::mojom::ConnectionType::CONNECTION_WIFI);
514   WaitForConnections();
515   EXPECT_FALSE(factory()->IsEndpointReachable());
516 
517   // Pump the loop, to ensure the pending backoff retry has no effect.
518   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
519       FROM_HERE, GetRunLoop()->QuitWhenIdleClosure(),
520       base::TimeDelta::FromMilliseconds(1));
521   WaitForConnections();
522 }
523 
524 // Fail after successful connection via signal reset.
TEST_F(ConnectionFactoryImplTest,FailViaSignalReset)525 TEST_F(ConnectionFactoryImplTest, FailViaSignalReset) {
526   factory()->SetConnectResult(net::OK);
527   factory()->Connect();
528   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
529 
530   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
531   EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
532   EXPECT_FALSE(factory()->IsEndpointReachable());
533 }
534 
TEST_F(ConnectionFactoryImplTest,IgnoreResetWhileConnecting)535 TEST_F(ConnectionFactoryImplTest, IgnoreResetWhileConnecting) {
536   factory()->SetConnectResult(net::OK);
537   factory()->Connect();
538   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
539 
540   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
541   base::TimeTicks retry_time = factory()->NextRetryAttempt();
542   EXPECT_FALSE(retry_time.is_null());
543   EXPECT_FALSE(factory()->IsEndpointReachable());
544 
545   const int kNumAttempts = 5;
546   for (int i = 0; i < kNumAttempts; ++i)
547     factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
548   EXPECT_EQ(retry_time, factory()->NextRetryAttempt());
549   EXPECT_FALSE(factory()->IsEndpointReachable());
550 }
551 
552 // Go into backoff due to connection failure. On successful connection, receive
553 // a signal reset. The original backoff should be restored and extended, rather
554 // than a new backoff starting from scratch.
TEST_F(ConnectionFactoryImplTest,SignalResetRestoresBackoff)555 TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
556   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
557   base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
558   factory()->Connect();
559   WaitForConnections();
560   base::TimeTicks retry_time = factory()->NextRetryAttempt();
561   EXPECT_FALSE(retry_time.is_null());
562 
563   factory()->SetConnectResult(net::OK);
564   connect_time = factory()->tick_clock()->NowTicks();
565   WaitForConnections();
566   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
567 
568   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
569   EXPECT_FALSE(factory()->IsEndpointReachable());
570   EXPECT_FALSE(connected_server().is_valid());
571   EXPECT_NE(retry_time, factory()->NextRetryAttempt());
572   retry_time = factory()->NextRetryAttempt();
573   EXPECT_FALSE(retry_time.is_null());
574   EXPECT_GE((retry_time - connect_time).InMilliseconds(),
575             CalculateBackoff(2));
576 
577   factory()->SetConnectResult(net::OK);
578   connect_time = factory()->tick_clock()->NowTicks();
579   factory()->tick_clock()->Advance(
580       factory()->NextRetryAttempt() - connect_time);
581   WaitForConnections();
582   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
583   EXPECT_TRUE(factory()->IsEndpointReachable());
584   EXPECT_TRUE(connected_server().is_valid());
585 
586   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
587   EXPECT_NE(retry_time, factory()->NextRetryAttempt());
588   retry_time = factory()->NextRetryAttempt();
589   EXPECT_FALSE(retry_time.is_null());
590   EXPECT_GE((retry_time - connect_time).InMilliseconds(),
591             CalculateBackoff(3));
592   EXPECT_FALSE(factory()->IsEndpointReachable());
593   EXPECT_FALSE(connected_server().is_valid());
594 }
595 
596 // When the network is disconnected, close the socket and suppress further
597 // connection attempts until the network returns.
598 // Disabled while crbug.com/396687 is being investigated.
TEST_F(ConnectionFactoryImplTest,DISABLED_SuppressConnectWhenNoNetwork)599 TEST_F(ConnectionFactoryImplTest, DISABLED_SuppressConnectWhenNoNetwork) {
600   factory()->SetConnectResult(net::OK);
601   factory()->Connect();
602   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
603   EXPECT_TRUE(factory()->IsEndpointReachable());
604 
605   // Advance clock so the login window reset isn't encountered.
606   factory()->tick_clock()->Advance(base::TimeDelta::FromSeconds(11));
607 
608   // Will trigger reset, but will not attempt a new connection.
609   factory()->OnConnectionChanged(
610       network::mojom::ConnectionType::CONNECTION_NONE);
611   EXPECT_FALSE(factory()->IsEndpointReachable());
612   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
613 
614   // When the network returns, attempt to connect.
615   factory()->SetConnectResult(net::OK);
616   factory()->OnConnectionChanged(network::mojom::ConnectionType::CONNECTION_4G);
617   WaitForConnections();
618 
619   EXPECT_TRUE(factory()->IsEndpointReachable());
620   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
621 }
622 
623 // Receiving a network change event before the initial connection should have
624 // no effect.
TEST_F(ConnectionFactoryImplTest,NetworkChangeBeforeFirstConnection)625 TEST_F(ConnectionFactoryImplTest, NetworkChangeBeforeFirstConnection) {
626   factory()->OnConnectionChanged(network::mojom::ConnectionType::CONNECTION_4G);
627   factory()->SetConnectResult(net::OK);
628   factory()->Connect();
629   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
630   EXPECT_TRUE(factory()->IsEndpointReachable());
631 }
632 
633 // Test that if the client attempts to reconnect while a connection is already
634 // open, we don't crash.
TEST_F(ConnectionFactoryImplTest,ConnectionResetRace)635 TEST_F(ConnectionFactoryImplTest, ConnectionResetRace) {
636   // Initial successful connection.
637   factory()->SetConnectResult(net::OK);
638   factory()->Connect();
639   WaitForConnections();
640   EXPECT_TRUE(factory()->IsEndpointReachable());
641 
642   // Trigger a connection error under the hood.
643   factory()->SetSocketError();
644   EXPECT_FALSE(factory()->IsEndpointReachable());
645 
646   // Now trigger force a re-connection.
647   factory()->SetConnectResult(net::OK);
648   factory()->Connect();
649   WaitForConnections();
650 
651   // Re-connection should succeed.
652   EXPECT_TRUE(factory()->IsEndpointReachable());
653 }
654 
TEST_F(ConnectionFactoryImplTest,MultipleFailuresWrapClientEvents)655 TEST_F(ConnectionFactoryImplTest, MultipleFailuresWrapClientEvents) {
656   const int kNumAttempts = 50;
657   factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED,
658                                        kNumAttempts);
659 
660   factory()->Connect();
661   WaitForConnections();
662 
663   // There should be one failed client event for each failed connection, but
664   // there is a maximum cap of kMaxClientEvents, which is 30. There should also
665   // be a single event which records the events which were discarded.
666   auto client_events = GetClientEvents();
667   ASSERT_EQ(31, client_events.size());
668 
669   bool found_discarded_events = false;
670   for (const auto& client_event : client_events) {
671     if (client_event.type() == mcs_proto::ClientEvent::DISCARDED_EVENTS) {
672       // There should only be one event for discarded events.
673       EXPECT_FALSE(found_discarded_events);
674       found_discarded_events = true;
675       // There should be 50-30=20 discarded events.
676       EXPECT_EQ(20U, client_event.number_discarded_events());
677     } else {
678       EXPECT_EQ(mcs_proto::ClientEvent::FAILED_CONNECTION, client_event.type());
679       EXPECT_EQ(net::ERR_CONNECTION_FAILED, client_event.error_code());
680     }
681   }
682   EXPECT_TRUE(found_discarded_events);
683 
684   factory()->SetConnectResult(net::OK);
685   WaitForConnections();
686   EXPECT_TRUE(factory()->IsEndpointReachable());
687   EXPECT_TRUE(connected_server().is_valid());
688 
689   // Old client events should have been reset after the successful connection.
690   client_events = GetClientEvents();
691   ASSERT_EQ(0, client_events.size());
692 
693   // Test that EndConnectionAttempt doesn't write empty events to the tracker.
694   // There should be 2 events: 1) the successful connection which was previously
695   // established. 2) the unsuccessful connection triggered as a result of the
696   // SOCKET_FAILURE signal. The NETWORK_CHANGE signal should not cause an
697   // additional event since there is no in progress event.
698   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
699   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
700   factory()->SignalConnectionReset(ConnectionFactory::NETWORK_CHANGE);
701   WaitForConnections();
702 
703   client_events = GetClientEvents();
704   ASSERT_EQ(2, client_events.size());
705 }
706 
707 }  // namespace gcm
708