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

Unified Diff: google_apis/gcm/engine/connection_factory_impl_unittest.cc

Issue 213693002: [GCM] Add support for canary connection attempts (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refactor tests Created 6 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 side-by-side diff with in-line comments
Download patch
Index: google_apis/gcm/engine/connection_factory_impl_unittest.cc
diff --git a/google_apis/gcm/engine/connection_factory_impl_unittest.cc b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
index eebe14a9b0ad444e44f67975ec13a57293606f84..4983ea9d54b3dfa6ca85f1277eb73c37309a7a93 100644
--- a/google_apis/gcm/engine/connection_factory_impl_unittest.cc
+++ b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
@@ -9,6 +9,8 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/simple_test_tick_clock.h"
+#include "google_apis/gcm/base/mcs_util.h"
+#include "google_apis/gcm/engine/fake_connection_handler.h"
#include "net/base/backoff_entry.h"
#include "net/http/http_network_session.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -70,15 +72,11 @@ double CalculateBackoff(int num_attempts) {
return delay;
}
-// Helper methods that should never actually be called due to real connections
-// being stubbed out.
void ReadContinuation(
scoped_ptr<google::protobuf::MessageLite> message) {
- ADD_FAILURE();
}
void WriteContinuation() {
- ADD_FAILURE();
}
class TestBackoffEntry : public net::BackoffEntry {
@@ -110,11 +108,19 @@ class TestConnectionFactoryImpl : public ConnectionFactoryImpl {
TestConnectionFactoryImpl(const base::Closure& finished_callback);
virtual ~TestConnectionFactoryImpl();
+ void InitializeFactory();
+
// Overridden stubs.
virtual void ConnectImpl() OVERRIDE;
virtual void InitHandler() OVERRIDE;
virtual scoped_ptr<net::BackoffEntry> CreateBackoffEntry(
const net::BackoffEntry::Policy* const policy) OVERRIDE;
+ virtual scoped_ptr<ConnectionHandler> CreateConnectionHandler(
+ base::TimeDelta read_timeout,
+ const ConnectionHandler::ProtoReceivedCallback& read_callback,
+ const ConnectionHandler::ProtoSentCallback& write_callback,
+ const ConnectionHandler::ConnectionChangedCallback& connection_callback)
+ OVERRIDE;
virtual base::TimeTicks NowTicks() OVERRIDE;
// Helpers for verifying connection attempts are made. Connection results
@@ -136,6 +142,8 @@ class TestConnectionFactoryImpl : public ConnectionFactoryImpl {
bool connections_fulfilled_;
// Callback to invoke when all connection attempts have been made.
base::Closure finished_callback_;
+ // The current fake connection handler..
+ FakeConnectionHandler* fake_handler_;
};
TestConnectionFactoryImpl::TestConnectionFactoryImpl(
@@ -147,7 +155,8 @@ TestConnectionFactoryImpl::TestConnectionFactoryImpl(
connect_result_(net::ERR_UNEXPECTED),
num_expected_attempts_(0),
connections_fulfilled_(true),
- finished_callback_(finished_callback) {
+ finished_callback_(finished_callback),
+ fake_handler_(NULL) {
// Set a non-null time.
tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1));
}
@@ -158,7 +167,8 @@ TestConnectionFactoryImpl::~TestConnectionFactoryImpl() {
void TestConnectionFactoryImpl::ConnectImpl() {
ASSERT_GT(num_expected_attempts_, 0);
-
+ scoped_ptr<mcs_proto::LoginRequest> request(BuildLoginRequest(0, 0, ""));
+ GetConnectionHandler()->Init(*request, NULL);
OnConnectDone(connect_result_);
if (!NextRetryAttempt().is_null()) {
// Advance the time to the next retry time.
@@ -184,6 +194,18 @@ scoped_ptr<net::BackoffEntry> TestConnectionFactoryImpl::CreateBackoffEntry(
return scoped_ptr<net::BackoffEntry>(new TestBackoffEntry(&tick_clock_));
}
+scoped_ptr<ConnectionHandler>
+TestConnectionFactoryImpl::CreateConnectionHandler(
+ base::TimeDelta read_timeout,
+ const ConnectionHandler::ProtoReceivedCallback& read_callback,
+ const ConnectionHandler::ProtoSentCallback& write_callback,
+ const ConnectionHandler::ConnectionChangedCallback& connection_callback) {
+ fake_handler_ = new FakeConnectionHandler(
+ base::Bind(&ReadContinuation),
+ base::Bind(&WriteContinuation));
+ return make_scoped_ptr<ConnectionHandler>(fake_handler_);
+}
+
base::TimeTicks TestConnectionFactoryImpl::NowTicks() {
return tick_clock_.NowTicks();
}
@@ -194,6 +216,10 @@ void TestConnectionFactoryImpl::SetConnectResult(int connect_result) {
connections_fulfilled_ = false;
connect_result_ = connect_result;
num_expected_attempts_ = 1;
+ fake_handler_->ExpectOutgoingMessage(
+ MCSMessage(kLoginRequestTag,
+ BuildLoginRequest(0, 0, "").PassAs<
+ const google::protobuf::MessageLite>()));
}
void TestConnectionFactoryImpl::SetMultipleConnectResults(
@@ -205,6 +231,12 @@ void TestConnectionFactoryImpl::SetMultipleConnectResults(
connections_fulfilled_ = false;
connect_result_ = connect_result;
num_expected_attempts_ = num_expected_attempts;
+ for (int i = 0 ; i < num_expected_attempts; ++i) {
+ fake_handler_->ExpectOutgoingMessage(
+ MCSMessage(kLoginRequestTag,
+ BuildLoginRequest(0, 0, "").PassAs<
+ const google::protobuf::MessageLite>()));
+ }
}
class ConnectionFactoryImplTest : public testing::Test {
@@ -227,7 +259,12 @@ class ConnectionFactoryImplTest : public testing::Test {
ConnectionFactoryImplTest::ConnectionFactoryImplTest()
: factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete,
base::Unretained(this))),
- run_loop_(new base::RunLoop()) {}
+ run_loop_(new base::RunLoop()) {
+ factory()->Initialize(
+ ConnectionFactory::BuildLoginRequestCallback(),
+ ConnectionHandler::ProtoReceivedCallback(),
+ ConnectionHandler::ProtoSentCallback());
+}
ConnectionFactoryImplTest::~ConnectionFactoryImplTest() {}
void ConnectionFactoryImplTest::WaitForConnections() {
@@ -243,11 +280,6 @@ void ConnectionFactoryImplTest::ConnectionsComplete() {
// Verify building a connection handler works.
TEST_F(ConnectionFactoryImplTest, Initialize) {
- EXPECT_FALSE(factory()->IsEndpointReachable());
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- base::Bind(&ReadContinuation),
- base::Bind(&WriteContinuation));
ConnectionHandler* handler = factory()->GetConnectionHandler();
ASSERT_TRUE(handler);
EXPECT_FALSE(factory()->IsEndpointReachable());
@@ -255,54 +287,42 @@ TEST_F(ConnectionFactoryImplTest, Initialize) {
// An initial successful connection should not result in backoff.
TEST_F(ConnectionFactoryImplTest, ConnectSuccess) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::OK);
factory()->Connect();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]);
+ EXPECT_TRUE(factory()->IsEndpointReachable());
}
// A connection failure should result in backoff, and attempting the fallback
// endpoint next.
TEST_F(ConnectionFactoryImplTest, ConnectFail) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
factory()->Connect();
EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]);
+ EXPECT_FALSE(factory()->IsEndpointReachable());
}
// A connection success after a failure should reset backoff.
TEST_F(ConnectionFactoryImplTest, FailThenSucceed) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
factory()->Connect();
WaitForConnections();
+ EXPECT_FALSE(factory()->IsEndpointReachable());
base::TimeTicks retry_time = factory()->NextRetryAttempt();
EXPECT_FALSE(retry_time.is_null());
EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1));
factory()->SetConnectResult(net::OK);
WaitForConnections();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+ EXPECT_TRUE(factory()->IsEndpointReachable());
}
// Multiple connection failures should retry with an exponentially increasing
// backoff, then reset on success.
TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
const int kNumAttempts = 5;
factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED,
@@ -311,6 +331,7 @@ TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
factory()->Connect();
WaitForConnections();
+ EXPECT_FALSE(factory()->IsEndpointReachable());
base::TimeTicks retry_time = factory()->NextRetryAttempt();
EXPECT_FALSE(retry_time.is_null());
EXPECT_GE((retry_time - connect_time).InMilliseconds(),
@@ -319,59 +340,80 @@ TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
factory()->SetConnectResult(net::OK);
WaitForConnections();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+ EXPECT_TRUE(factory()->IsEndpointReachable());
}
-// IP events should reset backoff.
+// IP events should trigger canary connections.
TEST_F(ConnectionFactoryImplTest, FailThenIPEvent) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
factory()->Connect();
WaitForConnections();
- EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
+ base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
+ EXPECT_FALSE(initial_backoff.is_null());
+ factory()->SetConnectResult(net::ERR_FAILED);
factory()->OnIPAddressChanged();
- EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+ WaitForConnections();
+
+ // Backoff should increase.
+ base::TimeTicks next_backoff = factory()->NextRetryAttempt();
+ EXPECT_GT(next_backoff, initial_backoff);
+ EXPECT_FALSE(factory()->IsEndpointReachable());
}
-// Connection type events should reset backoff.
+// Connection type events should trigger canary connections.
TEST_F(ConnectionFactoryImplTest, FailThenConnectionTypeEvent) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
factory()->Connect();
WaitForConnections();
- EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
+ base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
+ EXPECT_FALSE(initial_backoff.is_null());
+ factory()->SetConnectResult(net::ERR_FAILED);
factory()->OnConnectionTypeChanged(
net::NetworkChangeNotifier::CONNECTION_WIFI);
- EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+ WaitForConnections();
+
+ // Backoff should increase.
+ base::TimeTicks next_backoff = factory()->NextRetryAttempt();
+ EXPECT_GT(next_backoff, initial_backoff);
+ EXPECT_FALSE(factory()->IsEndpointReachable());
+}
+
+// Verify that we reconnect even if a canary succeeded then disconnected while
+// a backoff was pending.
+TEST_F(ConnectionFactoryImplTest, CanarySucceedsThenDisconnects) {
+ factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
+ factory()->Connect();
+ WaitForConnections();
+ base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
+ EXPECT_FALSE(initial_backoff.is_null());
+
+ factory()->SetConnectResult(net::OK);
+ factory()->OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::CONNECTION_WIFI);
+ WaitForConnections();
+ EXPECT_TRUE(factory()->IsEndpointReachable());
+
+ factory()->SetConnectResult(net::OK);
+ factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
+ EXPECT_FALSE(factory()->IsEndpointReachable());
+ WaitForConnections();
+ EXPECT_TRUE(factory()->IsEndpointReachable());
}
// Fail after successful connection via signal reset.
TEST_F(ConnectionFactoryImplTest, FailViaSignalReset) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::OK);
factory()->Connect();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
- EXPECT_FALSE(factory()->GetConnectionHandler()->CanSendMessage());
+ EXPECT_FALSE(factory()->IsEndpointReachable());
}
TEST_F(ConnectionFactoryImplTest, IgnoreResetWhileConnecting) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::OK);
factory()->Connect();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
@@ -379,21 +421,19 @@ TEST_F(ConnectionFactoryImplTest, IgnoreResetWhileConnecting) {
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
base::TimeTicks retry_time = factory()->NextRetryAttempt();
EXPECT_FALSE(retry_time.is_null());
+ EXPECT_FALSE(factory()->IsEndpointReachable());
const int kNumAttempts = 5;
for (int i = 0; i < kNumAttempts; ++i)
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
EXPECT_EQ(retry_time, factory()->NextRetryAttempt());
+ EXPECT_FALSE(factory()->IsEndpointReachable());
}
// Go into backoff due to connection failure. On successful connection, receive
// a signal reset. The original backoff should be restored and extended, rather
// than a new backoff starting from scratch.
TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
- factory()->Initialize(
- ConnectionFactory::BuildLoginRequestCallback(),
- ConnectionHandler::ProtoReceivedCallback(),
- ConnectionHandler::ProtoSentCallback());
factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
factory()->Connect();
@@ -407,7 +447,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
- EXPECT_FALSE(factory()->GetConnectionHandler()->CanSendMessage());
+ EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_NE(retry_time, factory()->NextRetryAttempt());
retry_time = factory()->NextRetryAttempt();
EXPECT_FALSE(retry_time.is_null());
@@ -420,6 +460,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
factory()->NextRetryAttempt() - connect_time);
WaitForConnections();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+ EXPECT_TRUE(factory()->IsEndpointReachable());
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
EXPECT_NE(retry_time, factory()->NextRetryAttempt());
@@ -427,6 +468,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
EXPECT_FALSE(retry_time.is_null());
EXPECT_GE((retry_time - connect_time).InMilliseconds(),
CalculateBackoff(3));
+ EXPECT_FALSE(factory()->IsEndpointReachable());
}
} // namespace

Powered by Google App Engine
This is Rietveld 408576698