Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / parallel_authenticator_unittest.cc
1 // Copyright (c) 2012 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
5 #include "chrome/browser/chromeos/login/parallel_authenticator.h"
6
7 #include <string>
8
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
17 #include "chrome/browser/chromeos/login/mock_url_fetchers.h"
18 #include "chrome/browser/chromeos/login/mock_user_manager.h"
19 #include "chrome/browser/chromeos/login/test_attempt_state.h"
20 #include "chrome/browser/chromeos/login/user.h"
21 #include "chrome/browser/chromeos/login/user_manager.h"
22 #include "chrome/browser/chromeos/settings/cros_settings.h"
23 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
24 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "chromeos/chromeos_switches.h"
27 #include "chromeos/cryptohome/mock_async_method_caller.h"
28 #include "chromeos/cryptohome/system_salt_getter.h"
29 #include "chromeos/dbus/fake_cryptohome_client.h"
30 #include "chromeos/dbus/fake_dbus_thread_manager.h"
31 #include "content/public/test/test_browser_thread_bundle.h"
32 #include "google_apis/gaia/mock_url_fetcher_factory.h"
33 #include "net/base/net_errors.h"
34 #include "net/url_request/url_request_status.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37 #include "third_party/cros_system_api/dbus/service_constants.h"
38 #include "url/gurl.h"
39
40 using ::testing::Invoke;
41 using ::testing::Return;
42 using ::testing::_;
43
44 namespace chromeos {
45
46 class ParallelAuthenticatorTest : public testing::Test {
47  public:
48   ParallelAuthenticatorTest()
49       : username_("me@nowhere.org"),
50         password_("fakepass"),
51         hash_ascii_(ParallelAuthenticator::HashPassword(
52             password_,
53             SystemSaltGetter::ConvertRawSaltToHexString(
54                 FakeCryptohomeClient::GetStubSystemSalt()))),
55         user_manager_enabler_(new MockUserManager),
56         mock_caller_(NULL) {
57   }
58
59   virtual ~ParallelAuthenticatorTest() {
60     DCHECK(!mock_caller_);
61   }
62
63   virtual void SetUp() {
64     CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager);
65
66     mock_caller_ = new cryptohome::MockAsyncMethodCaller;
67     cryptohome::AsyncMethodCaller::InitializeForTesting(mock_caller_);
68
69     FakeDBusThreadManager* fake_dbus_thread_manager = new FakeDBusThreadManager;
70     fake_cryptohome_client_ = new FakeCryptohomeClient;
71     fake_dbus_thread_manager->SetCryptohomeClient(
72         scoped_ptr<CryptohomeClient>(fake_cryptohome_client_));
73     DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager);
74
75     SystemSaltGetter::Initialize();
76
77     auth_ = new ParallelAuthenticator(&consumer_);
78     state_.reset(new TestAttemptState(UserContext(username_,
79                                                   password_,
80                                                   std::string()),
81                                       "",
82                                       "",
83                                       User::USER_TYPE_REGULAR,
84                                       false));
85   }
86
87   // Tears down the test fixture.
88   virtual void TearDown() {
89     SystemSaltGetter::Shutdown();
90     DBusThreadManager::Shutdown();
91
92     cryptohome::AsyncMethodCaller::Shutdown();
93     mock_caller_ = NULL;
94   }
95
96   base::FilePath PopulateTempFile(const char* data, int data_len) {
97     base::FilePath out;
98     FILE* tmp_file = base::CreateAndOpenTemporaryFile(&out);
99     EXPECT_NE(tmp_file, static_cast<FILE*>(NULL));
100     EXPECT_EQ(file_util::WriteFile(out, data, data_len), data_len);
101     EXPECT_TRUE(base::CloseFile(tmp_file));
102     return out;
103   }
104
105   // Allow test to fail and exit gracefully, even if OnLoginFailure()
106   // wasn't supposed to happen.
107   void FailOnLoginFailure() {
108     ON_CALL(consumer_, OnLoginFailure(_))
109         .WillByDefault(Invoke(MockConsumer::OnFailQuitAndFail));
110   }
111
112   // Allow test to fail and exit gracefully, even if
113   // OnRetailModeLoginSuccess() wasn't supposed to happen.
114   void FailOnRetailModeLoginSuccess() {
115     ON_CALL(consumer_, OnRetailModeLoginSuccess(_))
116         .WillByDefault(Invoke(MockConsumer::OnRetailModeSuccessQuitAndFail));
117   }
118
119   // Allow test to fail and exit gracefully, even if OnLoginSuccess()
120   // wasn't supposed to happen.
121   void FailOnLoginSuccess() {
122     ON_CALL(consumer_, OnLoginSuccess(_))
123         .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail));
124   }
125
126   // Allow test to fail and exit gracefully, even if
127   // OnOffTheRecordLoginSuccess() wasn't supposed to happen.
128   void FailOnGuestLoginSuccess() {
129     ON_CALL(consumer_, OnOffTheRecordLoginSuccess())
130         .WillByDefault(Invoke(MockConsumer::OnGuestSuccessQuitAndFail));
131   }
132
133   void ExpectLoginFailure(const LoginFailure& failure) {
134     EXPECT_CALL(consumer_, OnLoginFailure(failure))
135         .WillOnce(Invoke(MockConsumer::OnFailQuit))
136         .RetiresOnSaturation();
137   }
138
139   void ExpectRetailModeLoginSuccess() {
140     EXPECT_CALL(consumer_, OnRetailModeLoginSuccess(_))
141         .WillOnce(Invoke(MockConsumer::OnRetailModeSuccessQuit))
142         .RetiresOnSaturation();
143   }
144
145   void ExpectLoginSuccess(const std::string& username,
146                           const std::string& password,
147                           const std::string& username_hash_,
148                           bool pending) {
149     EXPECT_CALL(consumer_, OnLoginSuccess(UserContext(
150         username,
151         password,
152         std::string(),
153         username_hash_,
154         true,  // using_oauth
155         UserContext::AUTH_FLOW_OFFLINE)))
156         .WillOnce(Invoke(MockConsumer::OnSuccessQuit))
157         .RetiresOnSaturation();
158   }
159
160   void ExpectGuestLoginSuccess() {
161     EXPECT_CALL(consumer_, OnOffTheRecordLoginSuccess())
162         .WillOnce(Invoke(MockConsumer::OnGuestSuccessQuit))
163         .RetiresOnSaturation();
164   }
165
166   void ExpectPasswordChange() {
167     EXPECT_CALL(consumer_, OnPasswordChangeDetected())
168         .WillOnce(Invoke(MockConsumer::OnMigrateQuit))
169         .RetiresOnSaturation();
170   }
171
172   void RunResolve(ParallelAuthenticator* auth) {
173     auth->Resolve();
174     base::MessageLoop::current()->RunUntilIdle();
175   }
176
177   void SetAttemptState(ParallelAuthenticator* auth, TestAttemptState* state) {
178     auth->set_attempt_state(state);
179   }
180
181   ParallelAuthenticator::AuthState SetAndResolveState(
182       ParallelAuthenticator* auth, TestAttemptState* state) {
183     auth->set_attempt_state(state);
184     return auth->ResolveState();
185   }
186
187   void SetOwnerState(bool owner_check_finished, bool check_result) {
188     auth_->SetOwnerState(owner_check_finished, check_result);
189   }
190
191   content::TestBrowserThreadBundle thread_bundle_;
192
193   std::string username_;
194   std::string password_;
195   std::string username_hash_;
196   std::string hash_ascii_;
197
198   ScopedDeviceSettingsTestHelper device_settings_test_helper_;
199   ScopedTestCrosSettings test_cros_settings_;
200
201   ScopedUserManagerEnabler user_manager_enabler_;
202
203   cryptohome::MockAsyncMethodCaller* mock_caller_;
204
205   MockConsumer consumer_;
206   scoped_refptr<ParallelAuthenticator> auth_;
207   scoped_ptr<TestAttemptState> state_;
208   FakeCryptohomeClient* fake_cryptohome_client_;
209 };
210
211 TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) {
212   EXPECT_CALL(consumer_, OnLoginSuccess(UserContext(
213       username_,
214       password_,
215       std::string(),
216       username_hash_,
217       true,  // using oauth
218       UserContext::AUTH_FLOW_OFFLINE)))
219       .Times(1)
220       .RetiresOnSaturation();
221
222   SetAttemptState(auth_.get(), state_.release());
223   auth_->OnLoginSuccess();
224 }
225
226 TEST_F(ParallelAuthenticatorTest, OnPasswordChangeDetected) {
227   EXPECT_CALL(consumer_, OnPasswordChangeDetected())
228       .Times(1)
229       .RetiresOnSaturation();
230   SetAttemptState(auth_.get(), state_.release());
231   auth_->OnPasswordChangeDetected();
232 }
233
234 TEST_F(ParallelAuthenticatorTest, ResolveNothingDone) {
235   EXPECT_EQ(ParallelAuthenticator::CONTINUE,
236             SetAndResolveState(auth_.get(), state_.release()));
237 }
238
239
240 TEST_F(ParallelAuthenticatorTest, ResolvePossiblePwChangeToFailedMount) {
241   // Set up state as though a cryptohome mount attempt has occurred
242   // and been rejected.
243   state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE);
244
245   // When there is no online attempt and online results, POSSIBLE_PW_CHANGE
246   EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT,
247             SetAndResolveState(auth_.get(), state_.release()));
248 }
249
250 TEST_F(ParallelAuthenticatorTest, ResolveNeedOldPw) {
251   // Set up state as though a cryptohome mount attempt has occurred
252   // and been rejected because of unmatched key; additionally,
253   // an online auth attempt has completed successfully.
254   state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE);
255   state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
256
257   EXPECT_EQ(ParallelAuthenticator::NEED_OLD_PW,
258             SetAndResolveState(auth_.get(), state_.release()));
259 }
260
261 TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededDirectFailedMount) {
262   // Set up state as though a cryptohome mount attempt has occurred
263   // and succeeded but we are in safe mode and the current user is not owner.
264   // This is a high level test to verify the proper transitioning in this mode
265   // only. It is not testing that we properly verify that the user is an owner
266   // or that we really are in "safe-mode".
267   state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
268   SetOwnerState(true, false);
269
270   EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED,
271             SetAndResolveState(auth_.get(), state_.release()));
272 }
273
274 TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededMount) {
275   // Set up state as though a cryptohome mount attempt has occurred
276   // and succeeded but we are in safe mode and the current user is not owner.
277   // This test will check that the "safe-mode" policy is not set and will let
278   // the mount finish successfully.
279   state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
280   SetOwnerState(false, false);
281   // and test that the mount has succeeded.
282   state_.reset(new TestAttemptState(UserContext(username_,
283                                                 password_,
284                                                 std::string()),
285                                     "",
286                                     "",
287                                     User::USER_TYPE_REGULAR,
288                                     false));
289   state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
290   EXPECT_EQ(ParallelAuthenticator::OFFLINE_LOGIN,
291             SetAndResolveState(auth_.get(), state_.release()));
292 }
293
294 TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) {
295   FailOnLoginSuccess();  // Set failing on success as the default...
296   LoginFailure failure = LoginFailure(LoginFailure::OWNER_REQUIRED);
297   ExpectLoginFailure(failure);
298
299   fake_cryptohome_client_->set_unmount_result(true);
300
301   CrosSettingsProvider* device_settings_provider;
302   StubCrosSettingsProvider stub_settings_provider;
303   // Set up state as though a cryptohome mount attempt has occurred
304   // and succeeded but we are in safe mode and the current user is not owner.
305   state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
306   SetOwnerState(false, false);
307   // Remove the real DeviceSettingsProvider and replace it with a stub.
308   device_settings_provider =
309       CrosSettings::Get()->GetProvider(chromeos::kReportDeviceVersionInfo);
310   EXPECT_TRUE(device_settings_provider != NULL);
311   EXPECT_TRUE(
312       CrosSettings::Get()->RemoveSettingsProvider(device_settings_provider));
313   CrosSettings::Get()->AddSettingsProvider(&stub_settings_provider);
314   CrosSettings::Get()->SetBoolean(kPolicyMissingMitigationMode, true);
315
316   // Initialize login state for this test to verify the login state is changed
317   // to SAFE_MODE.
318   LoginState::Initialize();
319
320   EXPECT_EQ(ParallelAuthenticator::CONTINUE,
321             SetAndResolveState(auth_.get(), state_.release()));
322   EXPECT_TRUE(LoginState::Get()->IsInSafeMode());
323
324   // Simulate TPM token ready event.
325   DeviceSettingsService::Get()->OnTPMTokenReady();
326
327   // Flush all the pending operations. The operations should induce an owner
328   // verification.
329   device_settings_test_helper_.Flush();
330   // and test that the mount has succeeded.
331   state_.reset(new TestAttemptState(UserContext(username_,
332                                                 password_,
333                                                 std::string()),
334                                     "",
335                                     "",
336                                     User::USER_TYPE_REGULAR,
337                                     false));
338   state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
339   EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED,
340             SetAndResolveState(auth_.get(), state_.release()));
341
342   // Unset global objects used by this test.
343   LoginState::Shutdown();
344   EXPECT_TRUE(
345       CrosSettings::Get()->RemoveSettingsProvider(&stub_settings_provider));
346   CrosSettings::Get()->AddSettingsProvider(device_settings_provider);
347 }
348
349 TEST_F(ParallelAuthenticatorTest, DriveFailedMount) {
350   FailOnLoginSuccess();
351   ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME));
352
353   // Set up state as though a cryptohome mount attempt has occurred
354   // and failed.
355   state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_NONE);
356   SetAttemptState(auth_.get(), state_.release());
357
358   RunResolve(auth_.get());
359 }
360
361 TEST_F(ParallelAuthenticatorTest, DriveGuestLogin) {
362   ExpectGuestLoginSuccess();
363   FailOnLoginFailure();
364
365   // Set up mock async method caller to respond as though a tmpfs mount
366   // attempt has occurred and succeeded.
367   mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
368   EXPECT_CALL(*mock_caller_, AsyncMountGuest(_))
369       .Times(1)
370       .RetiresOnSaturation();
371
372   auth_->LoginOffTheRecord();
373   base::MessageLoop::current()->Run();
374 }
375
376 TEST_F(ParallelAuthenticatorTest, DriveGuestLoginButFail) {
377   FailOnGuestLoginSuccess();
378   ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS));
379
380   // Set up mock async method caller to respond as though a tmpfs mount
381   // attempt has occurred and failed.
382   mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE);
383   EXPECT_CALL(*mock_caller_, AsyncMountGuest(_))
384       .Times(1)
385       .RetiresOnSaturation();
386
387   auth_->LoginOffTheRecord();
388   base::MessageLoop::current()->Run();
389 }
390
391 TEST_F(ParallelAuthenticatorTest, DriveRetailModeUserLogin) {
392   ExpectRetailModeLoginSuccess();
393   FailOnLoginFailure();
394
395   // Set up mock async method caller to respond as though a tmpfs mount
396   // attempt has occurred and succeeded.
397   mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
398   EXPECT_CALL(*mock_caller_, AsyncMountGuest(_))
399       .Times(1)
400       .RetiresOnSaturation();
401
402   auth_->LoginRetailMode();
403   base::MessageLoop::current()->Run();
404 }
405
406 TEST_F(ParallelAuthenticatorTest, DriveRetailModeLoginButFail) {
407   FailOnRetailModeLoginSuccess();
408   ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS));
409
410   // Set up mock async method caller to respond as though a tmpfs mount
411   // attempt has occurred and failed.
412   mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE);
413   EXPECT_CALL(*mock_caller_, AsyncMountGuest(_))
414       .Times(1)
415       .RetiresOnSaturation();
416
417   auth_->LoginRetailMode();
418   base::MessageLoop::current()->Run();
419 }
420
421 TEST_F(ParallelAuthenticatorTest, DriveDataResync) {
422   ExpectLoginSuccess(username_,
423                      password_,
424                      cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername,
425                      false);
426   FailOnLoginFailure();
427
428   // Set up mock async method caller to respond successfully to a cryptohome
429   // remove attempt and a cryptohome create attempt (indicated by the
430   // |CREATE_IF_MISSING| flag to AsyncMount).
431   mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
432   EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _))
433       .Times(1)
434       .RetiresOnSaturation();
435   EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_,
436                                         cryptohome::CREATE_IF_MISSING, _))
437       .Times(1)
438       .RetiresOnSaturation();
439   EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _))
440       .Times(1)
441       .RetiresOnSaturation();
442
443   state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
444   SetAttemptState(auth_.get(), state_.release());
445
446   auth_->ResyncEncryptedData();
447   base::MessageLoop::current()->Run();
448 }
449
450 TEST_F(ParallelAuthenticatorTest, DriveResyncFail) {
451   FailOnLoginSuccess();
452   ExpectLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED));
453
454   // Set up mock async method caller to fail a cryptohome remove attempt.
455   mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE);
456   EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _))
457       .Times(1)
458       .RetiresOnSaturation();
459
460   SetAttemptState(auth_.get(), state_.release());
461
462   auth_->ResyncEncryptedData();
463   base::MessageLoop::current()->Run();
464 }
465
466 TEST_F(ParallelAuthenticatorTest, DriveRequestOldPassword) {
467   FailOnLoginSuccess();
468   ExpectPasswordChange();
469
470   state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE);
471   state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
472   SetAttemptState(auth_.get(), state_.release());
473
474   RunResolve(auth_.get());
475 }
476
477 TEST_F(ParallelAuthenticatorTest, DriveDataRecover) {
478   ExpectLoginSuccess(username_,
479                      password_,
480                      cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername,
481                      false);
482   FailOnLoginFailure();
483
484   // Set up mock async method caller to respond successfully to a key migration.
485   mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
486   EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _))
487       .Times(1)
488       .RetiresOnSaturation();
489   EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_,
490                                         cryptohome::MOUNT_FLAGS_NONE, _))
491       .Times(1)
492       .RetiresOnSaturation();
493   EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _))
494         .Times(1)
495         .RetiresOnSaturation();
496
497   state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
498   SetAttemptState(auth_.get(), state_.release());
499
500   auth_->RecoverEncryptedData(std::string());
501   base::MessageLoop::current()->Run();
502 }
503
504 TEST_F(ParallelAuthenticatorTest, DriveDataRecoverButFail) {
505   FailOnLoginSuccess();
506   ExpectPasswordChange();
507
508   // Set up mock async method caller to fail a key migration attempt,
509   // asserting that the wrong password was used.
510   mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_KEY_FAILURE);
511   EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _))
512       .Times(1)
513       .RetiresOnSaturation();
514
515   SetAttemptState(auth_.get(), state_.release());
516
517   auth_->RecoverEncryptedData(std::string());
518   base::MessageLoop::current()->Run();
519 }
520
521 TEST_F(ParallelAuthenticatorTest, ResolveNoMountToFailedMount) {
522   // Set up state as though a cryptohome mount attempt has occurred
523   // and been rejected because the user doesn't exist.
524   state_->PresetCryptohomeStatus(false,
525                                  cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST);
526
527   // When there is no online attempt and online results, NO_MOUNT will be
528   // resolved to FAILED_MOUNT.
529   EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT,
530             SetAndResolveState(auth_.get(), state_.release()));
531 }
532
533 TEST_F(ParallelAuthenticatorTest, ResolveCreateNew) {
534   // Set up state as though a cryptohome mount attempt has occurred
535   // and been rejected because the user doesn't exist; additionally,
536   // an online auth attempt has completed successfully.
537   state_->PresetCryptohomeStatus(false,
538                                  cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST);
539   state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
540
541   EXPECT_EQ(ParallelAuthenticator::CREATE_NEW,
542             SetAndResolveState(auth_.get(), state_.release()));
543 }
544
545 TEST_F(ParallelAuthenticatorTest, DriveCreateForNewUser) {
546   ExpectLoginSuccess(username_,
547                      password_,
548                      cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername,
549                      false);
550   FailOnLoginFailure();
551
552   // Set up mock async method caller to respond successfully to a cryptohome
553   // create attempt (indicated by the |CREATE_IF_MISSING| flag to AsyncMount).
554   mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
555   EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_,
556                                         cryptohome::CREATE_IF_MISSING, _))
557       .Times(1)
558       .RetiresOnSaturation();
559   EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _))
560       .Times(1)
561       .RetiresOnSaturation();
562
563   // Set up state as though a cryptohome mount attempt has occurred
564   // and been rejected because the user doesn't exist; additionally,
565   // an online auth attempt has completed successfully.
566   state_->PresetCryptohomeStatus(false,
567                                  cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST);
568   state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
569   SetAttemptState(auth_.get(), state_.release());
570
571   RunResolve(auth_.get());
572 }
573
574 TEST_F(ParallelAuthenticatorTest, DriveOfflineLogin) {
575   ExpectLoginSuccess(username_, password_, username_hash_, false);
576   FailOnLoginFailure();
577
578   // Set up state as though a cryptohome mount attempt has occurred and
579   // succeeded.
580   state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
581   SetAttemptState(auth_.get(), state_.release());
582
583   RunResolve(auth_.get());
584 }
585
586 TEST_F(ParallelAuthenticatorTest, DriveOnlineLogin) {
587   ExpectLoginSuccess(username_, password_, username_hash_, false);
588   FailOnLoginFailure();
589
590   // Set up state as though a cryptohome mount attempt has occurred and
591   // succeeded.
592   state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE);
593   state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone());
594   SetAttemptState(auth_.get(), state_.release());
595
596   RunResolve(auth_.get());
597 }
598
599 TEST_F(ParallelAuthenticatorTest, DriveUnlock) {
600   ExpectLoginSuccess(username_, std::string(), std::string(), false);
601   FailOnLoginFailure();
602
603   // Set up mock async method caller to respond successfully to a cryptohome
604   // key-check attempt.
605   mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
606   EXPECT_CALL(*mock_caller_, AsyncCheckKey(username_, _, _))
607       .Times(1)
608       .RetiresOnSaturation();
609
610   auth_->AuthenticateToUnlock(UserContext(username_,
611                                           std::string(),
612                                           std::string()));
613   base::MessageLoop::current()->Run();
614 }
615
616 }  // namespace chromeos