Home | History | Annotate | Download | only in common
      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 
     20 using testing::Mock;
     21 using testing::Return;
     22 using testing::Sequence;
     23 
     24 namespace policy {
     25 
     26 namespace {
     27 
     28 // Helper to write a policy in |bundle| with less code.
     29 void 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 
     40 class 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 
     60 MockPolicyLoader::MockPolicyLoader(
     61     scoped_refptr<base::SequencedTaskRunner> task_runner)
     62     : AsyncPolicyLoader(task_runner) {}
     63 
     64 MockPolicyLoader::~MockPolicyLoader() {}
     65 
     66 scoped_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 
     78 class 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 
     96 AsyncPolicyProviderTest::AsyncPolicyProviderTest() {}
     97 
     98 AsyncPolicyProviderTest::~AsyncPolicyProviderTest() {}
     99 
    100 void 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 
    121 void AsyncPolicyProviderTest::TearDown() {
    122   if (provider_) {
    123     provider_->Shutdown();
    124     provider_.reset();
    125   }
    126   loop_.RunUntilIdle();
    127 }
    128 
    129 TEST_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 
    144 TEST_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 
    169 TEST_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 
    206 TEST_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