Chromium Code Reviews| Index: chrome/browser/services/gcm/gcm_account_tracker_unittest.cc |
| diff --git a/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc b/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc |
| index 0abc15ac2d4daef69451b65f5e69d01d728b176c..d3911f022e6e58319955ad87312a288c0f92c085 100644 |
| --- a/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc |
| +++ b/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc |
| @@ -9,6 +9,8 @@ |
| #include "base/memory/scoped_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| +#include "base/run_loop.h" |
| +#include "components/gcm_driver/fake_gcm_driver.h" |
| #include "google_apis/gaia/fake_identity_provider.h" |
| #include "google_apis/gaia/fake_oauth2_token_service.h" |
| #include "google_apis/gaia/google_service_auth_error.h" |
| @@ -61,6 +63,81 @@ void VerifyAccountTokens( |
| } |
| } |
| +class CustomFakeGCMDriver : public FakeGCMDriver { |
|
Nicolas Zea
2014/10/08 00:36:35
nit: comment what it does differently from the nor
fgorski
2014/10/08 18:04:27
Done.
|
| + public: |
| + CustomFakeGCMDriver(); |
| + virtual ~CustomFakeGCMDriver(); |
| + |
| + virtual void SetAccountTokens( |
| + const std::vector<GCMClient::AccountTokenInfo>& account_tokens) OVERRIDE; |
|
Nicolas Zea
2014/10/08 00:36:35
nit: OVERRIDE -> override
fgorski
2014/10/08 18:04:27
Done.
|
| + virtual void AddConnectionObserver(GCMConnectionObserver* observer) OVERRIDE; |
| + virtual void RemoveConnectionObserver( |
| + GCMConnectionObserver* observer) OVERRIDE; |
| + virtual bool IsConnected() const OVERRIDE { return connected_; } |
| + |
| + void set_connected(bool connected) { |
|
Nicolas Zea
2014/10/08 00:36:35
uber nit: the hacker_style inline method is genera
fgorski
2014/10/08 18:04:27
Uber done.
|
| + connected_ = connected; |
| + if (connected && last_connection_observer_) |
| + last_connection_observer_->OnConnected(ip_endpoint_); |
| + } |
| + |
| + // Test results and helpers. |
| + void ResetResults(); |
| + bool update_accounts_called() const { return update_accounts_called_; } |
| + const std::vector<GCMClient::AccountTokenInfo>& accounts() const { |
| + return accounts_; |
| + } |
| + const GCMConnectionObserver* last_connection_observer() const { |
| + return last_connection_observer_; |
| + } |
| + const GCMConnectionObserver* last_removed_connection_observer() const { |
| + return removed_connection_observer_; |
| + } |
| + |
| + private: |
| + bool connected_; |
| + std::vector<GCMClient::AccountTokenInfo> accounts_; |
| + bool update_accounts_called_; |
| + GCMConnectionObserver* last_connection_observer_; |
| + GCMConnectionObserver* removed_connection_observer_; |
| + net::IPEndPoint ip_endpoint_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CustomFakeGCMDriver); |
| +}; |
| + |
| +CustomFakeGCMDriver::CustomFakeGCMDriver() |
| + : connected_(true), |
| + update_accounts_called_(false), |
| + last_connection_observer_(NULL), |
| + removed_connection_observer_(NULL) { |
| +} |
| + |
| +CustomFakeGCMDriver::~CustomFakeGCMDriver() { |
| +} |
| + |
| +void CustomFakeGCMDriver::SetAccountTokens( |
| + const std::vector<GCMClient::AccountTokenInfo>& accounts) { |
| + update_accounts_called_ = true; |
| + accounts_ = accounts; |
| +} |
| + |
| +void CustomFakeGCMDriver::AddConnectionObserver( |
| + GCMConnectionObserver* observer) { |
| + last_connection_observer_ = observer; |
| +} |
| + |
| +void CustomFakeGCMDriver::RemoveConnectionObserver( |
| + GCMConnectionObserver* observer) { |
| + removed_connection_observer_ = observer; |
| +} |
| + |
| +void CustomFakeGCMDriver::ResetResults() { |
| + accounts_.clear(); |
| + update_accounts_called_ = false; |
| + last_connection_observer_ = NULL; |
| + removed_connection_observer_ = NULL; |
| +} |
| + |
| } // namespace |
| class GCMAccountTrackerTest : public testing::Test { |
| @@ -68,9 +145,6 @@ class GCMAccountTrackerTest : public testing::Test { |
| GCMAccountTrackerTest(); |
| virtual ~GCMAccountTrackerTest(); |
| - // Callback for the account tracker. |
| - void UpdateAccounts(const std::vector<GCMClient::AccountTokenInfo>& accounts); |
| - |
| // Helpers to pass fake events to the tracker. Tests should have either a pair |
| // of Start/FinishAccountSignIn or SignInAccount per account. Don't mix. |
| // Call to SignOutAccount is not mandatory. |
| @@ -81,21 +155,15 @@ class GCMAccountTrackerTest : public testing::Test { |
| // Helpers for dealing with OAuth2 access token requests. |
| void IssueAccessToken(const std::string& account_key); |
| + void IssueExpiredAccessToken(const std::string& account_key); |
| void IssueError(const std::string& account_key); |
| - // Test results and helpers. |
| - void ResetResults(); |
| - bool update_accounts_called() const { return update_accounts_called_; } |
| - const std::vector<GCMClient::AccountTokenInfo>& accounts() const { |
| - return accounts_; |
| - } |
| - |
| - // Accessor to account tracker. |
| + // Accessors to account tracker and gcm driver. |
| GCMAccountTracker* tracker() { return tracker_.get(); } |
| + CustomFakeGCMDriver* driver() { return &driver_; } |
| private: |
| - std::vector<GCMClient::AccountTokenInfo> accounts_; |
| - bool update_accounts_called_; |
| + CustomFakeGCMDriver driver_; |
| base::MessageLoop message_loop_; |
| net::TestURLFetcherFactory test_fetcher_factory_; |
| @@ -104,8 +172,7 @@ class GCMAccountTrackerTest : public testing::Test { |
| scoped_ptr<GCMAccountTracker> tracker_; |
| }; |
| -GCMAccountTrackerTest::GCMAccountTrackerTest() |
| - : update_accounts_called_(false) { |
| +GCMAccountTrackerTest::GCMAccountTrackerTest() { |
| fake_token_service_.reset(new FakeOAuth2TokenService()); |
| fake_identity_provider_.reset( |
| @@ -116,10 +183,7 @@ GCMAccountTrackerTest::GCMAccountTrackerTest() |
| new net::TestURLRequestContextGetter( |
| message_loop_.message_loop_proxy()))); |
| - tracker_.reset(new GCMAccountTracker( |
| - gaia_account_tracker.Pass(), |
| - base::Bind(&GCMAccountTrackerTest::UpdateAccounts, |
| - base::Unretained(this)))); |
| + tracker_.reset(new GCMAccountTracker(gaia_account_tracker.Pass(), &driver_)); |
| } |
| GCMAccountTrackerTest::~GCMAccountTrackerTest() { |
| @@ -127,17 +191,6 @@ GCMAccountTrackerTest::~GCMAccountTrackerTest() { |
| tracker_->Shutdown(); |
| } |
| -void GCMAccountTrackerTest::UpdateAccounts( |
| - const std::vector<GCMClient::AccountTokenInfo>& accounts) { |
| - update_accounts_called_ = true; |
| - accounts_ = accounts; |
| -} |
| - |
| -void GCMAccountTrackerTest::ResetResults() { |
| - accounts_.clear(); |
| - update_accounts_called_ = false; |
| -} |
| - |
| void GCMAccountTrackerTest::StartAccountSignIn(const std::string& account_key) { |
| fake_identity_provider_->LogIn(account_key); |
| fake_token_service_->AddAccount(account_key); |
| @@ -169,19 +222,25 @@ void GCMAccountTrackerTest::IssueAccessToken(const std::string& account_key) { |
| account_key, MakeAccessToken(account_key), base::Time::Max()); |
| } |
| +void GCMAccountTrackerTest::IssueExpiredAccessToken( |
| + const std::string& account_key) { |
| + fake_token_service_->IssueAllTokensForAccount( |
| + account_key, MakeAccessToken(account_key), base::Time::Now()); |
| +} |
| + |
| void GCMAccountTrackerTest::IssueError(const std::string& account_key) { |
| fake_token_service_->IssueErrorForAllPendingRequestsForAccount( |
| account_key, |
| GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); |
| } |
| +// TODO(fgorsk): This actually need fixing. |
|
Nicolas Zea
2014/10/08 00:36:35
Is this comment still relevant?
fgorski
2014/10/08 18:04:27
Removing.
|
| TEST_F(GCMAccountTrackerTest, NoAccounts) { |
| - EXPECT_FALSE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| tracker()->Start(); |
| // Callback should not be called if there where no accounts provided. |
| - EXPECT_FALSE(update_accounts_called()); |
| - EXPECT_TRUE(accounts().empty()); |
| - tracker()->Stop(); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| + EXPECT_TRUE(driver()->accounts().empty()); |
| } |
| // Verifies that callback is called after a token is issued for a single account |
| @@ -193,18 +252,17 @@ TEST_F(GCMAccountTrackerTest, SingleAccount) { |
| tracker()->Start(); |
| // We don't have any accounts to report, but given the inner account tracker |
| // is still working we don't make a call with empty accounts list. |
| - EXPECT_FALSE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| // This concludes the work of inner account tracker. |
| FinishAccountSignIn(kAccountId1); |
| IssueAccessToken(kAccountId1); |
| - EXPECT_TRUE(update_accounts_called()); |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| std::vector<GCMClient::AccountTokenInfo> expected_accounts; |
| expected_accounts.push_back(MakeAccountToken(kAccountId1)); |
| - VerifyAccountTokens(expected_accounts, accounts()); |
| - tracker()->Stop(); |
| + VerifyAccountTokens(expected_accounts, driver()->accounts()); |
| } |
| TEST_F(GCMAccountTrackerTest, MultipleAccounts) { |
| @@ -212,39 +270,35 @@ TEST_F(GCMAccountTrackerTest, MultipleAccounts) { |
| StartAccountSignIn(kAccountId2); |
| tracker()->Start(); |
| - EXPECT_FALSE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| FinishAccountSignIn(kAccountId1); |
| IssueAccessToken(kAccountId1); |
| - EXPECT_FALSE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| FinishAccountSignIn(kAccountId2); |
| IssueAccessToken(kAccountId2); |
| - EXPECT_TRUE(update_accounts_called()); |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| std::vector<GCMClient::AccountTokenInfo> expected_accounts; |
| expected_accounts.push_back(MakeAccountToken(kAccountId1)); |
| expected_accounts.push_back(MakeAccountToken(kAccountId2)); |
| - VerifyAccountTokens(expected_accounts, accounts()); |
| - |
| - tracker()->Stop(); |
| + VerifyAccountTokens(expected_accounts, driver()->accounts()); |
| } |
| TEST_F(GCMAccountTrackerTest, AccountAdded) { |
| tracker()->Start(); |
| - ResetResults(); |
| + driver()->ResetResults(); |
| SignInAccount(kAccountId1); |
| - EXPECT_FALSE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| IssueAccessToken(kAccountId1); |
| - EXPECT_TRUE(update_accounts_called()); |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| std::vector<GCMClient::AccountTokenInfo> expected_accounts; |
| expected_accounts.push_back(MakeAccountToken(kAccountId1)); |
| - VerifyAccountTokens(expected_accounts, accounts()); |
| - |
| - tracker()->Stop(); |
| + VerifyAccountTokens(expected_accounts, driver()->accounts()); |
| } |
| TEST_F(GCMAccountTrackerTest, AccountRemoved) { |
| @@ -254,19 +308,17 @@ TEST_F(GCMAccountTrackerTest, AccountRemoved) { |
| tracker()->Start(); |
| IssueAccessToken(kAccountId1); |
| IssueAccessToken(kAccountId2); |
| - EXPECT_TRUE(update_accounts_called()); |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| - ResetResults(); |
| - EXPECT_FALSE(update_accounts_called()); |
| + driver()->ResetResults(); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| SignOutAccount(kAccountId2); |
| - EXPECT_TRUE(update_accounts_called()); |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| std::vector<GCMClient::AccountTokenInfo> expected_accounts; |
| expected_accounts.push_back(MakeAccountToken(kAccountId1)); |
| - VerifyAccountTokens(expected_accounts, accounts()); |
| - |
| - tracker()->Stop(); |
| + VerifyAccountTokens(expected_accounts, driver()->accounts()); |
| } |
| TEST_F(GCMAccountTrackerTest, GetTokenFailed) { |
| @@ -275,16 +327,20 @@ TEST_F(GCMAccountTrackerTest, GetTokenFailed) { |
| tracker()->Start(); |
| IssueAccessToken(kAccountId1); |
| - EXPECT_FALSE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| IssueError(kAccountId2); |
| - EXPECT_TRUE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| + |
| + EXPECT_EQ(1UL, tracker()->get_pending_token_request_count()); |
| + |
| + IssueAccessToken(kAccountId2); |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| std::vector<GCMClient::AccountTokenInfo> expected_accounts; |
| expected_accounts.push_back(MakeAccountToken(kAccountId1)); |
| - VerifyAccountTokens(expected_accounts, accounts()); |
| - |
| - tracker()->Stop(); |
| + expected_accounts.push_back(MakeAccountToken(kAccountId2)); |
| + VerifyAccountTokens(expected_accounts, driver()->accounts()); |
| } |
| TEST_F(GCMAccountTrackerTest, GetTokenFailedAccountRemoved) { |
| @@ -295,15 +351,15 @@ TEST_F(GCMAccountTrackerTest, GetTokenFailedAccountRemoved) { |
| IssueAccessToken(kAccountId1); |
| IssueError(kAccountId2); |
| - ResetResults(); |
| + driver()->ResetResults(); |
| SignOutAccount(kAccountId2); |
| - EXPECT_TRUE(update_accounts_called()); |
| + IssueError(kAccountId2); |
| + |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| std::vector<GCMClient::AccountTokenInfo> expected_accounts; |
| expected_accounts.push_back(MakeAccountToken(kAccountId1)); |
| - VerifyAccountTokens(expected_accounts, accounts()); |
| - |
| - tracker()->Stop(); |
| + VerifyAccountTokens(expected_accounts, driver()->accounts()); |
| } |
| TEST_F(GCMAccountTrackerTest, AccountRemovedWhileRequestsPending) { |
| @@ -312,17 +368,55 @@ TEST_F(GCMAccountTrackerTest, AccountRemovedWhileRequestsPending) { |
| tracker()->Start(); |
| IssueAccessToken(kAccountId1); |
| - EXPECT_FALSE(update_accounts_called()); |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| SignOutAccount(kAccountId2); |
| IssueAccessToken(kAccountId2); |
| - EXPECT_TRUE(update_accounts_called()); |
| + EXPECT_TRUE(driver()->update_accounts_called()); |
| std::vector<GCMClient::AccountTokenInfo> expected_accounts; |
| expected_accounts.push_back(MakeAccountToken(kAccountId1)); |
| - VerifyAccountTokens(expected_accounts, accounts()); |
| + VerifyAccountTokens(expected_accounts, driver()->accounts()); |
| +} |
| + |
| +// Makes sure that tracker observes GCM connection when running. |
| +TEST_F(GCMAccountTrackerTest, TrackerObservesConnection) { |
| + EXPECT_EQ(NULL, driver()->last_connection_observer()); |
| + tracker()->Start(); |
| + EXPECT_EQ(tracker(), driver()->last_connection_observer()); |
| + tracker()->Shutdown(); |
| + EXPECT_EQ(tracker(), driver()->last_removed_connection_observer()); |
| +} |
| + |
| +// Makes sure that token fetching happens only after connection is established. |
| +TEST_F(GCMAccountTrackerTest, PostponeTokenFetchingUntilConnected) { |
| + driver()->set_connected(false); |
| + StartAccountSignIn(kAccountId1); |
| + tracker()->Start(); |
| + FinishAccountSignIn(kAccountId1); |
| - tracker()->Stop(); |
| + EXPECT_EQ(0UL, tracker()->get_pending_token_request_count()); |
| + driver()->set_connected(true); |
| + |
| + EXPECT_EQ(1UL, tracker()->get_pending_token_request_count()); |
| +} |
| + |
| +TEST_F(GCMAccountTrackerTest, IvalidateExpiredTokens) { |
| + StartAccountSignIn(kAccountId1); |
| + StartAccountSignIn(kAccountId2); |
| + tracker()->Start(); |
| + FinishAccountSignIn(kAccountId1); |
| + FinishAccountSignIn(kAccountId2); |
| + |
| + EXPECT_EQ(2UL, tracker()->get_pending_token_request_count()); |
| + |
| + IssueExpiredAccessToken(kAccountId1); |
| + IssueAccessToken(kAccountId2); |
| + // Because the first token is expired, we expect the sanitize to kick in and |
| + // clean it up before the SetAccessToken is called. This also means a new |
| + // token request will be issued |
| + EXPECT_FALSE(driver()->update_accounts_called()); |
| + EXPECT_EQ(1UL, tracker()->get_pending_token_request_count()); |
| } |
| // TODO(fgorski): Add test for adding account after removal >> make sure it does |