Home | History | Annotate | Download | only in login
      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