blob: d3841bdcd44b99089016621aa573c686353df2a3 [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"
16#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
17#include "components/signin/core/browser/fake_signin_manager.h"
18#include "components/signin/core/browser/test_signin_client.h"
19#include "components/sync_preferences/testing_pref_service_syncable.h"
[email protected]641c8cc72014-07-02 00:33:0620#include "google_apis/gaia/fake_oauth2_token_service.h"
21#include "google_apis/gaia/google_service_auth_error.h"
22#include "net/http/http_status_code.h"
23#include "net/url_request/test_url_fetcher_factory.h"
24#include "net/url_request/url_request_test_util.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
27namespace gcm {
28
29namespace {
30
Colin Blundellbf6d4c5f2018-05-16 11:12:2931#if defined(OS_CHROMEOS)
32using SigninManagerForTest = FakeSigninManagerBase;
33#else
34using SigninManagerForTest = FakeSigninManager;
35#endif // OS_CHROMEOS
36
Colin Blundella1b7c902018-06-29 06:28:0637const char kGaiaId1[] = "account_1";
38const char kEmail1[] = "[email protected]";
39const char kGaiaId2[] = "account_2";
40const char kEmail2[] = "[email protected]";
[email protected]641c8cc72014-07-02 00:33:0641
Colin Blundella1b7c902018-06-29 06:28:0642std::string AccountIdToObfuscatedId(const std::string& account_id) {
43 return "obfid-" + account_id;
[email protected]641c8cc72014-07-02 00:33:0644}
45
Colin Blundella1b7c902018-06-29 06:28:0646std::string GetValidTokenInfoResponse(const std::string& account_id) {
47 return std::string("{ \"id\": \"") + AccountIdToObfuscatedId(account_id) +
[email protected]641c8cc72014-07-02 00:33:0648 "\" }";
49}
50
Colin Blundella1b7c902018-06-29 06:28:0651std::string MakeAccessToken(const std::string& account_id) {
52 return "access_token-" + account_id;
[email protected]641c8cc72014-07-02 00:33:0653}
54
Colin Blundella1b7c902018-06-29 06:28:0655GCMClient::AccountTokenInfo MakeAccountToken(const std::string& account_id) {
fgorski58b9dfc2014-09-29 16:46:1856 GCMClient::AccountTokenInfo token_info;
Colin Blundella1b7c902018-06-29 06:28:0657 token_info.account_id = account_id;
58
59 // TODO(https://crbug.com/856170): This *should* be expected to be the email
60 // address for the given account, but there is a bug in AccountTracker that
61 // means that |token_info.email| actually gets populated with the account ID
62 // by the production code. Hence the test expectation has to match what the
63 // production code actually does :). If/when that bug gets fixed, this
64 // function should be changed to take in the email address as well as the
65 // account ID and populate this field with the email address.
66 token_info.email = account_id;
67 token_info.access_token = MakeAccessToken(account_id);
fgorski58b9dfc2014-09-29 16:46:1868 return token_info;
69}
70
71void VerifyAccountTokens(
72 const std::vector<GCMClient::AccountTokenInfo>& expected_tokens,
73 const std::vector<GCMClient::AccountTokenInfo>& actual_tokens) {
74 EXPECT_EQ(expected_tokens.size(), actual_tokens.size());
75 for (std::vector<GCMClient::AccountTokenInfo>::const_iterator
76 expected_iter = expected_tokens.begin(),
77 actual_iter = actual_tokens.begin();
78 expected_iter != expected_tokens.end() &&
79 actual_iter != actual_tokens.end();
80 ++expected_iter, ++actual_iter) {
81 EXPECT_EQ(expected_iter->account_id, actual_iter->account_id);
82 EXPECT_EQ(expected_iter->email, actual_iter->email);
83 EXPECT_EQ(expected_iter->access_token, actual_iter->access_token);
84 }
85}
86
fgorski83afd872014-10-16 01:11:5287// This version of FakeGCMDriver is customized around handling accounts and
88// connection events for testing GCMAccountTracker.
89class CustomFakeGCMDriver : public FakeGCMDriver {
90 public:
91 CustomFakeGCMDriver();
Daniel Chenga542fca2014-10-21 09:51:2992 ~CustomFakeGCMDriver() override;
fgorski83afd872014-10-16 01:11:5293
94 // GCMDriver overrides:
Daniel Chenga542fca2014-10-21 09:51:2995 void SetAccountTokens(
fgorski83afd872014-10-16 01:11:5296 const std::vector<GCMClient::AccountTokenInfo>& account_tokens) override;
Daniel Chenga542fca2014-10-21 09:51:2997 void AddConnectionObserver(GCMConnectionObserver* observer) override;
98 void RemoveConnectionObserver(GCMConnectionObserver* observer) override;
99 bool IsConnected() const override { return connected_; }
fgorski9a405102014-11-19 01:25:16100 base::Time GetLastTokenFetchTime() override;
101 void SetLastTokenFetchTime(const base::Time& time) override;
fgorski83afd872014-10-16 01:11:52102
103 // Test results and helpers.
104 void SetConnected(bool connected);
105 void ResetResults();
106 bool update_accounts_called() const { return update_accounts_called_; }
107 const std::vector<GCMClient::AccountTokenInfo>& accounts() const {
108 return accounts_;
109 }
110 const GCMConnectionObserver* last_connection_observer() const {
111 return last_connection_observer_;
112 }
113 const GCMConnectionObserver* last_removed_connection_observer() const {
114 return removed_connection_observer_;
115 }
116
117 private:
118 bool connected_;
119 std::vector<GCMClient::AccountTokenInfo> accounts_;
120 bool update_accounts_called_;
121 GCMConnectionObserver* last_connection_observer_;
122 GCMConnectionObserver* removed_connection_observer_;
123 net::IPEndPoint ip_endpoint_;
fgorski9a405102014-11-19 01:25:16124 base::Time last_token_fetch_time_;
fgorski83afd872014-10-16 01:11:52125
126 DISALLOW_COPY_AND_ASSIGN(CustomFakeGCMDriver);
127};
128
129CustomFakeGCMDriver::CustomFakeGCMDriver()
130 : connected_(true),
131 update_accounts_called_(false),
Ivan Kotenkov75b1c3a2017-10-24 14:47:24132 last_connection_observer_(nullptr),
133 removed_connection_observer_(nullptr) {}
fgorski83afd872014-10-16 01:11:52134
135CustomFakeGCMDriver::~CustomFakeGCMDriver() {
136}
137
138void CustomFakeGCMDriver::SetAccountTokens(
139 const std::vector<GCMClient::AccountTokenInfo>& accounts) {
140 update_accounts_called_ = true;
141 accounts_ = accounts;
142}
143
144void CustomFakeGCMDriver::AddConnectionObserver(
145 GCMConnectionObserver* observer) {
146 last_connection_observer_ = observer;
147}
148
149void CustomFakeGCMDriver::RemoveConnectionObserver(
150 GCMConnectionObserver* observer) {
151 removed_connection_observer_ = observer;
152}
153
154void CustomFakeGCMDriver::SetConnected(bool connected) {
155 connected_ = connected;
156 if (connected && last_connection_observer_)
157 last_connection_observer_->OnConnected(ip_endpoint_);
158}
159
160void CustomFakeGCMDriver::ResetResults() {
161 accounts_.clear();
162 update_accounts_called_ = false;
Ivan Kotenkov75b1c3a2017-10-24 14:47:24163 last_connection_observer_ = nullptr;
164 removed_connection_observer_ = nullptr;
fgorski83afd872014-10-16 01:11:52165}
166
fgorski9a405102014-11-19 01:25:16167
168base::Time CustomFakeGCMDriver::GetLastTokenFetchTime() {
169 return last_token_fetch_time_;
170}
171
172void CustomFakeGCMDriver::SetLastTokenFetchTime(const base::Time& time) {
173 last_token_fetch_time_ = time;
174}
175
[email protected]641c8cc72014-07-02 00:33:06176} // namespace
177
178class GCMAccountTrackerTest : public testing::Test {
179 public:
180 GCMAccountTrackerTest();
dchenge1bc7982014-10-30 00:32:40181 ~GCMAccountTrackerTest() override;
[email protected]641c8cc72014-07-02 00:33:06182
Colin Blundell04720562018-05-14 09:19:40183 // Helpers to pass fake info to the tracker. Tests should have either a pair
Colin Blundellbf6d4c5f2018-05-16 11:12:29184 // of Start(Primary)/FinishAccountAddition or Add(Primary)Account per
Colin Blundella1b7c902018-06-29 06:28:06185 // account. Don't mix. Any methods that return an std::string are returning
186 // the account ID of the newly-added account, which can then be passed into
187 // any methods that take in an account ID.
Colin Blundell04720562018-05-14 09:19:40188 // Call to RemoveAccount is not mandatory.
Colin Blundella1b7c902018-06-29 06:28:06189 std::string StartAccountAddition(const std::string& gaia_id,
190 const std::string& email);
191 std::string StartPrimaryAccountAddition(const std::string& gaia_id,
192 const std::string& email);
193 void FinishAccountAddition(const std::string& account_id);
194 std::string AddAccount(const std::string& gaia_id, const std::string& email);
195 std::string AddPrimaryAccount(const std::string& gaia_id,
196 const std::string& email);
197 void RemoveAccount(const std::string& account_id);
[email protected]641c8cc72014-07-02 00:33:06198
199 // Helpers for dealing with OAuth2 access token requests.
Colin Blundella1b7c902018-06-29 06:28:06200 void IssueAccessToken(const std::string& account_id);
201 void IssueExpiredAccessToken(const std::string& account_id);
202 void IssueError(const std::string& account_id);
[email protected]641c8cc72014-07-02 00:33:06203
fgorski83afd872014-10-16 01:11:52204 // Accessors to account tracker and gcm driver.
[email protected]641c8cc72014-07-02 00:33:06205 GCMAccountTracker* tracker() { return tracker_.get(); }
fgorski83afd872014-10-16 01:11:52206 CustomFakeGCMDriver* driver() { return &driver_; }
[email protected]641c8cc72014-07-02 00:33:06207
fgorski9a405102014-11-19 01:25:16208 // Accessors to private methods of account tracker.
209 bool IsFetchingRequired() const;
210 bool IsTokenReportingRequired() const;
211 base::TimeDelta GetTimeToNextTokenReporting() const;
212
[email protected]641c8cc72014-07-02 00:33:06213 private:
fgorski83afd872014-10-16 01:11:52214 CustomFakeGCMDriver driver_;
[email protected]641c8cc72014-07-02 00:33:06215
216 base::MessageLoop message_loop_;
217 net::TestURLFetcherFactory test_fetcher_factory_;
Colin Blundellbf6d4c5f2018-05-16 11:12:29218 sync_preferences::TestingPrefServiceSyncable pref_service_;
219 AccountTrackerService account_tracker_service_;
220 std::unique_ptr<TestSigninClient> test_signin_client_;
221 std::unique_ptr<SigninManagerForTest> fake_signin_manager_;
222 std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_;
dchenga77e28eb2016-04-21 21:34:37223 std::unique_ptr<GCMAccountTracker> tracker_;
[email protected]641c8cc72014-07-02 00:33:06224};
225
fgorski83afd872014-10-16 01:11:52226GCMAccountTrackerTest::GCMAccountTrackerTest() {
Colin Blundellbf6d4c5f2018-05-16 11:12:29227 fake_token_service_.reset(new FakeProfileOAuth2TokenService());
[email protected]641c8cc72014-07-02 00:33:06228
Colin Blundellbf6d4c5f2018-05-16 11:12:29229 test_signin_client_.reset(new TestSigninClient(&pref_service_));
230#if defined(OS_CHROMEOS)
231 fake_signin_manager_.reset(new SigninManagerForTest(
232 test_signin_client_.get(), &account_tracker_service_));
233#else
234 fake_signin_manager_.reset(new SigninManagerForTest(
235 test_signin_client_.get(), fake_token_service_.get(),
236 &account_tracker_service_, nullptr));
237#endif
238
239 AccountTrackerService::RegisterPrefs(pref_service_.registry());
240 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
241 SigninManagerBase::RegisterPrefs(pref_service_.registry());
242 account_tracker_service_.Initialize(test_signin_client_.get());
243
Colin Blundell021e3e4d2018-04-19 01:03:24244 std::unique_ptr<AccountTracker> gaia_account_tracker(new AccountTracker(
Colin Blundellf8789932018-05-22 11:35:56245 fake_signin_manager_.get(), fake_token_service_.get(),
Colin Blundell021e3e4d2018-04-19 01:03:24246 new net::TestURLRequestContextGetter(message_loop_.task_runner())));
[email protected]641c8cc72014-07-02 00:33:06247
Colin Blundellf8789932018-05-22 11:35:56248 tracker_.reset(new GCMAccountTracker(std::move(gaia_account_tracker),
249 fake_token_service_.get(), &driver_));
[email protected]641c8cc72014-07-02 00:33:06250}
251
252GCMAccountTrackerTest::~GCMAccountTrackerTest() {
253 if (tracker_)
254 tracker_->Shutdown();
255}
256
Colin Blundella1b7c902018-06-29 06:28:06257std::string GCMAccountTrackerTest::StartAccountAddition(
258 const std::string& gaia_id,
259 const std::string& email) {
260 std::string account_id =
261 account_tracker_service_.SeedAccountInfo(gaia_id, email);
262 fake_token_service_->UpdateCredentials(account_id, "fake_refresh_token");
263 return account_id;
Colin Blundellbf6d4c5f2018-05-16 11:12:29264}
265
Colin Blundella1b7c902018-06-29 06:28:06266std::string GCMAccountTrackerTest::StartPrimaryAccountAddition(
267 const std::string& gaia_id,
268 const std::string& email) {
Colin Blundellbf6d4c5f2018-05-16 11:12:29269// NOTE: Setting of the primary account info must be done first on ChromeOS
270// to ensure that AccountTracker and GCMAccountTracker respond as expected
271// when the token is added to the token service.
272// TODO(blundell): On non-ChromeOS, it would be good to add tests wherein
273// setting of the primary account is done afterward to check that the flow
274// that ensues from the GoogleSigninSucceeded callback firing works as
275// expected.
276#if defined(OS_CHROMEOS)
Colin Blundella1b7c902018-06-29 06:28:06277 fake_signin_manager_->SignIn(email);
Colin Blundellbf6d4c5f2018-05-16 11:12:29278#else
Colin Blundella1b7c902018-06-29 06:28:06279 fake_signin_manager_->SignIn(gaia_id, email, "" /* password */);
Colin Blundellbf6d4c5f2018-05-16 11:12:29280#endif
Colin Blundella1b7c902018-06-29 06:28:06281
282 std::string account_id = fake_signin_manager_->GetAuthenticatedAccountId();
283 fake_token_service_->UpdateCredentials(account_id, "fake_refresh_token");
284
285 return 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 Blundella1b7c902018-06-29 06:28:06300std::string GCMAccountTrackerTest::AddPrimaryAccount(const std::string& gaia_id,
301 const std::string& email) {
302 std::string account_id = StartPrimaryAccountAddition(gaia_id, email);
303 FinishAccountAddition(account_id);
304 return account_id;
Colin Blundellbf6d4c5f2018-05-16 11:12:29305}
306
Colin Blundella1b7c902018-06-29 06:28:06307std::string GCMAccountTrackerTest::AddAccount(const std::string& gaia_id,
308 const std::string& email) {
309 std::string account_id = StartAccountAddition(gaia_id, email);
310 FinishAccountAddition(account_id);
311 return account_id;
[email protected]641c8cc72014-07-02 00:33:06312}
313
Colin Blundella1b7c902018-06-29 06:28:06314void GCMAccountTrackerTest::RemoveAccount(const std::string& account_id) {
315 fake_token_service_->RevokeCredentials(account_id);
[email protected]641c8cc72014-07-02 00:33:06316}
317
Colin Blundella1b7c902018-06-29 06:28:06318void GCMAccountTrackerTest::IssueAccessToken(const std::string& account_id) {
[email protected]641c8cc72014-07-02 00:33:06319 fake_token_service_->IssueAllTokensForAccount(
Colin Blundella1b7c902018-06-29 06:28:06320 account_id, MakeAccessToken(account_id), base::Time::Max());
[email protected]641c8cc72014-07-02 00:33:06321}
322
fgorski83afd872014-10-16 01:11:52323void GCMAccountTrackerTest::IssueExpiredAccessToken(
Colin Blundella1b7c902018-06-29 06:28:06324 const std::string& account_id) {
fgorski83afd872014-10-16 01:11:52325 fake_token_service_->IssueAllTokensForAccount(
Colin Blundella1b7c902018-06-29 06:28:06326 account_id, MakeAccessToken(account_id), base::Time::Now());
fgorski83afd872014-10-16 01:11:52327}
328
Colin Blundella1b7c902018-06-29 06:28:06329void GCMAccountTrackerTest::IssueError(const std::string& account_id) {
[email protected]641c8cc72014-07-02 00:33:06330 fake_token_service_->IssueErrorForAllPendingRequestsForAccount(
Colin Blundella1b7c902018-06-29 06:28:06331 account_id,
[email protected]641c8cc72014-07-02 00:33:06332 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
333}
334
fgorski9a405102014-11-19 01:25:16335bool GCMAccountTrackerTest::IsFetchingRequired() const {
336 return tracker_->IsTokenFetchingRequired();
337}
338
339bool GCMAccountTrackerTest::IsTokenReportingRequired() const {
340 return tracker_->IsTokenReportingRequired();
341}
342
343base::TimeDelta GCMAccountTrackerTest::GetTimeToNextTokenReporting() const {
344 return tracker_->GetTimeToNextTokenReporting();
345}
346
[email protected]641c8cc72014-07-02 00:33:06347TEST_F(GCMAccountTrackerTest, NoAccounts) {
fgorski83afd872014-10-16 01:11:52348 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06349 tracker()->Start();
[email protected]7df5ef22014-07-17 07:35:58350 // Callback should not be called if there where no accounts provided.
fgorski83afd872014-10-16 01:11:52351 EXPECT_FALSE(driver()->update_accounts_called());
352 EXPECT_TRUE(driver()->accounts().empty());
[email protected]641c8cc72014-07-02 00:33:06353}
354
355// Verifies that callback is called after a token is issued for a single account
356// with a specific scope. In this scenario, the underlying account tracker is
357// still working when the CompleteCollectingTokens is called for the first time.
358TEST_F(GCMAccountTrackerTest, SingleAccount) {
Colin Blundella1b7c902018-06-29 06:28:06359 std::string account_id1 = StartPrimaryAccountAddition(kGaiaId1, kEmail1);
[email protected]641c8cc72014-07-02 00:33:06360
361 tracker()->Start();
362 // We don't have any accounts to report, but given the inner account tracker
363 // is still working we don't make a call with empty accounts list.
fgorski83afd872014-10-16 01:11:52364 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06365
366 // This concludes the work of inner account tracker.
Colin Blundella1b7c902018-06-29 06:28:06367 FinishAccountAddition(account_id1);
368 IssueAccessToken(account_id1);
[email protected]641c8cc72014-07-02 00:33:06369
fgorski83afd872014-10-16 01:11:52370 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06371
fgorski58b9dfc2014-09-29 16:46:18372 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06373 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52374 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06375}
376
377TEST_F(GCMAccountTrackerTest, MultipleAccounts) {
Colin Blundella1b7c902018-06-29 06:28:06378 std::string account_id1 = StartPrimaryAccountAddition(kGaiaId1, kEmail1);
Colin Blundellbf6d4c5f2018-05-16 11:12:29379
Colin Blundella1b7c902018-06-29 06:28:06380 std::string account_id2 = StartAccountAddition(kGaiaId2, kEmail2);
[email protected]641c8cc72014-07-02 00:33:06381
382 tracker()->Start();
fgorski83afd872014-10-16 01:11:52383 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06384
Colin Blundella1b7c902018-06-29 06:28:06385 FinishAccountAddition(account_id1);
386 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52387 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06388
Colin Blundella1b7c902018-06-29 06:28:06389 FinishAccountAddition(account_id2);
390 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52391 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06392
fgorski58b9dfc2014-09-29 16:46:18393 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06394 expected_accounts.push_back(MakeAccountToken(account_id1));
395 expected_accounts.push_back(MakeAccountToken(account_id2));
fgorski83afd872014-10-16 01:11:52396 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06397}
398
399TEST_F(GCMAccountTrackerTest, AccountAdded) {
400 tracker()->Start();
fgorski83afd872014-10-16 01:11:52401 driver()->ResetResults();
[email protected]641c8cc72014-07-02 00:33:06402
Colin Blundella1b7c902018-06-29 06:28:06403 std::string account_id1 = AddPrimaryAccount(kGaiaId1, kEmail1);
fgorski83afd872014-10-16 01:11:52404 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06405
Colin Blundella1b7c902018-06-29 06:28:06406 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52407 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06408
fgorski58b9dfc2014-09-29 16:46:18409 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06410 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52411 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06412}
413
414TEST_F(GCMAccountTrackerTest, AccountRemoved) {
Colin Blundella1b7c902018-06-29 06:28:06415 std::string account_id1 = AddPrimaryAccount(kGaiaId1, kEmail1);
416 std::string account_id2 = AddAccount(kGaiaId2, kEmail2);
[email protected]641c8cc72014-07-02 00:33:06417
418 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06419 IssueAccessToken(account_id1);
420 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52421 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06422
fgorski83afd872014-10-16 01:11:52423 driver()->ResetResults();
424 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06425
Colin Blundella1b7c902018-06-29 06:28:06426 RemoveAccount(account_id2);
fgorski83afd872014-10-16 01:11:52427 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06428
fgorski58b9dfc2014-09-29 16:46:18429 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06430 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52431 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06432}
433
434TEST_F(GCMAccountTrackerTest, GetTokenFailed) {
Colin Blundella1b7c902018-06-29 06:28:06435 std::string account_id1 = AddPrimaryAccount(kGaiaId1, kEmail1);
436 std::string account_id2 = AddAccount(kGaiaId2, kEmail2);
[email protected]641c8cc72014-07-02 00:33:06437
438 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06439 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52440 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06441
Colin Blundella1b7c902018-06-29 06:28:06442 IssueError(account_id2);
fgorski83afd872014-10-16 01:11:52443
fgorskibe981e72015-01-26 21:07:19444 // Failed token is not retried any more. Account marked as removed.
445 EXPECT_EQ(0UL, tracker()->get_pending_token_request_count());
fgorski83afd872014-10-16 01:11:52446 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06447
fgorski58b9dfc2014-09-29 16:46:18448 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06449 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52450 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06451}
452
453TEST_F(GCMAccountTrackerTest, GetTokenFailedAccountRemoved) {
Colin Blundella1b7c902018-06-29 06:28:06454 std::string account_id1 = AddPrimaryAccount(kGaiaId1, kEmail1);
455 std::string account_id2 = AddAccount(kGaiaId2, kEmail2);
[email protected]641c8cc72014-07-02 00:33:06456
457 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06458 IssueAccessToken(account_id1);
[email protected]641c8cc72014-07-02 00:33:06459
fgorski83afd872014-10-16 01:11:52460 driver()->ResetResults();
Colin Blundella1b7c902018-06-29 06:28:06461 RemoveAccount(account_id2);
462 IssueError(account_id2);
fgorski83afd872014-10-16 01:11:52463
464 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06465
fgorski58b9dfc2014-09-29 16:46:18466 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06467 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52468 VerifyAccountTokens(expected_accounts, driver()->accounts());
[email protected]641c8cc72014-07-02 00:33:06469}
470
471TEST_F(GCMAccountTrackerTest, AccountRemovedWhileRequestsPending) {
Colin Blundella1b7c902018-06-29 06:28:06472 std::string account_id1 = AddPrimaryAccount(kGaiaId1, kEmail1);
473 std::string account_id2 = AddAccount(kGaiaId2, kEmail2);
[email protected]641c8cc72014-07-02 00:33:06474
475 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06476 IssueAccessToken(account_id1);
fgorski83afd872014-10-16 01:11:52477 EXPECT_FALSE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06478
Colin Blundella1b7c902018-06-29 06:28:06479 RemoveAccount(account_id2);
480 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52481 EXPECT_TRUE(driver()->update_accounts_called());
[email protected]641c8cc72014-07-02 00:33:06482
fgorski58b9dfc2014-09-29 16:46:18483 std::vector<GCMClient::AccountTokenInfo> expected_accounts;
Colin Blundella1b7c902018-06-29 06:28:06484 expected_accounts.push_back(MakeAccountToken(account_id1));
fgorski83afd872014-10-16 01:11:52485 VerifyAccountTokens(expected_accounts, driver()->accounts());
486}
[email protected]641c8cc72014-07-02 00:33:06487
fgorski83afd872014-10-16 01:11:52488// Makes sure that tracker observes GCM connection when running.
489TEST_F(GCMAccountTrackerTest, TrackerObservesConnection) {
Ivan Kotenkov75b1c3a2017-10-24 14:47:24490 EXPECT_EQ(nullptr, driver()->last_connection_observer());
fgorski83afd872014-10-16 01:11:52491 tracker()->Start();
492 EXPECT_EQ(tracker(), driver()->last_connection_observer());
493 tracker()->Shutdown();
494 EXPECT_EQ(tracker(), driver()->last_removed_connection_observer());
495}
496
497// Makes sure that token fetching happens only after connection is established.
498TEST_F(GCMAccountTrackerTest, PostponeTokenFetchingUntilConnected) {
499 driver()->SetConnected(false);
Colin Blundella1b7c902018-06-29 06:28:06500 std::string account_id1 = StartPrimaryAccountAddition(kGaiaId1, kEmail1);
fgorski83afd872014-10-16 01:11:52501 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06502 FinishAccountAddition(account_id1);
fgorski83afd872014-10-16 01:11:52503
504 EXPECT_EQ(0UL, tracker()->get_pending_token_request_count());
505 driver()->SetConnected(true);
506
507 EXPECT_EQ(1UL, tracker()->get_pending_token_request_count());
508}
509
fgorski9a405102014-11-19 01:25:16510TEST_F(GCMAccountTrackerTest, InvalidateExpiredTokens) {
Colin Blundella1b7c902018-06-29 06:28:06511 std::string account_id1 = StartPrimaryAccountAddition(kGaiaId1, kEmail1);
512 std::string account_id2 = StartAccountAddition(kGaiaId2, kEmail2);
fgorski83afd872014-10-16 01:11:52513 tracker()->Start();
Colin Blundella1b7c902018-06-29 06:28:06514 FinishAccountAddition(account_id1);
515 FinishAccountAddition(account_id2);
fgorski83afd872014-10-16 01:11:52516
517 EXPECT_EQ(2UL, tracker()->get_pending_token_request_count());
518
Colin Blundella1b7c902018-06-29 06:28:06519 IssueExpiredAccessToken(account_id1);
520 IssueAccessToken(account_id2);
fgorski83afd872014-10-16 01:11:52521 // Because the first token is expired, we expect the sanitize to kick in and
522 // clean it up before the SetAccessToken is called. This also means a new
523 // token request will be issued
524 EXPECT_FALSE(driver()->update_accounts_called());
525 EXPECT_EQ(1UL, tracker()->get_pending_token_request_count());
[email protected]641c8cc72014-07-02 00:33:06526}
527
fgorski9a405102014-11-19 01:25:16528// Testing for whether there are still more tokens to be fetched. Typically the
529// need for token fetching triggers immediate request, unless there is no
530// connection, that is why connection is set on and off in this test.
531TEST_F(GCMAccountTrackerTest, IsTokenFetchingRequired) {
532 tracker()->Start();
533 driver()->SetConnected(false);
534 EXPECT_FALSE(IsFetchingRequired());
Colin Blundella1b7c902018-06-29 06:28:06535 std::string account_id1 = StartPrimaryAccountAddition(kGaiaId1, kEmail1);
536 FinishAccountAddition(account_id1);
fgorski9a405102014-11-19 01:25:16537 EXPECT_TRUE(IsFetchingRequired());
538
539 driver()->SetConnected(true);
540 EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started.
Colin Blundella1b7c902018-06-29 06:28:06541 IssueAccessToken(account_id1);
fgorski9a405102014-11-19 01:25:16542 EXPECT_FALSE(IsFetchingRequired());
543
Colin Blundella1b7c902018-06-29 06:28:06544 std::string account_id2 = StartAccountAddition(kGaiaId2, kEmail2);
545 FinishAccountAddition(account_id2);
Colin Blundellaa0f4f02018-06-28 14:41:45546 EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started.
fgorski9a405102014-11-19 01:25:16547
Colin Blundellaa0f4f02018-06-28 14:41:45548 // Disconnect the driver again so that the access token request being
549 // fulfilled doesn't immediately cause another access token request (which
550 // then would cause IsFetchingRequired() to be false, preventing us from
551 // distinguishing this case from the case where IsFetchingRequired() is false
552 // because GCMAccountTracker didn't detect that a new access token needs to be
553 // fetched).
554 driver()->SetConnected(false);
Colin Blundella1b7c902018-06-29 06:28:06555 IssueExpiredAccessToken(account_id2);
Colin Blundellaa0f4f02018-06-28 14:41:45556
557 // Make sure that if the token was expired it is marked as being needed again.
fgorski9a405102014-11-19 01:25:16558 EXPECT_TRUE(IsFetchingRequired());
559}
560
561// Tests what is the expected time to the next token fetching.
562TEST_F(GCMAccountTrackerTest, GetTimeToNextTokenReporting) {
563 tracker()->Start();
564 // At this point the last token fetch time is never.
565 EXPECT_EQ(base::TimeDelta(), GetTimeToNextTokenReporting());
566
fgorski702e92ed2015-01-29 19:22:02567 // Regular case. The tokens have been just reported.
fgorski9a405102014-11-19 01:25:16568 driver()->SetLastTokenFetchTime(base::Time::Now());
569 EXPECT_TRUE(GetTimeToNextTokenReporting() <=
570 base::TimeDelta::FromSeconds(12 * 60 * 60));
fgorski702e92ed2015-01-29 19:22:02571
572 // A case when gcm driver is not yet initialized.
573 driver()->SetLastTokenFetchTime(base::Time::Max());
574 EXPECT_EQ(base::TimeDelta::FromSeconds(12 * 60 * 60),
575 GetTimeToNextTokenReporting());
576
577 // A case when token reporting calculation is expected to result in more than
578 // 12 hours, in which case we expect exactly 12 hours.
579 driver()->SetLastTokenFetchTime(base::Time::Now() +
580 base::TimeDelta::FromDays(2));
581 EXPECT_EQ(base::TimeDelta::FromSeconds(12 * 60 * 60),
582 GetTimeToNextTokenReporting());
fgorski9a405102014-11-19 01:25:16583}
584
585// Tests conditions when token reporting is required.
586TEST_F(GCMAccountTrackerTest, IsTokenReportingRequired) {
587 tracker()->Start();
588 // Required because it is overdue.
589 EXPECT_TRUE(IsTokenReportingRequired());
590
591 // Not required because it just happened.
592 driver()->SetLastTokenFetchTime(base::Time::Now());
593 EXPECT_FALSE(IsTokenReportingRequired());
594
Colin Blundella1b7c902018-06-29 06:28:06595 std::string account_id1 = AddPrimaryAccount(kGaiaId1, kEmail1);
596 IssueAccessToken(account_id1);
fgorski9a405102014-11-19 01:25:16597 driver()->ResetResults();
598 // Reporting was triggered, which means testing for required will give false,
599 // but we have the update call.
Colin Blundella1b7c902018-06-29 06:28:06600 RemoveAccount(account_id1);
fgorski9a405102014-11-19 01:25:16601 EXPECT_TRUE(driver()->update_accounts_called());
602 EXPECT_FALSE(IsTokenReportingRequired());
603}
604
[email protected]641c8cc72014-07-02 00:33:06605// TODO(fgorski): Add test for adding account after removal >> make sure it does
606// not mark removal.
607
608} // namespace gcm