// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/policy/core/user_cloud_policy_store_ash.h"
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "chromeos/ash/components/cryptohome/cryptohome_parameters.h"
#include "chromeos/ash/components/dbus/cryptohome/account_identifier_operators.h"
#include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
#include "chromeos/components/onc/onc_test_utils.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
#include "components/policy/core/common/cloud/test/policy_builder.h"
#include "components/policy/core/common/policy_switches.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/policy/proto/cloud_policy.pb.h"
#include "crypto/rsa_private_key.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace em = enterprise_management;
using RetrievePolicyResponseType =
ash::SessionManagerClient::RetrievePolicyResponseType;
using testing::_;
using testing::AllOf;
using testing::Eq;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::Property;
using testing::Return;
using testing::SaveArg;
using testing::SetArgPointee;
namespace policy {
namespace {
const char kDefaultHomepage[] = "http://chromium.org";
base::FilePath GetUserPolicyKeyFile(
const base::FilePath& user_policy_dir,
const cryptohome::AccountIdentifier& cryptohome_id) {
const std::string sanitized_username =
ash::UserDataAuthClient::GetStubSanitizedUsername(cryptohome_id);
return user_policy_dir.AppendASCII(sanitized_username)
.AppendASCII("policy.pub");
}
bool StoreUserPolicyKey(const base::FilePath& user_policy_dir,
const cryptohome::AccountIdentifier& cryptohome_id,
const std::string& public_key) {
base::FilePath user_policy_key_file =
GetUserPolicyKeyFile(user_policy_dir, cryptohome_id);
if (!base::CreateDirectory(user_policy_key_file.DirName()))
return false;
return base::WriteFile(user_policy_key_file, public_key);
}
// For detailed test for UserCloudPolicyStoreAsh, this supports
// public key file update emulation.
class FakeSessionManagerClient : public ash::FakeSessionManagerClient {
public:
explicit FakeSessionManagerClient(const base::FilePath& user_policy_dir)
: user_policy_dir_(user_policy_dir) {}
FakeSessionManagerClient(const FakeSessionManagerClient&) = delete;
FakeSessionManagerClient& operator=(const FakeSessionManagerClient&) = delete;
// SessionManagerClient override:
void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id,
const std::string& policy_blob,
chromeos::VoidDBusMethodCallback callback) override {
ash::FakeSessionManagerClient::StorePolicyForUser(
cryptohome_id, policy_blob,
base::BindOnce(&FakeSessionManagerClient::OnStorePolicyForUser,
weak_ptr_factory_.GetWeakPtr(), cryptohome_id,
std::move(callback)));
}
void set_user_public_key(const cryptohome::AccountIdentifier& cryptohome_id,
const std::string& public_key) {
public_key_map_[cryptohome_id] = public_key;
}
private:
void OnStorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id,
chromeos::VoidDBusMethodCallback callback,
bool result) {
if (result) {
auto iter = public_key_map_.find(cryptohome_id);
if (iter != public_key_map_.end())
StoreUserPolicyKey(user_policy_dir_, cryptohome_id, iter->second);
}
std::move(callback).Run(result);
}
const base::FilePath user_policy_dir_;
std::map<cryptohome::AccountIdentifier, std::string> public_key_map_;
base::WeakPtrFactory<FakeSessionManagerClient> weak_ptr_factory_{this};
};
class UserCloudPolicyStoreAshTest : public testing::Test {
public:
UserCloudPolicyStoreAshTest(const UserCloudPolicyStoreAshTest&) = delete;
UserCloudPolicyStoreAshTest& operator=(const UserCloudPolicyStoreAshTest&) =
delete;
protected:
UserCloudPolicyStoreAshTest()
: task_environment_(
base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {}
void SetUp() override {
ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
session_manager_client_ =
std::make_unique<FakeSessionManagerClient>(user_policy_dir());
store_ = std::make_unique<UserCloudPolicyStoreAsh>(
&cryptohome_misc_client_, session_manager_client_.get(),
base::SingleThreadTaskRunner::GetCurrentDefault(), account_id_,
user_policy_dir());
store_->AddObserver(&observer_);
// Set the verification key to be used for testing by the
// CloudPolicyValidator.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII(
switches::kPolicyVerificationKey,
PolicyBuilder::GetEncodedPolicyVerificationKey());
// Install the initial public key, so that by default the validation of
// the stored/loaded policy blob succeeds.
std::string public_key = policy_.GetPublicSigningKeyAsString();
ASSERT_FALSE(public_key.empty());
ASSERT_TRUE(
StoreUserPolicyKey(user_policy_dir(), cryptohome_id_, public_key));
policy_.payload().mutable_homepagelocation()->set_value(kDefaultHomepage);
policy_.Build();
}
void TearDown() override {
store_->RemoveObserver(&observer_);
store_.reset();
}
// Install an expectation on |observer_| for an error code.
// This method should be called after a store->Store()/Load() call has been
// initiated. The expected OnStoreError call will be initiated asynchronously
// from this run_loop's iteration.
void RunLoopAndExpectError(CloudPolicyStore::Status error) {
base::RunLoop run_loop;
EXPECT_CALL(observer_, OnStoreError(AllOf(
Eq(store_.get()),
Property(&CloudPolicyStore::status, Eq(error)))))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
run_loop.Run();
Mock::VerifyAndClearExpectations(&observer_);
}
// Install an expectation on |observer_| for a successful load operation.
// This method should be called after a store->Store()/Load() call has been
// initiated. The expected OnStoreLoaded call will be initiated asynchronously
// from this run_loop's iteration.
void RunLoopAndExpectLoaded() {
base::RunLoop run_loop;
EXPECT_CALL(observer_, OnStoreLoaded(store_.get()))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
run_loop.Run();
Mock::VerifyAndClearExpectations(&observer_);
}
// Triggers a store_->Load() operation, handles the expected call to
// |session_manager_client_| and sends |response|.
void PerformPolicyLoad(const std::string& response) {
// Issue a load command.
session_manager_client_->set_user_policy(cryptohome_id_, response);
store_->Load();
}
// Verifies that store_->policy_map() has the HomepageLocation entry with
// the |expected_value|.
void VerifyPolicyMap(const char* expected_value) {
EXPECT_EQ(1U, store_->policy_map().size());
const PolicyMap::Entry* entry =
store_->policy_map().Get(key::kHomepageLocation);
ASSERT_TRUE(entry);
EXPECT_EQ(base::Value(expected_value),
*entry->value(base::Value::Type::STRING));
}
// Stores the current |policy_| and verifies that it is published.
// If |previous_value| is set then a previously existing policy with that
// value will be expected; otherwise no previous policy is expected.
// If |new_value| is set then a new policy with that value is expected after
// storing the |policy_| blob.
void PerformStorePolicy(const char* previous_value, const char* new_value) {
const CloudPolicyStore::Status initial_status = store_->status();
store_->Store(policy_.policy());
// The new policy shouldn't be present yet.
PolicyMap previous_policy;
EXPECT_EQ(previous_value != nullptr, store_->policy() != nullptr);
if (previous_value) {
previous_policy.Set(key::kHomepageLocation, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value(previous_value), nullptr);
}
EXPECT_TRUE(previous_policy.Equals(store_->policy_map()));
EXPECT_EQ(initial_status, store_->status());
RunLoopAndExpectLoaded();
ASSERT_TRUE(store_->policy());
EXPECT_EQ(policy_.policy_data().SerializeAsString(),
store_->policy()->SerializeAsString());
VerifyPolicyMap(new_value);
EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
}
void VerifyStoreHasValidationError() {
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
}
base::FilePath user_policy_dir() {
return tmp_dir_.GetPath().AppendASCII("var_run_user_policy");
}
base::FilePath user_policy_key_file() {
return GetUserPolicyKeyFile(user_policy_dir(), cryptohome_id_);
}
base::test::SingleThreadTaskEnvironment task_environment_;
ash::FakeCryptohomeMiscClient cryptohome_misc_client_;
std::unique_ptr<FakeSessionManagerClient> session_manager_client_;
UserPolicyBuilder policy_;
MockCloudPolicyStoreObserver observer_;
std::unique_ptr<UserCloudPolicyStoreAsh> store_;
const AccountId account_id_ =
AccountId::FromUserEmail(PolicyBuilder::kFakeUsername);
const cryptohome::AccountIdentifier cryptohome_id_ =
cryptohome::CreateAccountIdentifierFromAccountId(account_id_);
private:
base::ScopedTempDir tmp_dir_;
};
TEST_F(UserCloudPolicyStoreAshTest, InitialStore) {
// Start without any public key to trigger the initial key checks.
ASSERT_TRUE(base::DeleteFile(user_policy_key_file()));
// Make the policy blob contain a new public key.
policy_.SetDefaultNewSigningKey();
policy_.Build();
std::string new_public_key = policy_.GetPublicNewSigningKeyAsString();
ASSERT_FALSE(new_public_key.empty());
session_manager_client_->set_user_public_key(cryptohome_id_, new_public_key);
ASSERT_NO_FATAL_FAILURE(PerformStorePolicy(nullptr, kDefaultHomepage));
EXPECT_EQ(new_public_key, store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, InitialStoreValidationFail) {
// Start without any public key to trigger the initial key checks.
ASSERT_TRUE(base::DeleteFile(user_policy_key_file()));
// Make the policy blob contain a new public key.
policy_.SetDefaultSigningKey();
policy_.Build();
*policy_.policy().mutable_new_public_key_verification_signature_deprecated() =
"garbage";
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, InitialStoreMissingSignatureFailure) {
// Start without any public key to trigger the initial key checks.
ASSERT_TRUE(base::DeleteFile(user_policy_key_file()));
// Make the policy blob contain a new public key.
policy_.SetDefaultSigningKey();
policy_.Build();
policy_.policy().clear_new_public_key_verification_signature_deprecated();
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreWithExistingKey) {
ASSERT_NO_FATAL_FAILURE(PerformStorePolicy(nullptr, kDefaultHomepage));
EXPECT_EQ(policy_.GetPublicSigningKeyAsString(),
store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreWithRotation) {
// Make the policy blob contain a new public key.
policy_.SetDefaultNewSigningKey();
policy_.Build();
std::string new_public_key = policy_.GetPublicNewSigningKeyAsString();
ASSERT_FALSE(new_public_key.empty());
session_manager_client_->set_user_public_key(cryptohome_id_, new_public_key);
ASSERT_NO_FATAL_FAILURE(PerformStorePolicy(nullptr, kDefaultHomepage));
EXPECT_EQ(new_public_key, store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreWithRotationMissingSignatureError) {
// Make the policy blob contain a new public key.
policy_.SetDefaultNewSigningKey();
policy_.Build();
policy_.policy().clear_new_public_key_verification_signature_deprecated();
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreWithRotationValidationError) {
// Make the policy blob contain a new public key.
policy_.SetDefaultNewSigningKey();
policy_.Build();
*policy_.policy().mutable_new_public_key_verification_signature_deprecated() =
"garbage";
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreFail) {
// Let store policy fail.
session_manager_client_->ForceStorePolicyFailure(true);
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_STORE_ERROR);
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_STORE_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreValidationError) {
policy_.policy_data().clear_policy_type();
policy_.Build();
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreValueValidationError) {
std::string onc_policy = chromeos::onc::test_utils::ReadTestData(
"toplevel_with_unknown_fields.onc");
policy_.payload().mutable_opennetworkconfiguration()->set_value(onc_policy);
policy_.Build();
store_->Store(policy_.policy());
RunLoopAndExpectLoaded();
const CloudPolicyValidatorBase::ValidationResult* validation_result =
store_->validation_result();
EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
ASSERT_TRUE(validation_result);
EXPECT_EQ(CloudPolicyValidatorBase::VALIDATION_OK, validation_result->status);
EXPECT_EQ(3u, validation_result->value_validation_issues.size());
EXPECT_EQ(policy_.policy_data().policy_token(),
validation_result->policy_token);
EXPECT_EQ(policy_.policy().policy_data_signature(),
validation_result->policy_data_signature);
}
TEST_F(UserCloudPolicyStoreAshTest, StoreWithoutPolicyKey) {
// Make the dbus call to cryptohome fail.
cryptohome_misc_client_.SetServiceIsAvailable(false);
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, StoreWithInvalidSignature) {
// Break the signature.
policy_.policy().mutable_policy_data_signature()->append("garbage");
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, MultipleStoresWithRotation) {
// Store initial policy signed with the initial public key.
ASSERT_NO_FATAL_FAILURE(PerformStorePolicy(nullptr, kDefaultHomepage));
const std::string initial_public_key = policy_.GetPublicSigningKeyAsString();
EXPECT_EQ(initial_public_key, store_->policy_signature_public_key());
// Try storing an invalid policy signed with the new public key.
policy_.SetDefaultNewSigningKey();
policy_.policy_data().clear_policy_type();
policy_.Build();
// Store policy
store_->Store(policy_.policy());
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
// Still the initial public key is exposed.
EXPECT_EQ(initial_public_key, store_->policy_signature_public_key());
// Store the correct policy signed with the new public key.
policy_.policy_data().set_policy_type(dm_protocol::kChromeUserPolicyType);
policy_.Build();
std::string new_public_key = policy_.GetPublicNewSigningKeyAsString();
ASSERT_FALSE(new_public_key.empty());
session_manager_client_->set_user_public_key(cryptohome_id_, new_public_key);
ASSERT_NO_FATAL_FAILURE(
PerformStorePolicy(kDefaultHomepage, kDefaultHomepage));
EXPECT_EQ(policy_.GetPublicNewSigningKeyAsString(),
store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, Load) {
ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob()));
RunLoopAndExpectLoaded();
// Verify that the policy has been loaded.
ASSERT_TRUE(store_->policy());
EXPECT_EQ(policy_.policy_data().SerializeAsString(),
store_->policy()->SerializeAsString());
VerifyPolicyMap(kDefaultHomepage);
EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
EXPECT_EQ(policy_.GetPublicSigningKeyAsString(),
store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadNoPolicy) {
ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(""));
RunLoopAndExpectLoaded();
// Verify no policy has been installed.
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadInvalidPolicy) {
ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad("invalid"));
RunLoopAndExpectError(CloudPolicyStore::STATUS_PARSE_ERROR);
// Verify no policy has been installed.
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_PARSE_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadValidationError) {
policy_.policy_data().clear_policy_type();
policy_.Build();
ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob()));
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
VerifyStoreHasValidationError();
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadNoKey) {
// The loaded policy can't be verified without the public key.
ASSERT_TRUE(base::DeleteFile(user_policy_key_file()));
ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob()));
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
VerifyStoreHasValidationError();
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadInvalidSignature) {
// Break the signature.
policy_.policy().mutable_policy_data_signature()->append("garbage");
ASSERT_NO_FATAL_FAILURE(PerformPolicyLoad(policy_.GetBlob()));
RunLoopAndExpectError(CloudPolicyStore::STATUS_VALIDATION_ERROR);
VerifyStoreHasValidationError();
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadImmediately) {
session_manager_client_->set_user_policy(cryptohome_id_, policy_.GetBlob());
EXPECT_FALSE(store_->policy());
EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
store_->LoadImmediately();
// Note: verify that the |observer_| got notified synchronously, without
// having to spin the current loop. TearDown() will flush the loop so this
// must be done within the test.
Mock::VerifyAndClearExpectations(&observer_);
// The policy should become available without having to spin any loops.
ASSERT_TRUE(store_->policy());
EXPECT_EQ(policy_.policy_data().SerializeAsString(),
store_->policy()->SerializeAsString());
VerifyPolicyMap(kDefaultHomepage);
EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
EXPECT_EQ(policy_.GetPublicSigningKeyAsString(),
store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadImmediatelyNoPolicy) {
EXPECT_FALSE(store_->policy());
EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
store_->LoadImmediately();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadImmediatelyInvalidBlob) {
session_manager_client_->set_user_policy(cryptohome_id_, "le blob");
EXPECT_FALSE(store_->policy());
EXPECT_CALL(observer_, OnStoreError(store_.get()));
store_->LoadImmediately();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_PARSE_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadImmediatelyDBusFailure) {
session_manager_client_->set_user_policy(cryptohome_id_, policy_.GetBlob());
// Make the dbus call to cryptohome fail.
cryptohome_misc_client_.SetServiceIsAvailable(false);
EXPECT_FALSE(store_->policy());
EXPECT_CALL(observer_, OnStoreError(store_.get()));
store_->LoadImmediately();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_LOAD_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
TEST_F(UserCloudPolicyStoreAshTest, LoadImmediatelyNoUserPolicyKey) {
session_manager_client_->set_user_policy(cryptohome_id_, policy_.GetBlob());
// Ensure no policy data.
ASSERT_TRUE(base::DeleteFile(user_policy_key_file()));
EXPECT_FALSE(store_->policy());
EXPECT_CALL(observer_, OnStoreError(store_.get()));
store_->LoadImmediately();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_FALSE(store_->policy());
EXPECT_TRUE(store_->policy_map().empty());
EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, store_->status());
EXPECT_EQ(std::string(), store_->policy_signature_public_key());
}
} // namespace
} // namespace policy