Index: sync/notifier/gcm_network_channel_unittest.cc |
diff --git a/sync/notifier/gcm_network_channel_unittest.cc b/sync/notifier/gcm_network_channel_unittest.cc |
deleted file mode 100644 |
index 2564d0b9d2fd63230df0059d2580f0e3880b6e9a..0000000000000000000000000000000000000000 |
--- a/sync/notifier/gcm_network_channel_unittest.cc |
+++ /dev/null |
@@ -1,494 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#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; |
-}; |
- |
-// Backoff policy for test. Run first 5 retries without delay. |
-const net::BackoffEntry::Policy kTestBackoffPolicy = { |
- // Number of initial errors (in sequence) to ignore before applying |
- // exponential back-off rules. |
- 5, |
- |
- // Initial delay for exponential back-off in ms. |
- 2000, // 2 seconds. |
- |
- // Factor by which the waiting time will be multiplied. |
- 2, |
- |
- // Fuzzing percentage. ex: 10% will spread requests randomly |
- // between 90%-100% of the calculated time. |
- 0.2, // 20%. |
- |
- // Maximum amount of time we are willing to delay our request in ms. |
- 1000 * 3600 * 4, // 4 hours. |
- |
- // Time to keep an entry from being discarded even when it |
- // has no significant state, -1 to never discard. |
- -1, |
- |
- // Don't use initial delay unless the last request was an error. |
- 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: |
- // On Android GCMNetworkChannel::BuildUrl hits NOTREACHED(). I still want |
- // tests to run. |
- virtual GURL BuildUrl(const std::string& registration_id) OVERRIDE { |
- return GURL("http://test.url.com"); |
- } |
-}; |
- |
-class GCMNetworkChannelTest; |
- |
-// Test needs to capture setting echo-token header on http request. |
-// This class is going to do that. |
-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()); |
- // Ownership of delegate goes to GCNMentworkChannel but test needs pointer |
- // to it. |
- 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); |
- } |
- |
- // Helper functions to call private methods from test |
- 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); |
- |
- // After construction GCMNetworkChannel should have called Register. |
- EXPECT_FALSE(delegate()->register_callback.is_null()); |
- // Return valid registration id. |
- delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS); |
- |
- network_channel()->SendMessage("abra.cadabra"); |
- // SendMessage should have triggered RequestToken. No HTTP request should be |
- // started yet. |
- EXPECT_FALSE(delegate()->request_token_callback.is_null()); |
- EXPECT_EQ(url_fetchers_created_count(), 0); |
- // Return valid access token. This should trigger HTTP request. |
- delegate()->request_token_callback.Run( |
- GoogleServiceAuthError::AuthErrorNone(), "access.token"); |
- RunLoopUntilIdle(); |
- EXPECT_EQ(url_fetchers_created_count(), 1); |
- |
- // Return another access token. Message should be cleared by now and shouldn't |
- // be sent. |
- 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) { |
- // After construction GCMNetworkChannel should have called Register. |
- EXPECT_FALSE(delegate()->register_callback.is_null()); |
- EXPECT_EQ(1, delegate()->register_call_count_); |
- // Return transient error from Register call. |
- delegate()->register_callback.Run("", gcm::GCMClient::NETWORK_ERROR); |
- RunLoopUntilIdle(); |
- // GcmNetworkChannel should have scheduled Register retry. |
- EXPECT_EQ(2, delegate()->register_call_count_); |
- // Return persistent error from Register call. |
- delegate()->register_callback.Run("", gcm::GCMClient::NOT_SIGNED_IN); |
- RunLoopUntilIdle(); |
- // GcmNetworkChannel should give up trying. |
- EXPECT_EQ(2, delegate()->register_call_count_); |
- |
- network_channel()->SendMessage("abra.cadabra"); |
- // SendMessage shouldn't trigger RequestToken. |
- 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); |
- |
- // After construction GCMNetworkChannel should have called Register. |
- EXPECT_FALSE(delegate()->register_callback.is_null()); |
- |
- network_channel()->SendMessage("abra.cadabra"); |
- // SendMessage shouldn't trigger RequestToken. |
- EXPECT_TRUE(delegate()->request_token_callback.is_null()); |
- EXPECT_EQ(url_fetchers_created_count(), 0); |
- |
- // Return valid registration id. |
- delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS); |
- |
- EXPECT_FALSE(delegate()->request_token_callback.is_null()); |
- EXPECT_EQ(url_fetchers_created_count(), 0); |
- // Return valid access token. This should trigger HTTP request. |
- delegate()->request_token_callback.Run( |
- GoogleServiceAuthError::AuthErrorNone(), "access.token"); |
- RunLoopUntilIdle(); |
- EXPECT_EQ(url_fetchers_created_count(), 1); |
-} |
- |
-TEST_F(GCMNetworkChannelTest, RequestTokenFailure) { |
- // After construction GCMNetworkChannel should have called Register. |
- EXPECT_FALSE(delegate()->register_callback.is_null()); |
- // Return valid registration id. |
- delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS); |
- |
- network_channel()->SendMessage("abra.cadabra"); |
- // SendMessage should have triggered RequestToken. No HTTP request should be |
- // started yet. |
- EXPECT_FALSE(delegate()->request_token_callback.is_null()); |
- EXPECT_EQ(url_fetchers_created_count(), 0); |
- // RequestToken returns failure. |
- delegate()->request_token_callback.Run( |
- GoogleServiceAuthError::FromConnectionError(1), ""); |
- |
- // Should be no HTTP requests. |
- EXPECT_EQ(url_fetchers_created_count(), 0); |
-} |
- |
-TEST_F(GCMNetworkChannelTest, AuthErrorFromServer) { |
- // Setup fake response to return AUTH_ERROR. |
- url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"), |
- "", |
- net::HTTP_UNAUTHORIZED, |
- net::URLRequestStatus::SUCCESS); |
- |
- // After construction GCMNetworkChannel should have called Register. |
- EXPECT_FALSE(delegate()->register_callback.is_null()); |
- // Return valid registration id. |
- delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS); |
- |
- network_channel()->SendMessage("abra.cadabra"); |
- // SendMessage should have triggered RequestToken. No HTTP request should be |
- // started yet. |
- EXPECT_FALSE(delegate()->request_token_callback.is_null()); |
- EXPECT_EQ(url_fetchers_created_count(), 0); |
- // Return valid access token. This should trigger HTTP request. |
- delegate()->request_token_callback.Run( |
- GoogleServiceAuthError::AuthErrorNone(), "access.token"); |
- RunLoopUntilIdle(); |
- EXPECT_EQ(url_fetchers_created_count(), 1); |
- EXPECT_EQ(delegate()->invalidated_token, "access.token"); |
-} |
- |
-// Following two tests are to check for memory leaks/crashes when Register and |
-// RequestToken don't complete by the teardown. |
-TEST_F(GCMNetworkChannelTest, RegisterNeverCompletes) { |
- network_channel()->SendMessage("abra.cadabra"); |
- // Register should be called by now. Let's not complete and see what happens. |
- EXPECT_FALSE(delegate()->register_callback.is_null()); |
-} |
- |
-TEST_F(GCMNetworkChannelTest, RequestTokenNeverCompletes) { |
- network_channel()->SendMessage("abra.cadabra"); |
- // Return valid registration id. |
- delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS); |
- // RequestToken should be called by now. Let's not complete and see what |
- // happens. |
- EXPECT_FALSE(delegate()->request_token_callback.is_null()); |
-} |
- |
-TEST_F(GCMNetworkChannelTest, Base64EncodeDecode) { |
- std::string input; |
- std::string plain; |
- std::string base64; |
- // Empty string. |
- Base64EncodeURLSafe(input, &base64); |
- EXPECT_TRUE(base64.empty()); |
- EXPECT_TRUE(Base64DecodeURLSafe(base64, &plain)); |
- EXPECT_EQ(input, plain); |
- // String length: 1..7. |
- for (int length = 1; length < 8; length++) { |
- input = "abra.cadabra"; |
- input.resize(length); |
- Base64EncodeURLSafe(input, &base64); |
- // Ensure no padding at the end. |
- EXPECT_NE(base64[base64.size() - 1], '='); |
- EXPECT_TRUE(Base64DecodeURLSafe(base64, &plain)); |
- EXPECT_EQ(input, plain); |
- } |
- // Presence of '-', '_'. |
- 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()); |
- // POST will fail. |
- 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); |
- // Failing HTTP POST should cause TRANSIENT_INVALIDATION_ERROR. |
- EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state()); |
- // Network change to CONNECTION_NONE shouldn't affect invalidator state. |
- network_channel()->OnNetworkChanged( |
- net::NetworkChangeNotifier::CONNECTION_NONE); |
- EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state()); |
- // Network change to something else should trigger retry. |
- 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); |
- // After construction GCMNetworkChannel should have called Register. |
- // Return valid registration id. |
- delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS); |
- |
- network_channel()->SendMessage("abra.cadabra"); |
- // Return valid access token. This should trigger HTTP request. |
- delegate()->request_token_callback.Run( |
- GoogleServiceAuthError::AuthErrorNone(), "access.token"); |
- RunLoopUntilIdle(); |
- EXPECT_EQ(url_fetchers_created_count(), 1); |
- EXPECT_TRUE(get_last_echo_token().empty()); |
- |
- // Trigger response. |
- delegate()->message_callback.Run("abra.cadabra", "echo.token"); |
- // Send another message. |
- network_channel()->SendMessage("abra.cadabra"); |
- // Return valid access token. This should trigger HTTP request. |
- 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()); |
- |
- // Trigger response with empty echo token. |
- delegate()->message_callback.Run("abra.cadabra", ""); |
- // Send another message. |
- network_channel()->SendMessage("abra.cadabra"); |
- // Return valid access token. This should trigger HTTP request. |
- delegate()->request_token_callback.Run( |
- GoogleServiceAuthError::AuthErrorNone(), "access.token"); |
- RunLoopUntilIdle(); |
- EXPECT_EQ(url_fetchers_created_count(), 3); |
- // Echo_token should be from second message. |
- EXPECT_EQ("echo.token", get_last_echo_token()); |
-} |
-#endif |
- |
-} // namespace syncer |