Re-land: C++ readability review
[chromium-blink-merge.git] / google_apis / gcm / engine / connection_factory_impl_unittest.cc
blobed23da9f07e1367a29c9f02e9bdf8ee6c60af54c
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.
5 #include "google_apis/gcm/engine/connection_factory_impl.h"
7 #include <cmath>
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.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"
14 #include "google_apis/gcm/monitoring/fake_gcm_stats_recorder.h"
15 #include "net/base/backoff_entry.h"
16 #include "net/http/http_network_session.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 class Policy;
21 namespace gcm {
22 namespace {
24 const char kMCSEndpoint[] = "http://my.server";
25 const char kMCSEndpoint2[] = "http://my.alt.server";
27 const int kBackoffDelayMs = 1;
28 const int kBackoffMultiplier = 2;
30 // A backoff policy with small enough delays that tests aren't burdened.
31 const net::BackoffEntry::Policy kTestBackoffPolicy = {
32 // Number of initial errors (in sequence) to ignore before applying
33 // exponential back-off rules.
36 // Initial delay for exponential back-off in ms.
37 kBackoffDelayMs,
39 // Factor by which the waiting time will be multiplied.
40 kBackoffMultiplier,
42 // Fuzzing percentage. ex: 10% will spread requests randomly
43 // between 90%-100% of the calculated time.
46 // Maximum amount of time we are willing to delay our request in ms.
47 10,
49 // Time to keep an entry from being discarded even when it
50 // has no significant state, -1 to never discard.
51 -1,
53 // Don't use initial delay unless the last request was an error.
54 false,
57 std::vector<GURL> BuildEndpoints() {
58 std::vector<GURL> endpoints;
59 endpoints.push_back(GURL(kMCSEndpoint));
60 endpoints.push_back(GURL(kMCSEndpoint2));
61 return endpoints;
64 // Helper for calculating total expected exponential backoff delay given an
65 // arbitrary number of failed attempts. See BackoffEntry::CalculateReleaseTime.
66 double CalculateBackoff(int num_attempts) {
67 double delay = kBackoffDelayMs;
68 for (int i = 1; i < num_attempts; ++i) {
69 delay += kBackoffDelayMs * pow(static_cast<double>(kBackoffMultiplier),
70 i - 1);
72 DVLOG(1) << "Expected backoff " << delay << " milliseconds.";
73 return delay;
76 void ReadContinuation(
77 scoped_ptr<google::protobuf::MessageLite> message) {
80 void WriteContinuation() {
83 class TestBackoffEntry : public net::BackoffEntry {
84 public:
85 explicit TestBackoffEntry(base::SimpleTestTickClock* tick_clock);
86 ~TestBackoffEntry() override;
88 base::TimeTicks ImplGetTimeNow() const override;
90 private:
91 base::SimpleTestTickClock* tick_clock_;
94 TestBackoffEntry::TestBackoffEntry(base::SimpleTestTickClock* tick_clock)
95 : BackoffEntry(&kTestBackoffPolicy),
96 tick_clock_(tick_clock) {
99 TestBackoffEntry::~TestBackoffEntry() {}
101 base::TimeTicks TestBackoffEntry::ImplGetTimeNow() const {
102 return tick_clock_->NowTicks();
105 // A connection factory that stubs out network requests and overrides the
106 // backoff policy.
107 class TestConnectionFactoryImpl : public ConnectionFactoryImpl {
108 public:
109 TestConnectionFactoryImpl(const base::Closure& finished_callback);
110 ~TestConnectionFactoryImpl() override;
112 void InitializeFactory();
114 // Overridden stubs.
115 void ConnectImpl() override;
116 void InitHandler() override;
117 scoped_ptr<net::BackoffEntry> CreateBackoffEntry(
118 const net::BackoffEntry::Policy* const policy) override;
119 scoped_ptr<ConnectionHandler> CreateConnectionHandler(
120 base::TimeDelta read_timeout,
121 const ConnectionHandler::ProtoReceivedCallback& read_callback,
122 const ConnectionHandler::ProtoSentCallback& write_callback,
123 const ConnectionHandler::ConnectionChangedCallback& connection_callback)
124 override;
125 base::TimeTicks NowTicks() override;
127 // Helpers for verifying connection attempts are made. Connection results
128 // must be consumed.
129 void SetConnectResult(int connect_result);
130 void SetMultipleConnectResults(int connect_result, int num_expected_attempts);
132 // Force a login handshake to be delayed.
133 void SetDelayLogin(bool delay_login);
135 // Simulate a socket error.
136 void SetSocketError();
138 base::SimpleTestTickClock* tick_clock() { return &tick_clock_; }
140 private:
141 // Clock for controlling delay.
142 base::SimpleTestTickClock tick_clock_;
143 // The result to return on the next connect attempt.
144 int connect_result_;
145 // The number of expected connection attempts;
146 int num_expected_attempts_;
147 // Whether all expected connection attempts have been fulfilled since an
148 // expectation was last set.
149 bool connections_fulfilled_;
150 // Whether to delay a login handshake completion or not.
151 bool delay_login_;
152 // Callback to invoke when all connection attempts have been made.
153 base::Closure finished_callback_;
154 // A temporary scoped pointer to make sure we don't leak the handler in the
155 // cases it's never consumed by the ConnectionFactory.
156 scoped_ptr<FakeConnectionHandler> scoped_handler_;
157 // The current fake connection handler..
158 FakeConnectionHandler* fake_handler_;
159 // Dummy GCM Stats recorder.
160 FakeGCMStatsRecorder dummy_recorder_;
163 TestConnectionFactoryImpl::TestConnectionFactoryImpl(
164 const base::Closure& finished_callback)
165 : ConnectionFactoryImpl(BuildEndpoints(),
166 net::BackoffEntry::Policy(),
167 NULL,
168 NULL,
169 NULL,
170 &dummy_recorder_),
171 connect_result_(net::ERR_UNEXPECTED),
172 num_expected_attempts_(0),
173 connections_fulfilled_(true),
174 delay_login_(false),
175 finished_callback_(finished_callback),
176 scoped_handler_(
177 new FakeConnectionHandler(base::Bind(&ReadContinuation),
178 base::Bind(&WriteContinuation))),
179 fake_handler_(scoped_handler_.get()) {
180 // Set a non-null time.
181 tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1));
184 TestConnectionFactoryImpl::~TestConnectionFactoryImpl() {
185 EXPECT_EQ(0, num_expected_attempts_);
188 void TestConnectionFactoryImpl::ConnectImpl() {
189 ASSERT_GT(num_expected_attempts_, 0);
190 ASSERT_FALSE(GetConnectionHandler()->CanSendMessage());
191 scoped_ptr<mcs_proto::LoginRequest> request(BuildLoginRequest(0, 0, ""));
192 GetConnectionHandler()->Init(*request, NULL);
193 OnConnectDone(connect_result_);
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);
200 --num_expected_attempts_;
201 if (num_expected_attempts_ == 0) {
202 connect_result_ = net::ERR_UNEXPECTED;
203 connections_fulfilled_ = true;
204 finished_callback_.Run();
208 void TestConnectionFactoryImpl::InitHandler() {
209 EXPECT_NE(connect_result_, net::ERR_UNEXPECTED);
210 if (!delay_login_)
211 ConnectionHandlerCallback(net::OK);
214 scoped_ptr<net::BackoffEntry> TestConnectionFactoryImpl::CreateBackoffEntry(
215 const net::BackoffEntry::Policy* const policy) {
216 return scoped_ptr<net::BackoffEntry>(new TestBackoffEntry(&tick_clock_));
219 scoped_ptr<ConnectionHandler>
220 TestConnectionFactoryImpl::CreateConnectionHandler(
221 base::TimeDelta read_timeout,
222 const ConnectionHandler::ProtoReceivedCallback& read_callback,
223 const ConnectionHandler::ProtoSentCallback& write_callback,
224 const ConnectionHandler::ConnectionChangedCallback& connection_callback) {
225 return scoped_handler_.Pass();
228 base::TimeTicks TestConnectionFactoryImpl::NowTicks() {
229 return tick_clock_.NowTicks();
232 void TestConnectionFactoryImpl::SetConnectResult(int connect_result) {
233 DCHECK_NE(connect_result, net::ERR_UNEXPECTED);
234 ASSERT_EQ(0, num_expected_attempts_);
235 connections_fulfilled_ = false;
236 connect_result_ = connect_result;
237 num_expected_attempts_ = 1;
238 fake_handler_->ExpectOutgoingMessage(
239 MCSMessage(kLoginRequestTag, BuildLoginRequest(0, 0, "")));
242 void TestConnectionFactoryImpl::SetMultipleConnectResults(
243 int connect_result,
244 int num_expected_attempts) {
245 DCHECK_NE(connect_result, net::ERR_UNEXPECTED);
246 DCHECK_GT(num_expected_attempts, 0);
247 ASSERT_EQ(0, num_expected_attempts_);
248 connections_fulfilled_ = false;
249 connect_result_ = connect_result;
250 num_expected_attempts_ = num_expected_attempts;
251 for (int i = 0 ; i < num_expected_attempts; ++i) {
252 fake_handler_->ExpectOutgoingMessage(
253 MCSMessage(kLoginRequestTag, BuildLoginRequest(0, 0, "")));
257 void TestConnectionFactoryImpl::SetDelayLogin(bool delay_login) {
258 delay_login_ = delay_login;
259 fake_handler_->set_fail_login(delay_login_);
262 void TestConnectionFactoryImpl::SetSocketError() {
263 fake_handler_->set_had_error(true);
266 } // namespace
268 class ConnectionFactoryImplTest
269 : public testing::Test,
270 public ConnectionFactory::ConnectionListener {
271 public:
272 ConnectionFactoryImplTest();
273 ~ConnectionFactoryImplTest() override;
275 TestConnectionFactoryImpl* factory() { return &factory_; }
276 GURL& connected_server() { return connected_server_; }
278 void WaitForConnections();
280 // ConnectionFactory::ConnectionListener
281 void OnConnected(const GURL& current_server,
282 const net::IPEndPoint& ip_endpoint) override;
283 void OnDisconnected() override;
285 private:
286 void ConnectionsComplete();
288 TestConnectionFactoryImpl factory_;
289 base::MessageLoop message_loop_;
290 scoped_ptr<base::RunLoop> run_loop_;
292 GURL connected_server_;
295 ConnectionFactoryImplTest::ConnectionFactoryImplTest()
296 : factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete,
297 base::Unretained(this))),
298 run_loop_(new base::RunLoop()) {
299 factory()->SetConnectionListener(this);
300 factory()->Initialize(
301 ConnectionFactory::BuildLoginRequestCallback(),
302 ConnectionHandler::ProtoReceivedCallback(),
303 ConnectionHandler::ProtoSentCallback());
305 ConnectionFactoryImplTest::~ConnectionFactoryImplTest() {}
307 void ConnectionFactoryImplTest::WaitForConnections() {
308 run_loop_->Run();
309 run_loop_.reset(new base::RunLoop());
312 void ConnectionFactoryImplTest::ConnectionsComplete() {
313 if (!run_loop_)
314 return;
315 run_loop_->Quit();
318 void ConnectionFactoryImplTest::OnConnected(
319 const GURL& current_server,
320 const net::IPEndPoint& ip_endpoint) {
321 connected_server_ = current_server;
324 void ConnectionFactoryImplTest::OnDisconnected() {
325 connected_server_ = GURL();
328 // Verify building a connection handler works.
329 TEST_F(ConnectionFactoryImplTest, Initialize) {
330 ASSERT_FALSE(factory()->GetConnectionHandler());
331 EXPECT_FALSE(factory()->IsEndpointReachable());
332 EXPECT_FALSE(connected_server().is_valid());
335 // An initial successful connection should not result in backoff.
336 TEST_F(ConnectionFactoryImplTest, ConnectSuccess) {
337 factory()->SetConnectResult(net::OK);
338 factory()->Connect();
339 ASSERT_TRUE(factory()->GetConnectionHandler());
340 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
341 EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]);
342 EXPECT_TRUE(factory()->IsEndpointReachable());
343 EXPECT_TRUE(connected_server().is_valid());
346 // A connection failure should result in backoff, and attempting the fallback
347 // endpoint next.
348 TEST_F(ConnectionFactoryImplTest, ConnectFail) {
349 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
350 factory()->Connect();
351 EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
352 EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]);
353 EXPECT_FALSE(factory()->IsEndpointReachable());
354 EXPECT_FALSE(connected_server().is_valid());
357 // A connection success after a failure should reset backoff.
358 TEST_F(ConnectionFactoryImplTest, FailThenSucceed) {
359 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
360 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
361 factory()->Connect();
362 WaitForConnections();
363 EXPECT_FALSE(factory()->IsEndpointReachable());
364 EXPECT_FALSE(connected_server().is_valid());
365 base::TimeTicks retry_time = factory()->NextRetryAttempt();
366 EXPECT_FALSE(retry_time.is_null());
367 EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1));
368 factory()->SetConnectResult(net::OK);
369 WaitForConnections();
370 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
371 EXPECT_TRUE(factory()->IsEndpointReachable());
372 EXPECT_TRUE(connected_server().is_valid());
375 // Multiple connection failures should retry with an exponentially increasing
376 // backoff, then reset on success.
377 TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
378 const int kNumAttempts = 5;
379 factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED,
380 kNumAttempts);
382 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
383 factory()->Connect();
384 WaitForConnections();
385 EXPECT_FALSE(factory()->IsEndpointReachable());
386 EXPECT_FALSE(connected_server().is_valid());
387 base::TimeTicks retry_time = factory()->NextRetryAttempt();
388 EXPECT_FALSE(retry_time.is_null());
389 EXPECT_GE((retry_time - connect_time).InMilliseconds(),
390 CalculateBackoff(kNumAttempts));
392 factory()->SetConnectResult(net::OK);
393 WaitForConnections();
394 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
395 EXPECT_TRUE(factory()->IsEndpointReachable());
396 EXPECT_TRUE(connected_server().is_valid());
399 // Network change events should trigger canary connections.
400 TEST_F(ConnectionFactoryImplTest, FailThenNetworkChangeEvent) {
401 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
402 factory()->Connect();
403 WaitForConnections();
404 base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
405 EXPECT_FALSE(initial_backoff.is_null());
407 factory()->SetConnectResult(net::ERR_FAILED);
408 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_WIFI);
409 WaitForConnections();
411 // Backoff should increase.
412 base::TimeTicks next_backoff = factory()->NextRetryAttempt();
413 EXPECT_GT(next_backoff, initial_backoff);
414 EXPECT_FALSE(factory()->IsEndpointReachable());
417 // Verify that we reconnect even if a canary succeeded then disconnected while
418 // a backoff was pending.
419 TEST_F(ConnectionFactoryImplTest, CanarySucceedsThenDisconnects) {
420 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
421 factory()->Connect();
422 WaitForConnections();
423 base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
424 EXPECT_FALSE(initial_backoff.is_null());
426 factory()->SetConnectResult(net::OK);
427 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
428 WaitForConnections();
429 EXPECT_TRUE(factory()->IsEndpointReachable());
430 EXPECT_TRUE(connected_server().is_valid());
432 factory()->SetConnectResult(net::OK);
433 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
434 EXPECT_FALSE(factory()->IsEndpointReachable());
435 EXPECT_FALSE(connected_server().is_valid());
436 WaitForConnections();
437 EXPECT_TRUE(factory()->IsEndpointReachable());
438 EXPECT_TRUE(connected_server().is_valid());
441 // Verify that if a canary connects, but hasn't finished the handshake, a
442 // pending backoff attempt doesn't interrupt the connection.
443 TEST_F(ConnectionFactoryImplTest, CanarySucceedsRetryDuringLogin) {
444 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
445 factory()->Connect();
446 WaitForConnections();
447 base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
448 EXPECT_FALSE(initial_backoff.is_null());
450 factory()->SetDelayLogin(true);
451 factory()->SetConnectResult(net::OK);
452 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_WIFI);
453 WaitForConnections();
454 EXPECT_FALSE(factory()->IsEndpointReachable());
456 // Pump the loop, to ensure the pending backoff retry has no effect.
457 base::MessageLoop::current()->PostDelayedTask(
458 FROM_HERE,
459 base::MessageLoop::QuitClosure(),
460 base::TimeDelta::FromMilliseconds(1));
461 WaitForConnections();
464 // Fail after successful connection via signal reset.
465 TEST_F(ConnectionFactoryImplTest, FailViaSignalReset) {
466 factory()->SetConnectResult(net::OK);
467 factory()->Connect();
468 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
470 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
471 EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
472 EXPECT_FALSE(factory()->IsEndpointReachable());
475 TEST_F(ConnectionFactoryImplTest, IgnoreResetWhileConnecting) {
476 factory()->SetConnectResult(net::OK);
477 factory()->Connect();
478 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
480 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
481 base::TimeTicks retry_time = factory()->NextRetryAttempt();
482 EXPECT_FALSE(retry_time.is_null());
483 EXPECT_FALSE(factory()->IsEndpointReachable());
485 const int kNumAttempts = 5;
486 for (int i = 0; i < kNumAttempts; ++i)
487 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
488 EXPECT_EQ(retry_time, factory()->NextRetryAttempt());
489 EXPECT_FALSE(factory()->IsEndpointReachable());
492 // Go into backoff due to connection failure. On successful connection, receive
493 // a signal reset. The original backoff should be restored and extended, rather
494 // than a new backoff starting from scratch.
495 TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
496 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
497 base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
498 factory()->Connect();
499 WaitForConnections();
500 base::TimeTicks retry_time = factory()->NextRetryAttempt();
501 EXPECT_FALSE(retry_time.is_null());
503 factory()->SetConnectResult(net::OK);
504 connect_time = factory()->tick_clock()->NowTicks();
505 WaitForConnections();
506 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
508 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
509 EXPECT_FALSE(factory()->IsEndpointReachable());
510 EXPECT_FALSE(connected_server().is_valid());
511 EXPECT_NE(retry_time, factory()->NextRetryAttempt());
512 retry_time = factory()->NextRetryAttempt();
513 EXPECT_FALSE(retry_time.is_null());
514 EXPECT_GE((retry_time - connect_time).InMilliseconds(),
515 CalculateBackoff(2));
517 factory()->SetConnectResult(net::OK);
518 connect_time = factory()->tick_clock()->NowTicks();
519 factory()->tick_clock()->Advance(
520 factory()->NextRetryAttempt() - connect_time);
521 WaitForConnections();
522 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
523 EXPECT_TRUE(factory()->IsEndpointReachable());
524 EXPECT_TRUE(connected_server().is_valid());
526 factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
527 EXPECT_NE(retry_time, factory()->NextRetryAttempt());
528 retry_time = factory()->NextRetryAttempt();
529 EXPECT_FALSE(retry_time.is_null());
530 EXPECT_GE((retry_time - connect_time).InMilliseconds(),
531 CalculateBackoff(3));
532 EXPECT_FALSE(factory()->IsEndpointReachable());
533 EXPECT_FALSE(connected_server().is_valid());
536 // When the network is disconnected, close the socket and suppress further
537 // connection attempts until the network returns.
538 // Disabled while crbug.com/396687 is being investigated.
539 TEST_F(ConnectionFactoryImplTest, DISABLED_SuppressConnectWhenNoNetwork) {
540 factory()->SetConnectResult(net::OK);
541 factory()->Connect();
542 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
543 EXPECT_TRUE(factory()->IsEndpointReachable());
545 // Advance clock so the login window reset isn't encountered.
546 factory()->tick_clock()->Advance(base::TimeDelta::FromSeconds(11));
548 // Will trigger reset, but will not attempt a new connection.
549 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
550 EXPECT_FALSE(factory()->IsEndpointReachable());
551 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
553 // When the network returns, attempt to connect.
554 factory()->SetConnectResult(net::OK);
555 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_4G);
556 WaitForConnections();
558 EXPECT_TRUE(factory()->IsEndpointReachable());
559 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
562 // Receiving a network change event before the initial connection should have
563 // no effect.
564 TEST_F(ConnectionFactoryImplTest, NetworkChangeBeforeFirstConnection) {
565 factory()->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_4G);
566 factory()->SetConnectResult(net::OK);
567 factory()->Connect();
568 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
569 EXPECT_TRUE(factory()->IsEndpointReachable());
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());
581 // Trigger a connection error under the hood.
582 factory()->SetSocketError();
583 EXPECT_FALSE(factory()->IsEndpointReachable());
585 // Now trigger force a re-connection.
586 factory()->SetConnectResult(net::OK);
587 factory()->Connect();
588 WaitForConnections();
590 // Re-connection should succeed.
591 EXPECT_TRUE(factory()->IsEndpointReachable());
594 } // namespace gcm