blob: f17b7a6f6b6862a3d7c6f83cb10a6e0f1830868b [file] [log] [blame]
[email protected]641c8cc72014-07-02 00:33:061// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
jitendra.ks70c5b4c2015-08-19 18:53:345#include "components/gcm_driver/gcm_account_tracker.h"
[email protected]641c8cc72014-07-02 00:33:066
7#include <map>
dchenga77e28eb2016-04-21 21:34:378#include <memory>
[email protected]641c8cc72014-07-02 00:33:069#include <string>
dcheng51606352015-12-26 21:16:2310#include <utility>
[email protected]641c8cc72014-07-02 00:33:0611
avi26062922015-12-26 00:14:1812#include "base/macros.h"
fdoraye1e050c52016-07-19 21:05:5413#include "base/message_loop/message_loop.h"
fgorski83afd872014-10-16 01:11:5214#include "components/gcm_driver/fake_gcm_driver.h"
Colin Blundellbf6d4c5f2018-05-16 11:12:2915#include "components/signin/core/browser/account_tracker_service.h"
Colin Blundelle3f61fa2018-07-18 12:16:2616#include "components/signin/core/browser/fake_gaia_cookie_manager_service.h"
Colin Blundellbf6d4c5f2018-05-16 11:12:2917#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
18#include "components/signin/core/browser/fake_signin_manager.h"
19#include "components/signin/core/browser/test_signin_client.h"
20#include "components/sync_preferences/testing_pref_service_syncable.h"
[email protected]641c8cc72014-07-02 00:33:0621#include "google_apis/gaia/fake_oauth2_token_service.h"
22#include "google_apis/gaia/google_service_auth_error.h"
23#include "net/http/http_status_code.h"
24#include "net/url_request/test_url_fetcher_factory.h"
25#include "net/url_request/url_request_test_util.h"
Colin Blundell354f2212018-07-16 14:45:0826#include "services/identity/public/cpp/identity_manager.h"
27#include "services/identity/public/cpp/identity_test_utils.h"
[email protected]641c8cc72014-07-02 00:33:0628#include "testing/gtest/include/gtest/gtest.h"
29
30namespace gcm {
31
32namespace {
33
Colin Blundellbf6d4c5f2018-05-16 11:12:2934#if defined(OS_CHROMEOS)
35using SigninManagerForTest = FakeSigninManagerBase;
36#else
37using SigninManagerForTest = FakeSigninManager;
38#endif // OS_CHROMEOS
39
Colin Blundella1b7c902018-06-29 06:28:0640const char kEmail1[] = "[email protected]";
Colin Blundella1b7c902018-06-29 06:28:0641const char kEmail2[] = "[email protected]";
[email protected]641c8cc72014-07-02 00:33:0642
Colin Blundella1b7c902018-06-29 06:28:0643std::string AccountIdToObfuscatedId(const std::string& account_id) {
44 return "obfid-" + account_id;
[email protected]641c8cc72014-07-02 00:33:0645}
46
Colin Blundella1b7c902018-06-29 06:28:0647std::string GetValidTokenInfoResponse(const std::string& account_id) {
48 return std::string("{ \"id\": \"") + AccountIdToObfuscatedId(account_id) +
[email protected]641c8cc72014-07-02 00:33:0649 "\" }";
50}
51
Colin Blundella1b7c902018-06-29 06:28:0652std::string MakeAccessToken(const std::string& account_id) {
53 return "access_token-" + account_id;
[email protected]641c8cc72014-07-02 00:33:0654}
55
Colin Blundella1b7c902018-06-29 06:28:0656GCMClient::AccountTokenInfo MakeAccountToken(const std::string& account_id) {
fgorski58b9dfc2014-09-29 16:46:1857 GCMClient::AccountTokenInfo token_info;
Colin Blundella1b7c902018-06-29 06:28:0658 token_info.account_id = account_id;
59
60 // TODO(https://crbug.com/856170): This *should* be expected to be the email
61 // address for the given account, but there is a bug in AccountTracker that
62 // means that |token_info.email| actually gets populated with the account ID
63 // by the production code. Hence the test expectation has to match what the
64 // production code actually does :). If/when that bug gets fixed, this
65 // function should be changed to take in the email address as well as the
66 // account ID and populate this field with the email address.
67 token_info.email = account_id;
68 token_info.access_token = MakeAccessToken(account_id);
fgorski58b9dfc2014-09-29 16:46:1869 return token_info;
70}
71
72void VerifyAccountTokens(
73 const std::vector<GCMClient::AccountTokenInfo>& expected_tokens,
74 const std::vector<GCMClient::AccountTokenInfo>& actual_tokens) {
75 EXPECT_EQ(expected_tokens.size(), actual_tokens.size());
76 for (std::vector<GCMClient::AccountTokenInfo>::const_iterator
77 expected_iter = expected_tokens.begin(),
78 actual_iter = actual_tokens.begin();
79 expected_iter != expected_tokens.end() &&
80 actual_iter != actual_tokens.end();
81 ++expected_iter, ++actual_iter) {
82 EXPECT_EQ(expected_iter->account_id, actual_iter->account_id);
83 EXPECT_EQ(expected_iter->email, actual_iter->email);
84 EXPECT_EQ(expected_iter->access_token, actual_iter->access_token);
85 }
86}
87
fgorski83afd872014-10-16 01:11:5288// This version of FakeGCMDriver is customized around handling accounts and
89// connection events for testing GCMAccountTracker.
90class CustomFakeGCMDriver : public FakeGCMDriver {
91 public:
92 CustomFakeGCMDriver();
Daniel Chenga542fca2014-10-21 09:51:2993 ~CustomFakeGCMDriver() override;
fgorski83afd872014-10-16 01:11:5294
95 // GCMDriver overrides:
Daniel Chenga542fca2014-10-21 09:51:2996 void SetAccountTokens(
fgorski83afd872014-10-16 01:11:5297 const std::vector<GCMClient::AccountTokenInfo>& account_tokens) override;
Daniel Chenga542fca2014-10-21 09:51:2998 void AddConnectionObserver(GCMConnectionObserver* observer) override;
99 void RemoveConnectionObserver(GCMConnectionObserver* observer) override;
100 bool IsConnected() const override { return connected_; }
fgorski9a405102014-11-19 01:25:16101 base::Time GetLastTokenFetchTime() override;
102 void SetLastTokenFetchTime(const base::Time& time) override;
fgorski83afd872014-10-16 01:11:52103
104 // Test results and helpers.
105 void SetConnected(bool connected);
106 void ResetResults();
107 bool update_accounts_called() const { return update_accounts_called_; }
108 const std::vector<GCMClient::AccountTokenInfo>& accounts() const {
109 return accounts_;
110 }
111 const GCMConnectionObserver* last_connection_observer() const {
112 return last_connection_observer_;
113 }
114 const GCMConnectionObserver* last_removed_connection_observer() const {
115 return removed_connection_observer_;
116 }
117
118 private:
119 bool connected_;
120 std::vector<GCMClient::AccountTokenInfo> accounts_;
121 bool update_accounts_called_;
122 GCMConnectionObserver* last_connection_observer_;
123 GCMConnectionObserver* removed_connection_observer_;
124 net::IPEndPoint ip_endpoint_;
fgorski9a405102014-11-19 01:25:16125 base::Time last_token_fetch_time_;
fgorski83afd872014-10-16 01:11:52126
127 DISALLOW_COPY_AND_ASSIGN(CustomFakeGCMDriver);
128};
129
130CustomFakeGCMDriver::CustomFakeGCMDriver()
131 : connected_(true),
132 update_accounts_called_(false),
Ivan Kotenkov75b1c3a2017-10-24 14:47:24133 last_connection_observer_(nullptr),
134 removed_connection_observer_(nullptr) {}
fgorski83afd872014-10-16 01:11:52135
136CustomFakeGCMDriver::~CustomFakeGCMDriver() {
137}
138
139void CustomFakeGCMDriver::SetAccountTokens(
140 const std::vector<GCMClient::AccountTokenInfo>& accounts) {
141 update_accounts_called_ = true;
142 accounts_ = accounts;
143}
144
145void CustomFakeGCMDriver::AddConnectionObserver(
146 GCMConnectionObserver* observer) {
147 last_connection_observer_ = observer;
148}
149
150void CustomFakeGCMDriver::RemoveConnectionObserver(
151 GCMConnectionObserver* observer) {
152 removed_connection_observer_ = observer;
153}
154
155void CustomFakeGCMDriver::SetConnected(bool connected) {
156 connected_ = connected;
157 if (connected && last_connection_observer_)
158 last_connection_observer_->OnConnected(ip_endpoint_);
159}
160
161void CustomFakeGCMDriver::ResetResults() {
162 accounts_.clear();
163 update_accounts_called_ = false;
Ivan Kotenkov75b1c3a2017-10-24 14:47:24164 last_connection_observer_ = nullptr;
165 removed_connection_observer_ = nullptr;
fgorski83afd872014-10-16 01:11:52166}
167
fgorski9a405102014-11-19 01:25:16168
169base::Time CustomFakeGCMDriver::GetLastTokenFetchTime() {
170 return last_token_fetch_time_;
171}
172
173void CustomFakeGCMDriver::SetLastTokenFetchTime(const base::Time& time) {
174 last_token_fetch_time_ = time;
175}
176
[email protected]641c8cc72014-07-02 00:33:06177} // namespace
178
179class GCMAccountTrackerTest : public testing::Test {
180 public:
181 GCMAccountTrackerTest();
dchenge1bc7982014-10-30 00:32:40182 ~GCMAccountTrackerTest() override;
[email protected]641c8cc72014-07-02 00:33:06183
Colin Blundell04720562018-05-14 09:19:40184 // Helpers to pass fake info to the tracker. Tests should have either a pair
Colin Blundellbf6d4c5f2018-05-16 11:12:29185 // of Start(Primary)/FinishAccountAddition or Add(Primary)Account per
Colin Blundella1b7c902018-06-29 06:28:06186 // account. Don't mix. Any methods that return an std::string are returning
187 // the account ID of the newly-added account, which can then be passed into
188 // any methods that take in an account ID.
Colin Blundell04720562018-05-14 09:19:40189 // Call to RemoveAccount is not mandatory.
Colin Blundell354f2212018-07-16 14:45:08190 std::string StartAccountAddition(const std::string& email);
191 std::string StartPrimaryAccountAddition(const std::string& email);
Colin Blundella1b7c902018-06-29 06:28:06192 void FinishAccountAddition(const std::string& account_id);
Colin Blundell354f2212018-07-16 14:45:08193 std::string AddAccount(const std::string& email);
194 std::string AddPrimaryAccount(const std::string& email);
Colin Blundella1b7c902018-06-29 06:28:06195 void RemoveAccount(const std::string& account_id);
[email protected]641c8cc72014-07-02 00:33:06196
197 // Helpers for dealing with OAuth2 access token requests.
Colin Blundella1b7c902018-06-29 06:28:06198 void IssueAccessToken(const std::string& account_id);
199 void IssueExpiredAccessToken(const std::string& account_id);
200 void IssueError(const std::string& account_id);
[email protected]641c8cc72014-07-02 00:33:06201
fgorski83afd872014-10-16 01:11:52202 // Accessors to account tracker and gcm driver.
[email protected]641c8cc72014-07-02 00:33:06203 GCMAccountTracker* tracker() { return tracker_.get(); }
fgorski83afd872014-10-16 01:11:52204 CustomFakeGCMDriver* driver() { return &driver_; }
[email protected]641c8cc72014-07-02 00:33:06205
fgorski9a405102014-11-19 01:25:16206 // Accessors to private methods of account tracker.
207 bool IsFetchingRequired() const;
208 bool IsTokenReportingRequired() const;
209 base::TimeDelta GetTimeToNextTokenReporting() const;
210
[email protected]641c8cc72014-07-02 00:33:06211 private:
fgorski83afd872014-10-16 01:11:52212 CustomFakeGCMDriver driver_;
[email protected]641c8cc72014-07-02 00:33:06213
214 base::MessageLoop message_loop_;
215 net::TestURLFetcherFactory test_fetcher_factory_;
Colin Blundellbf6d4c5f2018-05-16 11:12:29216 sync_preferences::TestingPrefServiceSyncable pref_service_;
217 AccountTrackerService account_tracker_service_;
218 std::unique_ptr<TestSigninClient> test_signin_client_;
219 std::unique_ptr<SigninManagerForTest> fake_signin_manager_;
220 std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_;
Colin Blundelle3f61fa2018-07-18 12:16:26221 std::unique_ptr<FakeGaiaCookieManagerService>
222 fake_gaia_cookie_manager_service_;
Colin Blundell354f2212018-07-16 14:45:08223 std::unique_ptr<identity::IdentityManager> identity_manager_;
dchenga77e28eb2016-04-21 21:34:37224 std::unique_ptr<GCMAccountTracker> tracker_;
[email protected]641c8cc72014-07-02 00:33:06225};
226
fgorski83afd872014-10-16 01:11:52227GCMAccountTrackerTest::GCMAccountTrackerTest() {
Colin Blundellbf6d4c5f2018-05-16 11:12:29228 fake_token_service_.reset(new FakeProfileOAuth2TokenService());
[email protected]641c8cc72014-07-02 00:33:06229
Colin Blundellbf6d4c5f2018-05-16 11:12:29230 test_signin_client_.reset(new TestSigninClient(&pref_service_));
231#if defined(OS_CHROMEOS)
232 fake_signin_manager_.reset(new SigninManagerForTest(
233 test_signin_client_.get(), &account_tracker_service_));
234#else
235 fake_signin_manager_.reset(new SigninManagerForTest(
236 test_signin_client_.get(), fake_token_service_.get(),
237 &account_tracker_service_, nullptr));
238#endif
239
Colin Blundelle3f61fa2018-07-18 12:16:26240 fake_gaia_cookie_manager_service_.reset(new FakeGaiaCookieManagerService(
241 fake_token_service_.get(), "gcm_account_tracker_unittest",
242 test_signin_client_.get()));
Colin Blundellbf6d4c5f2018-05-16 11:12:29243 AccountTrackerService::RegisterPrefs(pref_service_.registry());
244 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
245 SigninManagerBase::RegisterPrefs(pref_service_.registry());
246 account_tracker_service_.Initialize(test_signin_client_.get());
247
Colin Blundell354f2212018-07-16 14:45:08248 identity_manager_ = std::make_unique<identity::IdentityManager>(
249 fake_signin_manager_.get(), fake_token_service_.get(),
Colin Blundelle3f61fa2018-07-18 12:16:26250 &account_tracker_service_, fake_gaia_cookie_manager_service_.get());
Colin Blundell354f2212018-07-16 14:45:08251
Colin Blundell021e3e4d2018-04-19 01:03:24252 std::unique_ptr<AccountTracker> gaia_account_tracker(new AccountTracker(
Colin Blundellf8789932018-05-22 11:35:56253 fake_signin_manager_.get(), fake_token_service_.get(),
Colin Blundell021e3e4d2018-04-19 01:03:24254 new net::TestURLRequestContextGetter(message_loop_.task_runner())));
[email protected]641c8cc72014-07-02 00:33:06255
Colin Blundellf8789932018-05-22 11:35:56256 tracker_.reset(new GCMAccountTracker(std::move(gaia_account_tracker),
Colin Blundell354f2212018-07-16 14:45:08257 identity_manager_.get(), &driver_));
[email protected]641c8cc72014-07-02 00:33:06258}
259
260GCMAccountTrackerTest::~GCMAccountTrackerTest() {
261 if (tracker_)
262 tracker_->Shutdown();
263}
264
Colin Blundella1b7c902018-06-29 06:28:06265std::string GCMAccountTrackerTest::StartAccountAddition(
Colin Blundella1b7c902018-06-29 06:28:06266 const std::string& email) {
Colin Blundell354f2212018-07-16 14:45:08267 return identity::MakeAccountAvailable(&account_tracker_service_,
268 fake_token_service_.get(),
269 identity_manager_.get(), email)
270 .account_id;
Colin Blundellbf6d4c5f2018-05-16 11:12:29271}
272
Colin Blundella1b7c902018-06-29 06:28:06273std::string GCMAccountTrackerTest::StartPrimaryAccountAddition(
Colin Blundella1b7c902018-06-29 06:28:06274 const std::string& email) {
Colin Blundellbf6d4c5f2018-05-16 11:12:29275// NOTE: Setting of the primary account info must be done first on ChromeOS
276// to ensure that AccountTracker and GCMAccountTracker respond as expected
277// when the token is added to the token service.
278// TODO(blundell): On non-ChromeOS, it would be good to add tests wherein
279// setting of the primary account is done afterward to check that the flow
280// that ensues from the GoogleSigninSucceeded callback firing works as
281// expected.
Colin Blundell354f2212018-07-16 14:45:08282return identity::MakePrimaryAccountAvailable(fake_signin_manager_.get(),
283 fake_token_service_.get(),
284 identity_manager_.get(), email)
285 .account_id;
[email protected]641c8cc72014-07-02 00:33:06286}
287
Colin Blundell04720562018-05-14 09:19:40288void GCMAccountTrackerTest::FinishAccountAddition(
Colin Blundella1b7c902018-06-29 06:28:06289 const std::string& account_id) {
290 IssueAccessToken(account_id);
[email protected]641c8cc72014-07-02 00:33:06291
292 net::TestURLFetcher* fetcher = test_fetcher_factory_.GetFetcherByID(
293 gaia::GaiaOAuthClient::kUrlFetcherId);
294 ASSERT_TRUE(fetcher);
295 fetcher->set_response_code(net::HTTP_OK);
Colin Blundella1b7c902018-06-29 06:28:06296 fetcher->SetResponseString(GetValidTokenInfoResponse(account_id));
[email protected]641c8cc72014-07-02 00:33:06297 fetcher->delegate()->OnURLFetchComplete(fetcher);
298}
299
Colin Blundell354f2212018-07-16 14:45:08300std::string GCMAccountTrackerTest::AddPrimaryAccount(const std::string& email) {
301 std::string account_id = StartPrimaryAccountAddition(email);
Colin Blundella1b7c902018-06-29 06:28:06302 FinishAccountAddition(account_id);
303 return account_id;
Colin Blundellbf6d4c5f2018-05-16 11:12:29304}
305
Colin Blundell354f2212018-07-16 14:45:08306std::string GCMAccountTrackerTest::AddAccount(const std::string& email) {
307 std::string account_id = StartAccountAddition(email);
Colin Blundella1b7c902018-06-29 06:28:06308 FinishAccountAddition(account_id);
309 return account_id;
[email protected]641c8cc72014-07-02 00:33:06310}
311
Colin Blundella1b7c902018-06-29 06:28:06312void GCMAccountTrackerTest::RemoveAccount(const std::string& account_id) {
Colin Blundell354f2212018-07-16 14:45:08313 identity::RemoveRefreshTokenForAccount(fake_token_service_.get(),
314 identity_manager_.get(), account_id);
[email protected]641c8cc72014-07-02 00:33:06315}
316
Colin Blundella1b7c902018-06-29 06:28:06317void GCMAccountTrackerTest::IssueAccessToken(const std::string& account_id) {
[email protected]641c8cc72014-07-02 00:33:06318 fake_token_service_->IssueAllTokensForAccount(
Colin Blundella1b7c902018-06-29 06:28:06319 account_id, MakeAccessToken(account_id), base::Time::Max());
[email protected]641c8cc72014-07-02 00:33:06320}
321
fgorski83afd872014-10-16 01:11:52322void GCMAccountTrackerTest::IssueExpiredAccessToken(
Colin Blundella1b7c902018-06-29 06:28:06323 const std::string& account_id) {
fgorski83afd872014-10-16 01:11:52324 fake_token_service_->IssueAllTokensForAccount(
Colin Blundella1b7c902018-06-29 06:28:06325 account_id, MakeAccessToken(account_id), base::Time::Now());
fgorski83afd872014-10-16 01:11:52326}
327
Colin Blundella1b7c902018-06-29 06:28:06328void GCMAccountTrackerTest::IssueError(const std::string& account_id) {
[email protected]641c8cc72014-07-02 00:33:06329 fake_token_service_->IssueErrorForAllPendingRequestsForAccount(
Colin Blundella1b7c902018-06-29 06:28:06330 account_id,
[email protected]641c8cc72014-07-02 00:33:06331 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
332}
333
fgorski9a405102014-11-19 01:25:16334bool GCMAccountTrackerTest::IsFetchingRequired() const {
335 return tracker_->IsTokenFetchingRequired();
336}
337
338bool GCMAccountTrackerTest::IsTokenReportingRequired() const {
339 return tracker_->IsTokenReportingRequired();
340}
341
342base::TimeDelta GCMAccountTrackerTest::GetTimeToNextTokenReporting() const {
343 return tracker_->GetTimeToNextTokenReporting();
344}
345
[email protected]641c8cc72014-07-02 00:33:06346TEST_F(GCMAccountTrackerTest, NoAccounts) {
fgorski83afd872014-10-16 01:11:52347 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06348 tracker()->Start();
[email protected]7df5ef22014-07-17 07:35:58349 // Callback should not be called if there where no accounts provided.
fgorski83afd872014-10-16 01:11:52350 EXPECT_FALSE(driver()->update_accounts_called());
351 EXPECT_TRUE(driver()->accounts().empty());
[email protected]641c8cc72014-07-02 00:33:06352}
353
354// Verifies that callback is called after a token is issued for a single account
355// with a specific scope. In this scenario, the underlying account tracker is
356// still working when the CompleteCollectingTokens is called for the first time.
357TEST_F(GCMAccountTrackerTest, SingleAccount) {
Colin Blundell354f2212018-07-16 14:45:08358 std::string account_id1 = StartPrimaryAccountAddition(kEmail1);
[email protected]641c8cc72014-07-02 00:33:06359
360 tracker()->Start();
361 // We don't have any accounts to report, but given the inner account tracker
362 // is still working we don't make a call with empty accounts list.
fgorski83afd872014-10-16 01:11:52363 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06364
365 // This concludes the work of inner account tracker.
Colin Blundella1b7c902018-06-29 06:28:06366 FinishAccountAddition(account_id1);
367 IssueAccessToken(account_id1);
[email protected]641c8cc72014-07-02 00:33:06368
fgorski83afd872014-10-16 01:11:52369 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06370
fgorski58b9dfc2014-09-29 16:46:18371 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06372 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52373 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06374}
375
376TEST_F(GCMAccountTrackerTest, MultipleAccounts) {
Colin Blundell354f2212018-07-16 14:45:08377 std::string account_id1 = StartPrimaryAccountAddition(kEmail1);
Colin Blundellbf6d4c5f2018-05-16 11:12:29378
Colin Blundell354f2212018-07-16 14:45:08379 std::string account_id2 = StartAccountAddition(kEmail2);
[email protected]641c8cc72014-07-02 00:33:06380
381 tracker()->Start();
fgorski83afd872014-10-16 01:11:52382 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06383
Colin Blundella1b7c902018-06-29 06:28:06384 FinishAccountAddition(account_id1);
385 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52386 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06387
Colin Blundella1b7c902018-06-29 06:28:06388 FinishAccountAddition(account_id2);
389 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52390 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06391
fgorski58b9dfc2014-09-29 16:46:18392 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06393 expected_accounts.push_back(MakeAccountToken(account_id1));
394 expected_accounts.push_back(MakeAccountToken(account_id2));
fgorski83afd872014-10-16 01:11:52395 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06396}
397
398TEST_F(GCMAccountTrackerTest, AccountAdded) {
399 tracker()->Start();
fgorski83afd872014-10-16 01:11:52400 driver()->ResetResults();
[email protected]641c8cc72014-07-02 00:33:06401
Colin Blundell354f2212018-07-16 14:45:08402 std::string account_id1 = AddPrimaryAccount(kEmail1);
fgorski83afd872014-10-16 01:11:52403 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06404
Colin Blundella1b7c902018-06-29 06:28:06405 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52406 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06407
fgorski58b9dfc2014-09-29 16:46:18408 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06409 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52410 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06411}
412
413TEST_F(GCMAccountTrackerTest, AccountRemoved) {
Colin Blundell354f2212018-07-16 14:45:08414 std::string account_id1 = AddPrimaryAccount(kEmail1);
415 std::string account_id2 = AddAccount(kEmail2);
[email protected]641c8cc72014-07-02 00:33:06416
417 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06418 IssueAccessToken(account_id1);
419 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52420 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06421
fgorski83afd872014-10-16 01:11:52422 driver()->ResetResults();
423 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06424
Colin Blundella1b7c902018-06-29 06:28:06425 RemoveAccount(account_id2);
fgorski83afd872014-10-16 01:11:52426 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06427
fgorski58b9dfc2014-09-29 16:46:18428 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06429 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52430 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06431}
432
433TEST_F(GCMAccountTrackerTest, GetTokenFailed) {
Colin Blundell354f2212018-07-16 14:45:08434 std::string account_id1 = AddPrimaryAccount(kEmail1);
435 std::string account_id2 = AddAccount(kEmail2);
[email protected]641c8cc72014-07-02 00:33:06436
437 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06438 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52439 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06440
Colin Blundella1b7c902018-06-29 06:28:06441 IssueError(account_id2);
fgorski83afd872014-10-16 01:11:52442
fgorskibe981e72015-01-26 21:07:19443 // Failed token is not retried any more. Account marked as removed.
444 EXPECT_EQ(0UL, tracker()->get_pending_token_request_count());
fgorski83afd872014-10-16 01:11:52445 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06446
fgorski58b9dfc2014-09-29 16:46:18447 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06448 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52449 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06450}
451
452TEST_F(GCMAccountTrackerTest, GetTokenFailedAccountRemoved) {
Colin Blundell354f2212018-07-16 14:45:08453 std::string account_id1 = AddPrimaryAccount(kEmail1);
454 std::string account_id2 = AddAccount(kEmail2);
[email protected]641c8cc72014-07-02 00:33:06455
456 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06457 IssueAccessToken(account_id1);
[email protected]641c8cc72014-07-02 00:33:06458
fgorski83afd872014-10-16 01:11:52459 driver()->ResetResults();
Colin Blundella1b7c902018-06-29 06:28:06460 RemoveAccount(account_id2);
461 IssueError(account_id2);
fgorski83afd872014-10-16 01:11:52462
463 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06464
fgorski58b9dfc2014-09-29 16:46:18465 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06466 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52467 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06468}
469
470TEST_F(GCMAccountTrackerTest, AccountRemovedWhileRequestsPending) {
Colin Blundell354f2212018-07-16 14:45:08471 std::string account_id1 = AddPrimaryAccount(kEmail1);
472 std::string account_id2 = AddAccount(kEmail2);
[email protected]641c8cc72014-07-02 00:33:06473
474 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06475 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52476 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06477
Colin Blundella1b7c902018-06-29 06:28:06478 RemoveAccount(account_id2);
479 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52480 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06481
fgorski58b9dfc2014-09-29 16:46:18482 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06483 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52484 VerifyAccountTokens(expected_accounts, driver()->accounts());
485}
[email protected]641c8cc72014-07-02 00:33:06486
fgorski83afd872014-10-16 01:11:52487// Makes sure that tracker observes GCM connection when running.
488TEST_F(GCMAccountTrackerTest, TrackerObservesConnection) {
Ivan Kotenkov75b1c3a2017-10-24 14:47:24489 EXPECT_EQ(nullptr, driver()->last_connection_observer());
fgorski83afd872014-10-16 01:11:52490 tracker()->Start();
491 EXPECT_EQ(tracker(), driver()->last_connection_observer());
492 tracker()->Shutdown();
493 EXPECT_EQ(tracker(), driver()->last_removed_connection_observer());
494}
495
496// Makes sure that token fetching happens only after connection is established.
497TEST_F(GCMAccountTrackerTest, PostponeTokenFetchingUntilConnected) {
498 driver()->SetConnected(false);
Colin Blundell354f2212018-07-16 14:45:08499 std::string account_id1 = StartPrimaryAccountAddition(kEmail1);
fgorski83afd872014-10-16 01:11:52500 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06501 FinishAccountAddition(account_id1);
fgorski83afd872014-10-16 01:11:52502
503 EXPECT_EQ(0UL, tracker()->get_pending_token_request_count());
504 driver()->SetConnected(true);
505
506 EXPECT_EQ(1UL, tracker()->get_pending_token_request_count());
507}
508
fgorski9a405102014-11-19 01:25:16509TEST_F(GCMAccountTrackerTest, InvalidateExpiredTokens) {
Colin Blundell354f2212018-07-16 14:45:08510 std::string account_id1 = StartPrimaryAccountAddition(kEmail1);
511 std::string account_id2 = StartAccountAddition(kEmail2);
fgorski83afd872014-10-16 01:11:52512 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06513 FinishAccountAddition(account_id1);
514 FinishAccountAddition(account_id2);
fgorski83afd872014-10-16 01:11:52515
516 EXPECT_EQ(2UL, tracker()->get_pending_token_request_count());
517
Colin Blundella1b7c902018-06-29 06:28:06518 IssueExpiredAccessToken(account_id1);
519 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52520 // Because the first token is expired, we expect the sanitize to kick in and
521 // clean it up before the SetAccessToken is called. This also means a new
522 // token request will be issued
523 EXPECT_FALSE(driver()->update_accounts_called());
524 EXPECT_EQ(1UL, tracker()->get_pending_token_request_count());
[email protected]641c8cc72014-07-02 00:33:06525}
526
fgorski9a405102014-11-19 01:25:16527// Testing for whether there are still more tokens to be fetched. Typically the
528// need for token fetching triggers immediate request, unless there is no
529// connection, that is why connection is set on and off in this test.
530TEST_F(GCMAccountTrackerTest, IsTokenFetchingRequired) {
531 tracker()->Start();
532 driver()->SetConnected(false);
533 EXPECT_FALSE(IsFetchingRequired());
Colin Blundell354f2212018-07-16 14:45:08534 std::string account_id1 = StartPrimaryAccountAddition(kEmail1);
Colin Blundella1b7c902018-06-29 06:28:06535 FinishAccountAddition(account_id1);
fgorski9a405102014-11-19 01:25:16536 EXPECT_TRUE(IsFetchingRequired());
537
538 driver()->SetConnected(true);
539 EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started.
Colin Blundella1b7c902018-06-29 06:28:06540 IssueAccessToken(account_id1);
fgorski9a405102014-11-19 01:25:16541 EXPECT_FALSE(IsFetchingRequired());
542
Colin Blundell354f2212018-07-16 14:45:08543 std::string account_id2 = StartAccountAddition(kEmail2);
Colin Blundella1b7c902018-06-29 06:28:06544 FinishAccountAddition(account_id2);
Colin Blundellaa0f4f02018-06-28 14:41:45545 EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started.
fgorski9a405102014-11-19 01:25:16546
Colin Blundellaa0f4f02018-06-28 14:41:45547 // Disconnect the driver again so that the access token request being
548 // fulfilled doesn't immediately cause another access token request (which
549 // then would cause IsFetchingRequired() to be false, preventing us from
550 // distinguishing this case from the case where IsFetchingRequired() is false
551 // because GCMAccountTracker didn't detect that a new access token needs to be
552 // fetched).
553 driver()->SetConnected(false);
Colin Blundella1b7c902018-06-29 06:28:06554 IssueExpiredAccessToken(account_id2);
Colin Blundellaa0f4f02018-06-28 14:41:45555
556 // Make sure that if the token was expired it is marked as being needed again.
fgorski9a405102014-11-19 01:25:16557 EXPECT_TRUE(IsFetchingRequired());
558}
559
560// Tests what is the expected time to the next token fetching.
561TEST_F(GCMAccountTrackerTest, GetTimeToNextTokenReporting) {
562 tracker()->Start();
563 // At this point the last token fetch time is never.
564 EXPECT_EQ(base::TimeDelta(), GetTimeToNextTokenReporting());
565
fgorski702e92ed2015-01-29 19:22:02566 // Regular case. The tokens have been just reported.
fgorski9a405102014-11-19 01:25:16567 driver()->SetLastTokenFetchTime(base::Time::Now());
568 EXPECT_TRUE(GetTimeToNextTokenReporting() <=
569 base::TimeDelta::FromSeconds(12 * 60 * 60));
fgorski702e92ed2015-01-29 19:22:02570
571 // A case when gcm driver is not yet initialized.
572 driver()->SetLastTokenFetchTime(base::Time::Max());
573 EXPECT_EQ(base::TimeDelta::FromSeconds(12 * 60 * 60),
574 GetTimeToNextTokenReporting());
575
576 // A case when token reporting calculation is expected to result in more than
577 // 12 hours, in which case we expect exactly 12 hours.
578 driver()->SetLastTokenFetchTime(base::Time::Now() +
579 base::TimeDelta::FromDays(2));
580 EXPECT_EQ(base::TimeDelta::FromSeconds(12 * 60 * 60),
581 GetTimeToNextTokenReporting());
fgorski9a405102014-11-19 01:25:16582}
583
584// Tests conditions when token reporting is required.
585TEST_F(GCMAccountTrackerTest, IsTokenReportingRequired) {
586 tracker()->Start();
587 // Required because it is overdue.
588 EXPECT_TRUE(IsTokenReportingRequired());
589
590 // Not required because it just happened.
591 driver()->SetLastTokenFetchTime(base::Time::Now());
592 EXPECT_FALSE(IsTokenReportingRequired());
593
Colin Blundell354f2212018-07-16 14:45:08594 std::string account_id1 = AddPrimaryAccount(kEmail1);
Colin Blundella1b7c902018-06-29 06:28:06595 IssueAccessToken(account_id1);
fgorski9a405102014-11-19 01:25:16596 driver()->ResetResults();
597 // Reporting was triggered, which means testing for required will give false,
598 // but we have the update call.
Colin Blundella1b7c902018-06-29 06:28:06599 RemoveAccount(account_id1);
fgorski9a405102014-11-19 01:25:16600 EXPECT_TRUE(driver()->update_accounts_called());
601 EXPECT_FALSE(IsTokenReportingRequired());
602}
603
[email protected]641c8cc72014-07-02 00:33:06604// TODO(fgorski): Add test for adding account after removal >> make sure it does
605// not mark removal.
606
607} // namespace gcm