15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/user_cloud_policy_store.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/scoped_temp_dir.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/run_loop.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_constants.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/cloud/policy_builder.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/policy_switches.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "policy/policy_constants.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::AllOf;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::Eq;
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::Mock;
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::Property;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using testing::Sequence;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace policy {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RunUntilIdle() {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop run_loop;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  run_loop.RunUntilIdle();
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool WriteStringToFile(const base::FilePath path, const std::string& data) {
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!base::CreateDirectory(path.DirName())) {
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(WARNING) << "Failed to create directory " << path.DirName().value();
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int size = data.size();
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (base::WriteFile(path, data.c_str(), size) != size) {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(WARNING) << "Failed to write " << path.value();
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class UserCloudPolicyStoreTest : public testing::Test {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserCloudPolicyStoreTest() {}
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    store_.reset(
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new UserCloudPolicyStore(policy_file(),
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 key_file(),
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 GetPolicyVerificationKey(),
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 loop_.message_loop_proxy()));
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    external_data_manager_.reset(new MockCloudExternalDataManager);
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    external_data_manager_->SetPolicyStore(store_.get());
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    store_->SetSigninUsername(PolicyBuilder::kFakeUsername);
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    store_->AddObserver(&observer_);
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Install an initial public key, so that by default the validation of
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the stored/loaded policy blob succeeds (it looks like a new key
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // provision).
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    policy_.SetDefaultInitialSigningKey();
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    InitPolicyPayload(&policy_.payload());
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    policy_.Build();
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    store_->RemoveObserver(&observer_);
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    external_data_manager_.reset();
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    store_.reset();
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunUntilIdle();
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void InitPolicyPayload(enterprise_management::CloudPolicySettings* payload) {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    payload->mutable_passwordmanagerenabled()->set_value(true);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    payload->mutable_urlblacklist()->mutable_value()->add_entries(
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "chromium.org");
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath policy_file() {
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return tmp_dir_.path().AppendASCII("policy");
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath key_file() {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return tmp_dir_.path().AppendASCII("policy_key");
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Verifies that store_->policy_map() has the appropriate entries.
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void VerifyPolicyMap(CloudPolicyStore* store) {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(2U, store->policy_map().size());
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PolicyMap::Entry* entry =
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        store->policy_map().Get(key::kPasswordManagerEnabled);
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(entry);
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_TRUE(base::FundamentalValue(true).Equals(entry->value));
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(store->policy_map().Get(key::kURLBlacklist));
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Install an expectation on |observer_| for an error code.
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ExpectError(CloudPolicyStore* store, CloudPolicyStore::Status error) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_CALL(observer_,
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                OnStoreError(AllOf(Eq(store),
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   Property(&CloudPolicyStore::status,
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            Eq(error)))));
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void StorePolicyAndEnsureLoaded(
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const enterprise_management::PolicyFetchResponse& policy) {
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Sequence s;
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    store_->Store(policy);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RunUntilIdle();
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Mock::VerifyAndClearExpectations(external_data_manager_.get());
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Mock::VerifyAndClearExpectations(&observer_);
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(store_->policy());
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserPolicyBuilder policy_;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockCloudPolicyStoreObserver observer_;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store_;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<MockCloudExternalDataManager> external_data_manager_;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // CloudPolicyValidator() requires a FILE thread so declare one here. Both
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |ui_thread_| and |file_thread_| share the same MessageLoop |loop_| so
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // callers can use RunLoop to manage both virtual threads.
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::MessageLoopForUI loop_;
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ScopedTempDir tmp_dir_;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyStoreTest);
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, LoadWithNoFile) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Sequence s;
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->Load();
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, LoadWithInvalidFile) {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a bogus file.
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(base::CreateDirectory(policy_file().DirName()));
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string bogus_data = "bogus_data";
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int size = bogus_data.size();
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(size, base::WriteFile(policy_file(),
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  bogus_data.c_str(), bogus_data.size()));
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->Load();
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithNoFile) {
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Sequence s;
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->LoadImmediately();  // Should load without running the message loop.
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithInvalidFile) {
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a bogus file.
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(base::CreateDirectory(policy_file().DirName()));
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string bogus_data = "bogus_data";
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int size = bogus_data.size();
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(size, base::WriteFile(policy_file(),
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  bogus_data.c_str(), bogus_data.size()));
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->LoadImmediately();  // Should load without running the message loop.
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Load file from cache with no key data - should give us a validation error.
21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, ShouldFailToLoadUnsignedPolicy) {
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserPolicyBuilder unsigned_builder;
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  unsigned_builder.UnsetSigningKey();
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  InitPolicyPayload(&unsigned_builder.payload());
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  unsigned_builder.Build();
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Policy should be unsigned.
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(unsigned_builder.policy().has_policy_data_signature());
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Write policy to disk.
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string data;
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(unsigned_builder.policy().SerializeToString(&data));
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(base::CreateDirectory(policy_file().DirName()));
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int size = data.size();
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(size, base::WriteFile(policy_file(), data.c_str(), size));
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Now make sure the data generates a validation error.
22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->LoadImmediately();  // Should load without running the message loop.
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&observer_);
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now mimic a new policy coming down - this should result in a new key
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // being installed.
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(policy_.policy().new_public_key(), store_->policy_key());
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy()->has_public_key_version());
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(base::PathExists(key_file()));
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, Store) {
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store a simple policy and make sure it ends up as the currently active
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // policy.
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Policy should be decoded and stored.
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(policy_.policy_data().SerializeAsString(),
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            store_->policy()->SerializeAsString());
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VerifyPolicyMap(store_.get());
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, StoreThenClear) {
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store a simple policy and make sure the file exists.
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // policy.
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy_map().empty());
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Policy file should exist.
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(base::PathExists(policy_file()));
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Sequence s2;
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s2);
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s2);
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->Clear();
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Policy file should not exist.
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(!base::PathExists(policy_file()));
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Policy should be gone.
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, StoreRotatedKey) {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store a simple policy and make sure it ends up as the currently active
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // policy.
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(policy_.policy().has_new_public_key_signature());
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string original_policy_key = policy_.policy().new_public_key();
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(original_policy_key, store_->policy_key());
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now do key rotation.
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.SetDefaultSigningKey();
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.SetDefaultNewSigningKey();
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.Build();
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(policy_.policy().has_new_public_key_signature());
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_NE(original_policy_key, policy_.policy().new_public_key());
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(policy_.policy().new_public_key(), store_->policy_key());
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, ProvisionKeyTwice) {
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store a simple policy and make sure it ends up as the currently active
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // policy.
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now try sending down policy signed with a different key (i.e. do key
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // rotation with a key not signed with the original signing key).
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.UnsetSigningKey();
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.SetDefaultNewSigningKey();
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.Build();
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(policy_.policy().has_new_public_key_signature());
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->Store(policy_.policy());
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, StoreTwoTimes) {
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy());
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(store_->policy_map().empty());
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store a simple policy then store a second policy before the first one
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // finishes validating, and make sure the second policy ends up as the active
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // policy.
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UserPolicyBuilder first_policy;
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  first_policy.SetDefaultInitialSigningKey();
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  first_policy.payload().mutable_passwordmanagerenabled()->set_value(false);
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  first_policy.Build();
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(first_policy.policy());
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Rebuild policy with the same signing key as |first_policy| (no rotation).
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.UnsetNewSigningKey();
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.SetDefaultSigningKey();
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.Build();
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(policy_.policy().has_new_public_key());
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Policy should be decoded and stored.
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(policy_.policy_data().SerializeAsString(),
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            store_->policy()->SerializeAsString());
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VerifyPolicyMap(store_.get());
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, StoreThenLoad) {
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store a simple policy and make sure it can be read back in.
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // policy.
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(store_->policy_key().empty());
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now, make sure the policy can be read back in from a second store.
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store2(
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new UserCloudPolicyStore(policy_file(),
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               key_file(),
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               GetPolicyVerificationKey(),
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               loop_.message_loop_proxy()));
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->AddObserver(&observer_);
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->Load();
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(store2->policy());
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(policy_.policy_data().SerializeAsString(),
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            store2->policy()->SerializeAsString());
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VerifyPolicyMap(store2.get());
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->RemoveObserver(&observer_);
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make sure that we properly resurrected the keys.
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(store2->policy_key(), store_->policy_key());
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, StoreThenLoadImmediately) {
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store a simple policy and make sure it can be read back in.
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // policy.
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now, make sure the policy can be read back in from a second store.
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store2(
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new UserCloudPolicyStore(policy_file(),
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               key_file(),
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               GetPolicyVerificationKey(),
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               loop_.message_loop_proxy()));
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->AddObserver(&observer_);
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->LoadImmediately();  // Should load without running the message loop.
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(store2->policy());
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(policy_.policy_data().SerializeAsString(),
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            store2->policy()->SerializeAsString());
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VerifyPolicyMap(store2.get());
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->RemoveObserver(&observer_);
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, StoreValidationError) {
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create an invalid policy (no policy type).
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.policy_data().clear_policy_type();
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.Build();
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store policy.
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->Store(policy_.policy());
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(store_->policy());
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, StoreUnsigned) {
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create unsigned policy, try to store it, should get a validation error.
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy_.policy().mutable_policy_data_signature()->clear();
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Store policy.
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store_->Store(policy_.policy());
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(store_->policy());
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, LoadValidationError) {
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Force a validation error by changing the username after policy is stored.
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sign out, and sign back in as a different user, and try to load the profile
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // data (should fail due to mismatched username).
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store2(
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new UserCloudPolicyStore(policy_file(),
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               key_file(),
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               GetPolicyVerificationKey(),
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               loop_.message_loop_proxy()));
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->SetSigninUsername("foobar@foobar.com");
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->AddObserver(&observer_);
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->Load();
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(store2->policy());
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->RemoveObserver(&observer_);
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sign out - we should be able to load the policy (don't check usernames
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // when signed out).
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store3(
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new UserCloudPolicyStore(policy_file(),
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               key_file(),
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               GetPolicyVerificationKey(),
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               loop_.message_loop_proxy()));
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store3->AddObserver(&observer_);
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(observer_, OnStoreLoaded(store3.get()));
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store3->Load();
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(store3->policy());
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store3->RemoveObserver(&observer_);
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now start a signin as a different user - this should fail validation.
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store4(
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new UserCloudPolicyStore(policy_file(),
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               key_file(),
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               GetPolicyVerificationKey(),
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               loop_.message_loop_proxy()));
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store4->SetSigninUsername("foobar@foobar.com");
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store4->AddObserver(&observer_);
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store4.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store4->Load();
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(store4->policy());
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store4->RemoveObserver(&observer_);
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, KeyRotation) {
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make sure when we load data from disk with a different key, that we trigger
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a server-side key rotation.
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(store_->policy()->has_public_key_version());
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string key_data;
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  enterprise_management::PolicySigningKey key;
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(base::ReadFileToString(key_file(), &key_data));
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(key.ParseFromString(key_data));
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  key.set_verification_key("different_key");
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  key.SerializeToString(&key_data);
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WriteStringToFile(key_file(), key_data);
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now load this in a new store - this should trigger key rotation. The keys
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // will still verify using the existing verification key.
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store2(
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new UserCloudPolicyStore(policy_file(),
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               key_file(),
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               GetPolicyVerificationKey(),
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               loop_.message_loop_proxy()));
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->AddObserver(&observer_);
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->Load();
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(store2->policy());
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(store2->policy()->has_public_key_version());
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->RemoveObserver(&observer_);
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(UserCloudPolicyStoreTest, InvalidCachedVerificationSignature) {
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make sure that we reject code with an invalid key.
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StorePolicyAndEnsureLoaded(policy_.policy());
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string key_data;
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  enterprise_management::PolicySigningKey key;
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(base::ReadFileToString(key_file(), &key_data));
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(key.ParseFromString(key_data));
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  key.set_signing_key_signature("different_key");
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  key.SerializeToString(&key_data);
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WriteStringToFile(key_file(), key_data);
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now load this in a new store - this should cause a validation error because
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the key won't verify.
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<UserCloudPolicyStore> store2(
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new UserCloudPolicyStore(policy_file(),
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               key_file(),
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               GetPolicyVerificationKey(),
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               loop_.message_loop_proxy()));
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->SetSigninUsername(PolicyBuilder::kFakeUsername);
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->AddObserver(&observer_);
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->Load();
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RunUntilIdle();
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  store2->RemoveObserver(&observer_);
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace policy
534