普通文本  |  230行  |  7.21 KB

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/cryptohome_op.h"

#include <string>

#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "chrome/browser/chromeos/cros/mock_library_loader.h"
#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
#include "chrome/browser/chromeos/login/auth_attempt_state.h"
#include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h"
#include "chrome/browser/chromeos/login/test_attempt_state.h"
#include "content/browser/browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::AnyNumber;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::_;

namespace chromeos {

class CryptohomeOpTest : public ::testing::Test {
 public:
  CryptohomeOpTest()
      : message_loop_(MessageLoop::TYPE_UI),
        ui_thread_(BrowserThread::UI, &message_loop_),
        io_thread_(BrowserThread::IO),
        username_("me@nowhere.org"),
        hash_ascii_("0a010000000000a0"),
        state_(username_, "", hash_ascii_, "", "", false),
        resolver_(new MockAuthAttemptStateResolver),
        mock_library_(new MockCryptohomeLibrary) {
  }

  virtual ~CryptohomeOpTest() {}

  virtual void SetUp() {
    CrosLibrary::TestApi* test_api = CrosLibrary::Get()->GetTestApi();

    MockLibraryLoader* loader = new MockLibraryLoader();
    ON_CALL(*loader, Load(_))
        .WillByDefault(Return(true));
    EXPECT_CALL(*loader, Load(_))
        .Times(AnyNumber());

    // Passes ownership of |loader| to CrosLibrary.
    test_api->SetLibraryLoader(loader, true);
    // |mock_library_| is mine, though.
    test_api->SetCryptohomeLibrary(mock_library_.get(), false);
    mock_library_->SetUp(false, 0);

    io_thread_.Start();
  }

  virtual void TearDown() {
    // Prevent bogus gMock leak check from firing.
    chromeos::CrosLibrary::TestApi* test_api =
        chromeos::CrosLibrary::Get()->GetTestApi();
    test_api->SetLibraryLoader(NULL, false);
  }

  void ExpectMigrate(bool passing_old_hash, const std::string& hash) {
    if (passing_old_hash) {
      EXPECT_CALL(*(mock_library_.get()), AsyncMigrateKey(username_,
                                                          hash,
                                                          hash_ascii_,
                                                          _))
          .Times(1)
          .RetiresOnSaturation();
    } else {
      EXPECT_CALL(*(mock_library_.get()), AsyncMigrateKey(username_,
                                                          hash_ascii_,
                                                          hash,
                                                          _))
          .Times(1)
          .RetiresOnSaturation();
    }
  }

  void ExpectMount() {
    EXPECT_CALL(*(mock_library_.get()),
                AsyncMount(username_, hash_ascii_, true, _))
        .Times(1)
        .RetiresOnSaturation();
  }

  void ExpectMountGuest() {
    EXPECT_CALL(*(mock_library_.get()), AsyncMountForBwsi(_))
        .Times(1)
        .RetiresOnSaturation();
  }

  void ExpectRemove() {
    EXPECT_CALL(*(mock_library_.get()), AsyncRemove(username_, _))
        .Times(1)
        .RetiresOnSaturation();
  }

  void ExpectCheckKey() {
    EXPECT_CALL(*(mock_library_.get()),
                AsyncCheckKey(username_, hash_ascii_, _))
        .Times(1)
        .RetiresOnSaturation();
  }

  void RunTest(CryptohomeOp* op, bool outcome, int code) {
    mock_library_->SetAsyncBehavior(outcome, code);

    EXPECT_CALL(*(resolver_.get()), Resolve())
        .Times(1)
        .RetiresOnSaturation();

    EXPECT_TRUE(op->Initiate());
    // Force IO thread to finish tasks so I can verify |state_|.
    io_thread_.Stop();

    EXPECT_EQ(outcome, state_.cryptohome_outcome());
    EXPECT_EQ(code, state_.cryptohome_code());
  }

  MessageLoop message_loop_;
  BrowserThread ui_thread_;
  BrowserThread io_thread_;
  std::string username_;
  std::string hash_ascii_;
  TestAttemptState state_;
  scoped_ptr<MockAuthAttemptStateResolver> resolver_;
  scoped_refptr<CryptohomeOp> op_;
  scoped_ptr<MockCryptohomeLibrary> mock_library_;

};

TEST_F(CryptohomeOpTest, MountSuccess) {
  ExpectMount();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true));
  RunTest(op.get(), true, kCryptohomeMountErrorNone);
}

TEST_F(CryptohomeOpTest, MountFatal) {
  ExpectMount();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true));
  RunTest(op.get(), false, kCryptohomeMountErrorFatal);
}

TEST_F(CryptohomeOpTest, MountKeyFailure) {
  ExpectMount();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true));
  RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure);
}

TEST_F(CryptohomeOpTest, MountRecreated) {
  ExpectMount();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMountAttempt(&state_, resolver_.get(), true));
  RunTest(op.get(), true, kCryptohomeMountErrorRecreated);
}

TEST_F(CryptohomeOpTest, MountGuestSuccess) {
  ExpectMountGuest();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMountGuestAttempt(&state_, resolver_.get()));
  RunTest(op.get(), true, kCryptohomeMountErrorNone);
}

TEST_F(CryptohomeOpTest, MountGuestFatal) {
  ExpectMountGuest();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMountGuestAttempt(&state_, resolver_.get()));
  RunTest(op.get(), false, kCryptohomeMountErrorFatal);
}

TEST_F(CryptohomeOpTest, MigrateSuccessPassOld) {
  ExpectMigrate(true, "");
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMigrateAttempt(&state_, resolver_.get(), true, ""));
  RunTest(op.get(), true, kCryptohomeMountErrorNone);
}

TEST_F(CryptohomeOpTest, MigrateSuccessPassNew) {
  ExpectMigrate(false, "");
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMigrateAttempt(&state_, resolver_.get(), false, ""));
  RunTest(op.get(), true, kCryptohomeMountErrorNone);
}

TEST_F(CryptohomeOpTest, MigrateKeyFailure) {
  ExpectMigrate(true, "");
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateMigrateAttempt(&state_, resolver_.get(), true, ""));
  RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure);
}

TEST_F(CryptohomeOpTest, RemoveSuccess) {
  ExpectRemove();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateRemoveAttempt(&state_, resolver_.get()));
  RunTest(op.get(), true, kCryptohomeMountErrorNone);
}

TEST_F(CryptohomeOpTest, RemoveFailure) {
  ExpectRemove();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateRemoveAttempt(&state_, resolver_.get()));
  RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure);
}

TEST_F(CryptohomeOpTest, CheckKeySuccess) {
  ExpectCheckKey();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateCheckKeyAttempt(&state_, resolver_.get()));
  RunTest(op.get(), true, kCryptohomeMountErrorNone);
}

TEST_F(CryptohomeOpTest, CheckKeyFailure) {
  ExpectCheckKey();
  scoped_refptr<CryptohomeOp> op(
      CryptohomeOp::CreateCheckKeyAttempt(&state_, resolver_.get()));
  RunTest(op.get(), false, kCryptohomeMountErrorKeyFailure);
}

}  // namespace chromeos