GN + Android: extract android_standalone_library rule.
[chromium-blink-merge.git] / components / signin / core / browser / account_tracker_service_unittest.cc
blobc990b1a15b41d906b51efaa35be33004901171b3
1 // 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.
5 #include <algorithm>
6 #include <vector>
8 #include "base/message_loop/message_loop.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/strings/stringprintf.h"
12 #include "components/signin/core/browser/account_tracker_service.h"
13 #include "components/signin/core/browser/test_signin_client.h"
14 #include "components/signin/core/common/signin_pref_names.h"
15 #include "google_apis/gaia/fake_oauth2_token_service.h"
16 #include "google_apis/gaia/gaia_oauth_client.h"
17 #include "net/http/http_status_code.h"
18 #include "net/url_request/test_url_fetcher_factory.h"
19 #include "net/url_request/url_fetcher_delegate.h"
20 #include "net/url_request/url_request_test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 namespace {
25 enum TrackingEventType {
26 UPDATED,
27 REMOVED,
30 std::string AccountIdToEmail(const std::string account_id) {
31 return account_id + "@gmail.com";
34 std::string AccountIdToGaiaId(const std::string account_id) {
35 return "gaia-" + account_id;
38 class TrackingEvent {
39 public:
40 TrackingEvent(TrackingEventType type,
41 const std::string& account_id,
42 const std::string& gaia_id)
43 : type_(type),
44 account_id_(account_id),
45 gaia_id_(gaia_id) {}
47 TrackingEvent(TrackingEventType type,
48 const std::string& account_id)
49 : type_(type),
50 account_id_(account_id),
51 gaia_id_(AccountIdToGaiaId(account_id)) {}
53 bool operator==(const TrackingEvent& event) const {
54 return type_ == event.type_ && account_id_ == event.account_id_ &&
55 gaia_id_ == event.gaia_id_;
58 std::string ToString() const {
59 const char * typestr = "INVALID";
60 switch (type_) {
61 case UPDATED:
62 typestr = "UPD";
63 break;
64 case REMOVED:
65 typestr = "REM";
66 break;
68 return base::StringPrintf("{ type: %s, account_id: %s, gaia: %s }",
69 typestr,
70 account_id_.c_str(),
71 gaia_id_.c_str());
74 private:
75 friend bool CompareByUser(TrackingEvent a, TrackingEvent b);
77 TrackingEventType type_;
78 std::string account_id_;
79 std::string gaia_id_;
82 bool CompareByUser(TrackingEvent a, TrackingEvent b) {
83 return a.account_id_ < b.account_id_;
86 std::string Str(const std::vector<TrackingEvent>& events) {
87 std::string str = "[";
88 bool needs_comma = false;
89 for (std::vector<TrackingEvent>::const_iterator it =
90 events.begin(); it != events.end(); ++it) {
91 if (needs_comma)
92 str += ",\n ";
93 needs_comma = true;
94 str += it->ToString();
96 str += "]";
97 return str;
100 class AccountTrackerObserver : public AccountTrackerService::Observer {
101 public:
102 AccountTrackerObserver() {}
103 ~AccountTrackerObserver() override {}
105 void Clear();
106 void SortEventsByUser();
108 testing::AssertionResult CheckEvents();
109 testing::AssertionResult CheckEvents(const TrackingEvent& e1);
110 testing::AssertionResult CheckEvents(const TrackingEvent& e1,
111 const TrackingEvent& e2);
112 testing::AssertionResult CheckEvents(const TrackingEvent& e1,
113 const TrackingEvent& e2,
114 const TrackingEvent& e3);
116 private:
117 // AccountTrackerService::Observer implementation
118 void OnAccountUpdated(const AccountTrackerService::AccountInfo& ids) override;
119 void OnAccountRemoved(const AccountTrackerService::AccountInfo& ids) override;
121 testing::AssertionResult CheckEvents(
122 const std::vector<TrackingEvent>& events);
124 std::vector<TrackingEvent> events_;
127 void AccountTrackerObserver::OnAccountUpdated(
128 const AccountTrackerService::AccountInfo& ids) {
129 events_.push_back(TrackingEvent(UPDATED, ids.account_id, ids.gaia));
132 void AccountTrackerObserver::OnAccountRemoved(
133 const AccountTrackerService::AccountInfo& ids) {
134 events_.push_back(TrackingEvent(REMOVED, ids.account_id, ids.gaia));
137 void AccountTrackerObserver::Clear() {
138 events_.clear();
141 void AccountTrackerObserver::SortEventsByUser() {
142 std::stable_sort(events_.begin(), events_.end(), CompareByUser);
145 testing::AssertionResult AccountTrackerObserver::CheckEvents() {
146 std::vector<TrackingEvent> events;
147 return CheckEvents(events);
150 testing::AssertionResult AccountTrackerObserver::CheckEvents(
151 const TrackingEvent& e1) {
152 std::vector<TrackingEvent> events;
153 events.push_back(e1);
154 return CheckEvents(events);
157 testing::AssertionResult AccountTrackerObserver::CheckEvents(
158 const TrackingEvent& e1,
159 const TrackingEvent& e2) {
160 std::vector<TrackingEvent> events;
161 events.push_back(e1);
162 events.push_back(e2);
163 return CheckEvents(events);
166 testing::AssertionResult AccountTrackerObserver::CheckEvents(
167 const TrackingEvent& e1,
168 const TrackingEvent& e2,
169 const TrackingEvent& e3) {
170 std::vector<TrackingEvent> events;
171 events.push_back(e1);
172 events.push_back(e2);
173 events.push_back(e3);
174 return CheckEvents(events);
177 testing::AssertionResult AccountTrackerObserver::CheckEvents(
178 const std::vector<TrackingEvent>& events) {
179 std::string maybe_newline = (events.size() + events_.size()) > 2 ? "\n" : "";
180 testing::AssertionResult result(
181 (events_ == events)
182 ? testing::AssertionSuccess()
183 : (testing::AssertionFailure()
184 << "Expected " << maybe_newline << Str(events) << ", "
185 << maybe_newline << "Got " << maybe_newline << Str(events_)));
186 events_.clear();
187 return result;
190 } // namespace
192 class AccountTrackerServiceTest : public testing::Test {
193 public:
194 AccountTrackerServiceTest() {}
196 ~AccountTrackerServiceTest() override {}
198 void SetUp() override {
199 fake_oauth2_token_service_.reset(new FakeOAuth2TokenService());
201 pref_service_.registry()->RegisterListPref(
202 AccountTrackerService::kAccountInfoPref);
203 pref_service_.registry()->RegisterIntegerPref(
204 prefs::kAccountIdMigrationState,
205 AccountTrackerService::MIGRATION_NOT_STARTED);
206 signin_client_.reset(new TestSigninClient(&pref_service_));
207 signin_client_.get()->SetURLRequestContext(
208 new net::TestURLRequestContextGetter(
209 message_loop_.message_loop_proxy()));
211 account_tracker_.reset(new AccountTrackerService());
212 account_tracker_->Initialize(fake_oauth2_token_service_.get(),
213 signin_client_.get());
214 account_tracker_->AddObserver(&observer_);
217 void TearDown() override {
218 account_tracker_->RemoveObserver(&observer_);
219 account_tracker_->Shutdown();
222 void SimulateTokenAvailable(const std::string& account_id) {
223 fake_oauth2_token_service_->AddAccount(account_id);
226 void SimulateTokenRevoked(const std::string& account_id) {
227 fake_oauth2_token_service_->RemoveAccount(account_id);
230 // Helpers to fake access token and user info fetching
231 void IssueAccessToken(const std::string& account_id) {
232 fake_oauth2_token_service_->IssueAllTokensForAccount(
233 account_id, "access_token-" + account_id, base::Time::Max());
236 std::string GenerateValidTokenInfoResponse(const std::string& account_id) {
237 return base::StringPrintf(
238 "{\"id\": \"%s\", \"email\": \"%s\", \"hd\": \"\"}",
239 AccountIdToGaiaId(account_id).c_str(),
240 AccountIdToEmail(account_id).c_str());
243 void ReturnOAuthUrlFetchSuccess(const std::string& account_id);
244 void ReturnOAuthUrlFetchFailure(const std::string& account_id);
246 base::MessageLoopForIO* message_loop() { return &message_loop_; }
247 AccountTrackerService* account_tracker() { return account_tracker_.get(); }
248 AccountTrackerObserver* observer() { return &observer_; }
249 OAuth2TokenService* token_service() {
250 return fake_oauth2_token_service_.get();
252 TestingPrefServiceSimple* pref_service() { return &pref_service_; }
253 SigninClient* signin_client() { return signin_client_.get(); }
255 private:
256 void ReturnOAuthUrlFetchResults(int fetcher_id,
257 net::HttpStatusCode response_code,
258 const std::string& response_string);
260 base::MessageLoopForIO message_loop_;
261 net::TestURLFetcherFactory test_fetcher_factory_;
262 scoped_ptr<FakeOAuth2TokenService> fake_oauth2_token_service_;
263 TestingPrefServiceSimple pref_service_;
264 scoped_ptr<AccountTrackerService> account_tracker_;
265 AccountTrackerObserver observer_;
266 scoped_ptr<TestSigninClient> signin_client_;
269 void AccountTrackerServiceTest::ReturnOAuthUrlFetchResults(
270 int fetcher_id,
271 net::HttpStatusCode response_code,
272 const std::string& response_string) {
273 net::TestURLFetcher* fetcher =
274 test_fetcher_factory_.GetFetcherByID(fetcher_id);
275 ASSERT_TRUE(fetcher);
276 fetcher->set_response_code(response_code);
277 fetcher->SetResponseString(response_string);
278 fetcher->delegate()->OnURLFetchComplete(fetcher);
281 void AccountTrackerServiceTest::ReturnOAuthUrlFetchSuccess(
282 const std::string& account_id) {
283 IssueAccessToken(account_id);
284 ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId,
285 net::HTTP_OK,
286 GenerateValidTokenInfoResponse(account_id));
289 void AccountTrackerServiceTest::ReturnOAuthUrlFetchFailure(
290 const std::string& account_id) {
291 IssueAccessToken(account_id);
292 ReturnOAuthUrlFetchResults(
293 gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_BAD_REQUEST, "");
296 TEST_F(AccountTrackerServiceTest, Basic) {
299 TEST_F(AccountTrackerServiceTest, TokenAvailable) {
300 SimulateTokenAvailable("alpha");
301 ASSERT_FALSE(account_tracker()->IsAllUserInfoFetched());
302 ASSERT_TRUE(observer()->CheckEvents());
305 TEST_F(AccountTrackerServiceTest, TokenAvailable_Revoked) {
306 SimulateTokenAvailable("alpha");
307 SimulateTokenRevoked("alpha");
308 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
309 ASSERT_TRUE(observer()->CheckEvents());
312 TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo) {
313 SimulateTokenAvailable("alpha");
314 ReturnOAuthUrlFetchSuccess("alpha");
315 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
316 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha")));
319 TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_Revoked) {
320 SimulateTokenAvailable("alpha");
321 ReturnOAuthUrlFetchSuccess("alpha");
322 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
323 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha")));
324 SimulateTokenRevoked("alpha");
325 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(REMOVED, "alpha")));
328 TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfoFailed) {
329 SimulateTokenAvailable("alpha");
330 ReturnOAuthUrlFetchFailure("alpha");
331 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
332 ASSERT_TRUE(observer()->CheckEvents());
335 TEST_F(AccountTrackerServiceTest, TokenAvailableTwice_UserInfoOnce) {
336 SimulateTokenAvailable("alpha");
337 ReturnOAuthUrlFetchSuccess("alpha");
338 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
339 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha")));
341 SimulateTokenAvailable("alpha");
342 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
343 ASSERT_TRUE(observer()->CheckEvents());
346 TEST_F(AccountTrackerServiceTest, TokenAlreadyExists) {
347 SimulateTokenAvailable("alpha");
348 AccountTrackerService tracker;
349 AccountTrackerObserver observer;
350 tracker.AddObserver(&observer);
351 tracker.Initialize(token_service(), signin_client());
352 ASSERT_FALSE(tracker.IsAllUserInfoFetched());
353 ASSERT_TRUE(observer.CheckEvents());
354 tracker.RemoveObserver(&observer);
355 tracker.Shutdown();
358 TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_TwoUserInfo) {
359 SimulateTokenAvailable("alpha");
360 SimulateTokenAvailable("beta");
361 ReturnOAuthUrlFetchSuccess("alpha");
362 ReturnOAuthUrlFetchSuccess("beta");
363 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
364 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha"),
365 TrackingEvent(UPDATED, "beta")));
368 TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_OneUserInfo) {
369 SimulateTokenAvailable("alpha");
370 SimulateTokenAvailable("beta");
371 ReturnOAuthUrlFetchSuccess("beta");
372 ASSERT_FALSE(account_tracker()->IsAllUserInfoFetched());
373 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "beta")));
374 ReturnOAuthUrlFetchSuccess("alpha");
375 ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched());
376 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha")));
379 TEST_F(AccountTrackerServiceTest, GetAccounts) {
380 SimulateTokenAvailable("alpha");
381 SimulateTokenAvailable("beta");
382 SimulateTokenAvailable("gamma");
383 ReturnOAuthUrlFetchSuccess("alpha");
384 ReturnOAuthUrlFetchSuccess("beta");
385 ReturnOAuthUrlFetchSuccess("gamma");
387 std::vector<AccountTrackerService::AccountInfo> infos =
388 account_tracker()->GetAccounts();
390 EXPECT_EQ(3u, infos.size());
391 EXPECT_EQ("alpha", infos[0].account_id);
392 EXPECT_EQ(AccountIdToGaiaId("alpha"), infos[0].gaia);
393 EXPECT_EQ(AccountIdToEmail("alpha"), infos[0].email);
394 EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound,
395 infos[0].hosted_domain);
396 EXPECT_EQ("beta", infos[1].account_id);
397 EXPECT_EQ(AccountIdToGaiaId("beta"), infos[1].gaia);
398 EXPECT_EQ(AccountIdToEmail("beta"), infos[1].email);
399 EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound,
400 infos[1].hosted_domain);
401 EXPECT_EQ("gamma", infos[2].account_id);
402 EXPECT_EQ(AccountIdToGaiaId("gamma"), infos[2].gaia);
403 EXPECT_EQ(AccountIdToEmail("gamma"), infos[2].email);
404 EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound,
405 infos[2].hosted_domain);
408 TEST_F(AccountTrackerServiceTest, GetAccountInfo_Empty) {
409 AccountTrackerService::AccountInfo info =
410 account_tracker()->GetAccountInfo("alpha");
411 ASSERT_EQ("", info.account_id);
414 TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable) {
415 SimulateTokenAvailable("alpha");
416 AccountTrackerService::AccountInfo info =
417 account_tracker()->GetAccountInfo("alpha");
418 ASSERT_EQ("alpha", info.account_id);
419 ASSERT_EQ("", info.gaia);
420 ASSERT_EQ("", info.email);
423 TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable_UserInfo) {
424 SimulateTokenAvailable("alpha");
425 ReturnOAuthUrlFetchSuccess("alpha");
426 AccountTrackerService::AccountInfo info =
427 account_tracker()->GetAccountInfo("alpha");
428 ASSERT_EQ("alpha", info.account_id);
429 ASSERT_EQ(AccountIdToGaiaId("alpha"), info.gaia);
430 ASSERT_EQ(AccountIdToEmail("alpha"), info.email);
431 ASSERT_EQ(AccountTrackerService::kNoHostedDomainFound, info.hosted_domain);
434 TEST_F(AccountTrackerServiceTest, FindAccountInfoByGaiaId) {
435 SimulateTokenAvailable("alpha");
436 ReturnOAuthUrlFetchSuccess("alpha");
438 std::string gaia_id = AccountIdToGaiaId("alpha");
439 AccountTrackerService::AccountInfo info =
440 account_tracker()->FindAccountInfoByGaiaId(gaia_id);
441 ASSERT_EQ("alpha", info.account_id);
442 ASSERT_EQ(gaia_id, info.gaia);
444 gaia_id = AccountIdToGaiaId("beta");
445 info = account_tracker()->FindAccountInfoByGaiaId(gaia_id);
446 ASSERT_EQ("", info.account_id);
449 TEST_F(AccountTrackerServiceTest, FindAccountInfoByEmail) {
450 SimulateTokenAvailable("alpha");
451 ReturnOAuthUrlFetchSuccess("alpha");
453 std::string email = AccountIdToEmail("alpha");
454 AccountTrackerService::AccountInfo info =
455 account_tracker()->FindAccountInfoByEmail(email);
456 ASSERT_EQ("alpha", info.account_id);
457 ASSERT_EQ(email, info.email);
459 // Should also work with "canonically-equal" email addresses.
460 info = account_tracker()->FindAccountInfoByEmail("Alpha@Gmail.COM");
461 ASSERT_EQ("alpha", info.account_id);
462 ASSERT_EQ(email, info.email);
463 info = account_tracker()->FindAccountInfoByEmail("al.pha@gmail.com");
464 ASSERT_EQ("alpha", info.account_id);
465 ASSERT_EQ(email, info.email);
467 email = AccountIdToEmail("beta");
468 info = account_tracker()->FindAccountInfoByEmail(email);
469 ASSERT_EQ("", info.account_id);
472 TEST_F(AccountTrackerServiceTest, Persistence) {
473 // Create a tracker and add two accounts. This should cause the accounts
474 // to be saved to persistence.
476 AccountTrackerService tracker;
477 tracker.Initialize(token_service(), signin_client());
478 SimulateTokenAvailable("alpha");
479 ReturnOAuthUrlFetchSuccess("alpha");
480 SimulateTokenAvailable("beta");
481 ReturnOAuthUrlFetchSuccess("beta");
482 tracker.Shutdown();
485 // Create a new tracker and make sure it loads the accounts corectly from
486 // persistence.
488 AccountTrackerService tracker;
489 tracker.AddObserver(observer());
490 tracker.Initialize(token_service(), signin_client());
491 ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha"),
492 TrackingEvent(UPDATED, "beta")));
494 std::vector<AccountTrackerService::AccountInfo> infos =
495 tracker.GetAccounts();
496 ASSERT_EQ(2u, infos.size());
497 EXPECT_EQ(AccountIdToGaiaId("alpha"), infos[0].gaia);
498 EXPECT_EQ(AccountIdToEmail("alpha"), infos[0].email);
499 EXPECT_EQ("beta", infos[1].account_id);
500 EXPECT_EQ(AccountIdToGaiaId("beta"), infos[1].gaia);
501 EXPECT_EQ(AccountIdToEmail("beta"), infos[1].email);
503 // Remove account.
504 SimulateTokenRevoked("alpha");
505 tracker.RemoveObserver(observer());
506 tracker.Shutdown();
509 // Create a new tracker and make sure it loads the single account from
510 // persistence.
512 AccountTrackerService tracker;
513 tracker.Initialize(token_service(), signin_client());
515 std::vector<AccountTrackerService::AccountInfo> infos =
516 tracker.GetAccounts();
517 ASSERT_EQ(1u, infos.size());
518 EXPECT_EQ("beta", infos[0].account_id);
519 EXPECT_EQ(AccountIdToGaiaId("beta"), infos[0].gaia);
520 EXPECT_EQ(AccountIdToEmail("beta"), infos[0].email);
521 tracker.Shutdown();
525 TEST_F(AccountTrackerServiceTest, SeedAccountInfo) {
526 std::vector<AccountTrackerService::AccountInfo> infos =
527 account_tracker()->GetAccounts();
528 EXPECT_EQ(0u, infos.size());
530 const std::string gaia_id = AccountIdToGaiaId("alpha");
531 const std::string email = AccountIdToEmail("alpha");
532 const std::string account_id =
533 account_tracker()->PickAccountIdForAccount(gaia_id, email);
534 account_tracker()->SeedAccountInfo(gaia_id, email);
536 infos = account_tracker()->GetAccounts();
537 EXPECT_EQ(1u, infos.size());
538 EXPECT_EQ(account_id, infos[0].account_id);
539 EXPECT_EQ(gaia_id, infos[0].gaia);
540 EXPECT_EQ(email, infos[0].email);