1// Copyright 2013 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 "components/policy/core/common/async_policy_provider.h" 6 7#include "base/callback.h" 8#include "base/memory/ref_counted.h" 9#include "base/message_loop/message_loop.h" 10#include "base/message_loop/message_loop_proxy.h" 11#include "base/sequenced_task_runner.h" 12#include "base/values.h" 13#include "components/policy/core/common/async_policy_loader.h" 14#include "components/policy/core/common/external_data_fetcher.h" 15#include "components/policy/core/common/mock_configuration_policy_provider.h" 16#include "components/policy/core/common/schema_registry.h" 17#include "testing/gmock/include/gmock/gmock.h" 18#include "testing/gtest/include/gtest/gtest.h" 19 20using testing::Mock; 21using testing::Return; 22using testing::Sequence; 23 24namespace policy { 25 26namespace { 27 28// Helper to write a policy in |bundle| with less code. 29void SetPolicy(PolicyBundle* bundle, 30 const std::string& name, 31 const std::string& value) { 32 bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 33 .Set(name, 34 POLICY_LEVEL_MANDATORY, 35 POLICY_SCOPE_USER, 36 new base::StringValue(value), 37 NULL); 38} 39 40class MockPolicyLoader : public AsyncPolicyLoader { 41 public: 42 explicit MockPolicyLoader( 43 scoped_refptr<base::SequencedTaskRunner> task_runner); 44 virtual ~MockPolicyLoader(); 45 46 // Load() returns a scoped_ptr<PolicyBundle> but it can't be mocked because 47 // scoped_ptr is moveable but not copyable. This override forwards the 48 // call to MockLoad() which returns a PolicyBundle*, and returns a copy 49 // wrapped in a passed scoped_ptr. 50 virtual scoped_ptr<PolicyBundle> Load() OVERRIDE; 51 52 MOCK_METHOD0(MockLoad, const PolicyBundle*()); 53 MOCK_METHOD0(InitOnBackgroundThread, void()); 54 MOCK_METHOD0(LastModificationTime, base::Time()); 55 56 private: 57 DISALLOW_COPY_AND_ASSIGN(MockPolicyLoader); 58}; 59 60MockPolicyLoader::MockPolicyLoader( 61 scoped_refptr<base::SequencedTaskRunner> task_runner) 62 : AsyncPolicyLoader(task_runner) {} 63 64MockPolicyLoader::~MockPolicyLoader() {} 65 66scoped_ptr<PolicyBundle> MockPolicyLoader::Load() { 67 scoped_ptr<PolicyBundle> bundle; 68 const PolicyBundle* loaded = MockLoad(); 69 if (loaded) { 70 bundle.reset(new PolicyBundle()); 71 bundle->CopyFrom(*loaded); 72 } 73 return bundle.Pass(); 74} 75 76} // namespace 77 78class AsyncPolicyProviderTest : public testing::Test { 79 protected: 80 AsyncPolicyProviderTest(); 81 virtual ~AsyncPolicyProviderTest(); 82 83 virtual void SetUp() OVERRIDE; 84 virtual void TearDown() OVERRIDE; 85 86 base::MessageLoop loop_; 87 SchemaRegistry schema_registry_; 88 PolicyBundle initial_bundle_; 89 MockPolicyLoader* loader_; 90 scoped_ptr<AsyncPolicyProvider> provider_; 91 92 private: 93 DISALLOW_COPY_AND_ASSIGN(AsyncPolicyProviderTest); 94}; 95 96AsyncPolicyProviderTest::AsyncPolicyProviderTest() {} 97 98AsyncPolicyProviderTest::~AsyncPolicyProviderTest() {} 99 100void AsyncPolicyProviderTest::SetUp() { 101 SetPolicy(&initial_bundle_, "policy", "initial"); 102 loader_ = new MockPolicyLoader(loop_.message_loop_proxy()); 103 EXPECT_CALL(*loader_, LastModificationTime()) 104 .WillRepeatedly(Return(base::Time())); 105 EXPECT_CALL(*loader_, InitOnBackgroundThread()).Times(1); 106 EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&initial_bundle_)); 107 108 provider_.reset(new AsyncPolicyProvider( 109 &schema_registry_, scoped_ptr<AsyncPolicyLoader>(loader_))); 110 provider_->Init(&schema_registry_); 111 // Verify that the initial load is done synchronously: 112 EXPECT_TRUE(provider_->policies().Equals(initial_bundle_)); 113 114 loop_.RunUntilIdle(); 115 Mock::VerifyAndClearExpectations(loader_); 116 117 EXPECT_CALL(*loader_, LastModificationTime()) 118 .WillRepeatedly(Return(base::Time())); 119} 120 121void AsyncPolicyProviderTest::TearDown() { 122 if (provider_) { 123 provider_->Shutdown(); 124 provider_.reset(); 125 } 126 loop_.RunUntilIdle(); 127} 128 129TEST_F(AsyncPolicyProviderTest, RefreshPolicies) { 130 PolicyBundle refreshed_bundle; 131 SetPolicy(&refreshed_bundle, "policy", "refreshed"); 132 EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&refreshed_bundle)); 133 134 MockConfigurationPolicyObserver observer; 135 provider_->AddObserver(&observer); 136 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1); 137 provider_->RefreshPolicies(); 138 loop_.RunUntilIdle(); 139 // The refreshed policies are now provided. 140 EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle)); 141 provider_->RemoveObserver(&observer); 142} 143 144TEST_F(AsyncPolicyProviderTest, RefreshPoliciesTwice) { 145 PolicyBundle refreshed_bundle; 146 SetPolicy(&refreshed_bundle, "policy", "refreshed"); 147 EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&refreshed_bundle)); 148 149 MockConfigurationPolicyObserver observer; 150 provider_->AddObserver(&observer); 151 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0); 152 provider_->RefreshPolicies(); 153 // Doesn't refresh before going through the background thread. 154 Mock::VerifyAndClearExpectations(&observer); 155 156 // Doesn't refresh if another RefreshPolicies request is made. 157 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0); 158 provider_->RefreshPolicies(); 159 Mock::VerifyAndClearExpectations(&observer); 160 161 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1); 162 loop_.RunUntilIdle(); 163 // The refreshed policies are now provided. 164 EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle)); 165 Mock::VerifyAndClearExpectations(&observer); 166 provider_->RemoveObserver(&observer); 167} 168 169TEST_F(AsyncPolicyProviderTest, RefreshPoliciesDuringReload) { 170 PolicyBundle reloaded_bundle; 171 SetPolicy(&reloaded_bundle, "policy", "reloaded"); 172 PolicyBundle refreshed_bundle; 173 SetPolicy(&refreshed_bundle, "policy", "refreshed"); 174 175 Sequence load_sequence; 176 // Reload. 177 EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence) 178 .WillOnce(Return(&reloaded_bundle)); 179 // RefreshPolicies. 180 EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence) 181 .WillOnce(Return(&refreshed_bundle)); 182 183 MockConfigurationPolicyObserver observer; 184 provider_->AddObserver(&observer); 185 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0); 186 187 // A Reload is triggered before RefreshPolicies, and it shouldn't trigger 188 // notifications. 189 loader_->Reload(true); 190 Mock::VerifyAndClearExpectations(&observer); 191 192 // Doesn't refresh before going through the background thread. 193 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0); 194 provider_->RefreshPolicies(); 195 Mock::VerifyAndClearExpectations(&observer); 196 197 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1); 198 loop_.RunUntilIdle(); 199 // The refreshed policies are now provided, and the |reloaded_bundle| was 200 // dropped. 201 EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle)); 202 Mock::VerifyAndClearExpectations(&observer); 203 provider_->RemoveObserver(&observer); 204} 205 206TEST_F(AsyncPolicyProviderTest, Shutdown) { 207 EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&initial_bundle_)); 208 209 MockConfigurationPolicyObserver observer; 210 provider_->AddObserver(&observer); 211 212 // Though there is a pending Reload, the provider and the loader can be 213 // deleted at any time. 214 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0); 215 loader_->Reload(true); 216 Mock::VerifyAndClearExpectations(&observer); 217 218 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0); 219 provider_->Shutdown(); 220 loop_.RunUntilIdle(); 221 Mock::VerifyAndClearExpectations(&observer); 222 223 provider_->RemoveObserver(&observer); 224 provider_.reset(); 225} 226 227} // namespace policy 228