| 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 {
|
| + public:
|
| + CustomFakeGCMDriver();
|
| + virtual ~CustomFakeGCMDriver();
|
| +
|
| + virtual void SetAccountTokens(
|
| + const std::vector<GCMClient::AccountTokenInfo>& account_tokens) OVERRIDE;
|
| + virtual void AddConnectionObserver(GCMConnectionObserver* observer) OVERRIDE;
|
| + virtual void RemoveConnectionObserver(
|
| + GCMConnectionObserver* observer) OVERRIDE;
|
| + virtual bool IsConnected() const OVERRIDE { return connected_; }
|
| +
|
| + void set_connected(bool connected) {
|
| + 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.
|
| 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
|
|
|