This source file includes following definitions.
- Initialize
- RequestToken
- InvalidateToken
- Register
- SetMessageReceiver
- BuildUrl
- test_
- last_invalidator_state_
- SetUp
- TearDown
- BuildUrl
- Base64EncodeURLSafe
- Base64DecodeURLSafe
- OnNetworkChannelStateChanged
- OnIncomingMessage
- network_channel
- delegate
- url_fetchers_created_count
- url_fetcher_factory
- CreateURLFetcher
- set_last_echo_token
- get_last_echo_token
- get_last_invalidator_state
- RunLoopUntilIdle
- AddExtraRequestHeader
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_test_util.h"
#include "sync/notifier/gcm_network_channel.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
class TestGCMNetworkChannelDelegate : public GCMNetworkChannelDelegate {
public:
TestGCMNetworkChannelDelegate()
: register_call_count_(0) {}
virtual void Initialize() OVERRIDE {}
virtual void RequestToken(RequestTokenCallback callback) OVERRIDE {
request_token_callback = callback;
}
virtual void InvalidateToken(const std::string& token) OVERRIDE {
invalidated_token = token;
}
virtual void Register(RegisterCallback callback) OVERRIDE {
++register_call_count_;
register_callback = callback;
}
virtual void SetMessageReceiver(MessageCallback callback) OVERRIDE {
message_callback = callback;
}
RequestTokenCallback request_token_callback;
std::string invalidated_token;
RegisterCallback register_callback;
int register_call_count_;
MessageCallback message_callback;
};
const net::BackoffEntry::Policy kTestBackoffPolicy = {
5,
2000,
2,
0.2,
1000 * 3600 * 4,
-1,
false,
};
class TestGCMNetworkChannel : public GCMNetworkChannel {
public:
TestGCMNetworkChannel(
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_ptr<GCMNetworkChannelDelegate> delegate)
: GCMNetworkChannel(request_context_getter, delegate.Pass()) {
ResetRegisterBackoffEntryForTest(&kTestBackoffPolicy);
}
protected:
virtual GURL BuildUrl(const std::string& registration_id) OVERRIDE {
return GURL("http://test.url.com");
}
};
class GCMNetworkChannelTest;
class TestNetworkChannelURLFetcher : public net::FakeURLFetcher {
public:
TestNetworkChannelURLFetcher(GCMNetworkChannelTest* test,
const GURL& url,
net::URLFetcherDelegate* delegate,
const std::string& response_data,
net::HttpStatusCode response_code,
net::URLRequestStatus::Status status)
: net::FakeURLFetcher(url,
delegate,
response_data,
response_code,
status),
test_(test) {}
virtual void AddExtraRequestHeader(const std::string& header_line) OVERRIDE;
private:
GCMNetworkChannelTest* test_;
};
class GCMNetworkChannelTest
: public ::testing::Test,
public SyncNetworkChannel::Observer {
public:
GCMNetworkChannelTest()
: delegate_(NULL),
url_fetchers_created_count_(0),
last_invalidator_state_(TRANSIENT_INVALIDATION_ERROR) {}
virtual ~GCMNetworkChannelTest() {
}
virtual void SetUp() {
request_context_getter_ = new net::TestURLRequestContextGetter(
base::MessageLoopProxy::current());
delegate_ = new TestGCMNetworkChannelDelegate();
scoped_ptr<GCMNetworkChannelDelegate> delegate(delegate_);
gcm_network_channel_.reset(new TestGCMNetworkChannel(
request_context_getter_,
delegate.Pass()));
gcm_network_channel_->AddObserver(this);
gcm_network_channel_->SetMessageReceiver(
invalidation::NewPermanentCallback(
this, &GCMNetworkChannelTest::OnIncomingMessage));
url_fetcher_factory_.reset(new net::FakeURLFetcherFactory(NULL,
base::Bind(&GCMNetworkChannelTest::CreateURLFetcher,
base::Unretained(this))));
}
virtual void TearDown() {
gcm_network_channel_->RemoveObserver(this);
}
GURL BuildUrl(const std::string& registration_id) {
return gcm_network_channel_->GCMNetworkChannel::BuildUrl(registration_id);
}
static void Base64EncodeURLSafe(const std::string& input,
std::string* output) {
GCMNetworkChannel::Base64EncodeURLSafe(input, output);
}
static bool Base64DecodeURLSafe(const std::string& input,
std::string* output) {
return GCMNetworkChannel::Base64DecodeURLSafe(input, output);
}
virtual void OnNetworkChannelStateChanged(
InvalidatorState invalidator_state) OVERRIDE {
last_invalidator_state_ = invalidator_state;
}
void OnIncomingMessage(std::string incoming_message) {
}
GCMNetworkChannel* network_channel() {
return gcm_network_channel_.get();
}
TestGCMNetworkChannelDelegate* delegate() {
return delegate_;
}
int url_fetchers_created_count() {
return url_fetchers_created_count_;
}
net::FakeURLFetcherFactory* url_fetcher_factory() {
return url_fetcher_factory_.get();
}
scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
const GURL& url,
net::URLFetcherDelegate* delegate,
const std::string& response_data,
net::HttpStatusCode response_code,
net::URLRequestStatus::Status status) {
++url_fetchers_created_count_;
return scoped_ptr<net::FakeURLFetcher>(new TestNetworkChannelURLFetcher(
this, url, delegate, response_data, response_code, status));
}
void set_last_echo_token(const std::string& echo_token) {
last_echo_token_ = echo_token;
}
const std::string& get_last_echo_token() {
return last_echo_token_;
}
InvalidatorState get_last_invalidator_state() {
return last_invalidator_state_;
}
void RunLoopUntilIdle() {
base::RunLoop run_loop;
run_loop.RunUntilIdle();
}
private:
base::MessageLoop message_loop_;
TestGCMNetworkChannelDelegate* delegate_;
scoped_ptr<GCMNetworkChannel> gcm_network_channel_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
scoped_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
int url_fetchers_created_count_;
std::string last_echo_token_;
InvalidatorState last_invalidator_state_;
};
void TestNetworkChannelURLFetcher::AddExtraRequestHeader(
const std::string& header_line) {
net::FakeURLFetcher::AddExtraRequestHeader(header_line);
std::string header_name("echo-token: ");
std::string echo_token;
if (StartsWithASCII(header_line, header_name, false)) {
echo_token = header_line;
ReplaceFirstSubstringAfterOffset(
&echo_token, 0, header_name, std::string());
test_->set_last_echo_token(echo_token);
}
}
TEST_F(GCMNetworkChannelTest, HappyCase) {
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state());
EXPECT_FALSE(delegate()->message_callback.is_null());
url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
std::string(),
net::HTTP_NO_CONTENT,
net::URLRequestStatus::SUCCESS);
EXPECT_FALSE(delegate()->register_callback.is_null());
delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
network_channel()->SendMessage("abra.cadabra");
EXPECT_FALSE(delegate()->request_token_callback.is_null());
EXPECT_EQ(url_fetchers_created_count(), 0);
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 1);
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token2");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 1);
EXPECT_EQ(INVALIDATIONS_ENABLED, get_last_invalidator_state());
}
TEST_F(GCMNetworkChannelTest, FailedRegister) {
EXPECT_FALSE(delegate()->register_callback.is_null());
EXPECT_EQ(1, delegate()->register_call_count_);
delegate()->register_callback.Run("", gcm::GCMClient::NETWORK_ERROR);
RunLoopUntilIdle();
EXPECT_EQ(2, delegate()->register_call_count_);
delegate()->register_callback.Run("", gcm::GCMClient::NOT_SIGNED_IN);
RunLoopUntilIdle();
EXPECT_EQ(2, delegate()->register_call_count_);
network_channel()->SendMessage("abra.cadabra");
EXPECT_TRUE(delegate()->request_token_callback.is_null());
EXPECT_EQ(0, url_fetchers_created_count());
}
TEST_F(GCMNetworkChannelTest, RegisterFinishesAfterSendMessage) {
url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
"",
net::HTTP_NO_CONTENT,
net::URLRequestStatus::SUCCESS);
EXPECT_FALSE(delegate()->register_callback.is_null());
network_channel()->SendMessage("abra.cadabra");
EXPECT_TRUE(delegate()->request_token_callback.is_null());
EXPECT_EQ(url_fetchers_created_count(), 0);
delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
EXPECT_FALSE(delegate()->request_token_callback.is_null());
EXPECT_EQ(url_fetchers_created_count(), 0);
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 1);
}
TEST_F(GCMNetworkChannelTest, RequestTokenFailure) {
EXPECT_FALSE(delegate()->register_callback.is_null());
delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
network_channel()->SendMessage("abra.cadabra");
EXPECT_FALSE(delegate()->request_token_callback.is_null());
EXPECT_EQ(url_fetchers_created_count(), 0);
delegate()->request_token_callback.Run(
GoogleServiceAuthError::FromConnectionError(1), "");
EXPECT_EQ(url_fetchers_created_count(), 0);
}
TEST_F(GCMNetworkChannelTest, AuthErrorFromServer) {
url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
"",
net::HTTP_UNAUTHORIZED,
net::URLRequestStatus::SUCCESS);
EXPECT_FALSE(delegate()->register_callback.is_null());
delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
network_channel()->SendMessage("abra.cadabra");
EXPECT_FALSE(delegate()->request_token_callback.is_null());
EXPECT_EQ(url_fetchers_created_count(), 0);
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 1);
EXPECT_EQ(delegate()->invalidated_token, "access.token");
}
TEST_F(GCMNetworkChannelTest, RegisterNeverCompletes) {
network_channel()->SendMessage("abra.cadabra");
EXPECT_FALSE(delegate()->register_callback.is_null());
}
TEST_F(GCMNetworkChannelTest, RequestTokenNeverCompletes) {
network_channel()->SendMessage("abra.cadabra");
delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
EXPECT_FALSE(delegate()->request_token_callback.is_null());
}
TEST_F(GCMNetworkChannelTest, Base64EncodeDecode) {
std::string input;
std::string plain;
std::string base64;
Base64EncodeURLSafe(input, &base64);
EXPECT_TRUE(base64.empty());
EXPECT_TRUE(Base64DecodeURLSafe(base64, &plain));
EXPECT_EQ(input, plain);
for (int length = 1; length < 8; length++) {
input = "abra.cadabra";
input.resize(length);
Base64EncodeURLSafe(input, &base64);
EXPECT_NE(base64[base64.size() - 1], '=');
EXPECT_TRUE(Base64DecodeURLSafe(base64, &plain));
EXPECT_EQ(input, plain);
}
input = "\xfb\xff";
Base64EncodeURLSafe(input, &base64);
EXPECT_EQ("-_8", base64);
EXPECT_TRUE(Base64DecodeURLSafe(base64, &plain));
EXPECT_EQ(input, plain);
}
TEST_F(GCMNetworkChannelTest, TransientError) {
EXPECT_FALSE(delegate()->message_callback.is_null());
url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
std::string(),
net::HTTP_SERVICE_UNAVAILABLE,
net::URLRequestStatus::SUCCESS);
delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
network_channel()->SendMessage("abra.cadabra");
EXPECT_FALSE(delegate()->request_token_callback.is_null());
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 1);
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state());
network_channel()->OnNetworkChanged(
net::NetworkChangeNotifier::CONNECTION_NONE);
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state());
network_channel()->OnNetworkChanged(
net::NetworkChangeNotifier::CONNECTION_WIFI);
EXPECT_EQ(INVALIDATIONS_ENABLED, get_last_invalidator_state());
network_channel()->OnNetworkChanged(
net::NetworkChangeNotifier::CONNECTION_NONE);
EXPECT_EQ(INVALIDATIONS_ENABLED, get_last_invalidator_state());
}
#if !defined(OS_ANDROID)
TEST_F(GCMNetworkChannelTest, BuildUrl) {
GURL url = BuildUrl("registration.id");
EXPECT_TRUE(url.SchemeIsHTTPOrHTTPS());
EXPECT_FALSE(url.host().empty());
EXPECT_FALSE(url.path().empty());
std::vector<std::string> parts;
Tokenize(url.path(), "/", &parts);
std::string buffer;
EXPECT_TRUE(Base64DecodeURLSafe(parts[parts.size() - 1], &buffer));
}
TEST_F(GCMNetworkChannelTest, EchoToken) {
url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
std::string(),
net::HTTP_OK,
net::URLRequestStatus::SUCCESS);
delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
network_channel()->SendMessage("abra.cadabra");
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 1);
EXPECT_TRUE(get_last_echo_token().empty());
delegate()->message_callback.Run("abra.cadabra", "echo.token");
network_channel()->SendMessage("abra.cadabra");
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 2);
EXPECT_EQ("echo.token", get_last_echo_token());
delegate()->message_callback.Run("abra.cadabra", "");
network_channel()->SendMessage("abra.cadabra");
delegate()->request_token_callback.Run(
GoogleServiceAuthError::AuthErrorNone(), "access.token");
RunLoopUntilIdle();
EXPECT_EQ(url_fetchers_created_count(), 3);
EXPECT_EQ("echo.token", get_last_echo_token());
}
#endif
}