1 // Copyright (c) 2011 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/cryptohome_op.h" 6 7 #include <string> 8 9 #include "base/memory/ref_counted.h" 10 #include "base/message_loop.h" 11 #include "chrome/browser/chromeos/cros/mock_library_loader.h" 12 #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" 13 #include "chrome/browser/chromeos/login/auth_attempt_state.h" 14 #include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h" 15 #include "chrome/browser/chromeos/login/test_attempt_state.h" 16 #include "content/browser/browser_thread.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 using ::testing::AnyNumber; 21 using ::testing::Invoke; 22 using ::testing::Return; 23 using ::testing::_; 24 25 namespace chromeos { 26 27 class CryptohomeOpTest : public ::testing::Test { 28 public: 29 CryptohomeOpTest() 30 : message_loop_(MessageLoop::TYPE_UI), 31 ui_thread_(BrowserThread::UI, &message_loop_), 32 io_thread_(BrowserThread::IO), 33 username_("me (at) nowhere.org"), 34 hash_ascii_("0a010000000000a0"), 35 state_(username_, "", hash_ascii_, "", "", false), 36 resolver_(new MockAuthAttemptStateResolver), 37 mock_library_(new MockCryptohomeLibrary) { 38 } 39 40 virtual ~CryptohomeOpTest() {} 41 42 virtual void SetUp() { 43 CrosLibrary::TestApi* test_api = CrosLibrary::Get()->GetTestApi(); 44 45 MockLibraryLoader* loader = new MockLibraryLoader(); 46 ON_CALL(*loader, Load(_)) 47 .WillByDefault(Return(true)); 48 EXPECT_CALL(*loader, Load(_)) 49 .Times(AnyNumber()); 50 51 // Passes ownership of |loader| to CrosLibrary. 52 test_api->SetLibraryLoader(loader, true); 53 // |mock_library_| is mine, though. 54 test_api->SetCryptohomeLibrary(mock_library_.get(), false); 55 mock_library_->SetUp(false, 0); 56 57 io_thread_.Start(); 58 } 59 60 virtual void TearDown() { 61 // Prevent bogus gMock leak check from firing. 62 chromeos::CrosLibrary::TestApi* test_api = 63 chromeos::CrosLibrary::Get()->GetTestApi(); 64 test_api->SetLibraryLoader(NULL, false); 65 } 66 67 void ExpectMigrate(bool passing_old_hash, const std::string& hash) { 68 if (passing_old_hash) { 69 EXPECT_CALL(*(mock_library_.get()), AsyncMigrateKey(username_, 70 hash, 71 hash_ascii_, 72 _)) 73 .Times(1) 74 .RetiresOnSaturation(); 75 } else { 76 EXPECT_CALL(*(mock_library_.get()), AsyncMigrateKey(username_, 77 hash_ascii_, 78 hash, 79 _)) 80 .Times(1) 81 .RetiresOnSaturation(); 82 } 83 } 84 85 void ExpectMount() { 86 EXPECT_CALL(*(mock_library_.get()), 87 AsyncMount(username_, hash_ascii_, true, _)) 88 .Times(1) 89 .RetiresOnSaturation(); 90 } 91 92 void ExpectMountGuest() { 93 EXPECT_CALL(*(mock_library_.get()), AsyncMountForBwsi(_)) 94 .Times(1) 95 .RetiresOnSaturation(); 96 } 97 98 void ExpectRemove() { 99 EXPECT_CALL(*(mock_library_.get()), AsyncRemove(username_, _)) 100 .Times(1) 101 .RetiresOnSaturation(); 102 } 103 104 void ExpectCheckKey() { 105 EXPECT_CALL(*(mock_library_.get()), 106 AsyncCheckKey(username_, hash_ascii_, _)) 107 .Times(1) 108 .RetiresOnSaturation(); 109 } 110 111 void RunTest(CryptohomeOp* op, bool outcome, int code) { 112 mock_library_->SetAsyncBehavior(outcome, code); 113 114 EXPECT_CALL(*(resolver_.get()), Resolve()) 115 .Times(1) 116 .RetiresOnSaturation(); 117 118 EXPECT_TRUE(op->Initiate()); 119 // Force IO thread to finish tasks so I can verify |state_|. 120 io_thread_.Stop(); 121 122 EXPECT_EQ(outcome, state_.cryptohome_outcome()); 123 EXPECT_EQ(code, state_.cryptohome_code()); 124 } 125 126 MessageLoop message_loop_; 127 BrowserThread ui_thread_; 128 BrowserThread io_thread_; 129 std::string username_; 130 std::string hash_ascii_; 131 TestAttemptState state_; 132 scoped_ptr<MockAuthAttemptStateResolver> resolver_; 133 scoped_refptr<CryptohomeOp> op_; 134 scoped_ptr<MockCryptohomeLibrary> mock_library_; 135 136 }; 137 138 TEST_F(CryptohomeOpTest, MountSuccess) { 139 ExpectMount(); 140 scoped_refptr<CryptohomeOp> op( 141 CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true)); 142 RunTest(op.get(), true, kCryptohomeMountErrorNone); 143 } 144 145 TEST_F(CryptohomeOpTest, MountFatal) { 146 ExpectMount(); 147 scoped_refptr<CryptohomeOp> op( 148 CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true)); 149 RunTest(op.get(), false, kCryptohomeMountErrorFatal); 150 } 151 152 TEST_F(CryptohomeOpTest, MountKeyFailure) { 153 ExpectMount(); 154 scoped_refptr<CryptohomeOp> op( 155 CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true)); 156 RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure); 157 } 158 159 TEST_F(CryptohomeOpTest, MountRecreated) { 160 ExpectMount(); 161 scoped_refptr<CryptohomeOp> op( 162 CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true)); 163 RunTest(op.get(), true, kCryptohomeMountErrorRecreated); 164 } 165 166 TEST_F(CryptohomeOpTest, MountGuestSuccess) { 167 ExpectMountGuest(); 168 scoped_refptr<CryptohomeOp> op( 169 CryptohomeOp::CreateMountGuestAttempt(&state_, resolver_.get())); 170 RunTest(op.get(), true, kCryptohomeMountErrorNone); 171 } 172 173 TEST_F(CryptohomeOpTest, MountGuestFatal) { 174 ExpectMountGuest(); 175 scoped_refptr<CryptohomeOp> op( 176 CryptohomeOp::CreateMountGuestAttempt(&state_, resolver_.get())); 177 RunTest(op.get(), false, kCryptohomeMountErrorFatal); 178 } 179 180 TEST_F(CryptohomeOpTest, MigrateSuccessPassOld) { 181 ExpectMigrate(true, ""); 182 scoped_refptr<CryptohomeOp> op( 183 CryptohomeOp::CreateMigrateAttempt(&state_, resolver_.get(), true, "")); 184 RunTest(op.get(), true, kCryptohomeMountErrorNone); 185 } 186 187 TEST_F(CryptohomeOpTest, MigrateSuccessPassNew) { 188 ExpectMigrate(false, ""); 189 scoped_refptr<CryptohomeOp> op( 190 CryptohomeOp::CreateMigrateAttempt(&state_, resolver_.get(), false, "")); 191 RunTest(op.get(), true, kCryptohomeMountErrorNone); 192 } 193 194 TEST_F(CryptohomeOpTest, MigrateKeyFailure) { 195 ExpectMigrate(true, ""); 196 scoped_refptr<CryptohomeOp> op( 197 CryptohomeOp::CreateMigrateAttempt(&state_, resolver_.get(), true, "")); 198 RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure); 199 } 200 201 TEST_F(CryptohomeOpTest, RemoveSuccess) { 202 ExpectRemove(); 203 scoped_refptr<CryptohomeOp> op( 204 CryptohomeOp::CreateRemoveAttempt(&state_, resolver_.get())); 205 RunTest(op.get(), true, kCryptohomeMountErrorNone); 206 } 207 208 TEST_F(CryptohomeOpTest, RemoveFailure) { 209 ExpectRemove(); 210 scoped_refptr<CryptohomeOp> op( 211 CryptohomeOp::CreateRemoveAttempt(&state_, resolver_.get())); 212 RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure); 213 } 214 215 TEST_F(CryptohomeOpTest, CheckKeySuccess) { 216 ExpectCheckKey(); 217 scoped_refptr<CryptohomeOp> op( 218 CryptohomeOp::CreateCheckKeyAttempt(&state_, resolver_.get())); 219 RunTest(op.get(), true, kCryptohomeMountErrorNone); 220 } 221 222 TEST_F(CryptohomeOpTest, CheckKeyFailure) { 223 ExpectCheckKey(); 224 scoped_refptr<CryptohomeOp> op( 225 CryptohomeOp::CreateCheckKeyAttempt(&state_, resolver_.get())); 226 RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure); 227 } 228 229 } // namespace chromeos 230