Home | History | Annotate | Download | only in cloud
      1 // Copyright (c) 2012 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 "chrome/browser/policy/cloud/cloud_policy_service.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
     10 #include "chrome/browser/policy/cloud/mock_cloud_policy_client.h"
     11 #include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
     12 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
     13 #include "testing/gmock/include/gmock/gmock.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace em = enterprise_management;
     17 
     18 using testing::_;
     19 
     20 namespace policy {
     21 
     22 class MockCloudPolicyServiceObserver : public CloudPolicyService::Observer {
     23  public:
     24   MockCloudPolicyServiceObserver() {}
     25   virtual ~MockCloudPolicyServiceObserver() {}
     26 
     27   MOCK_METHOD1(OnInitializationCompleted, void(CloudPolicyService* service));
     28  private:
     29   DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyServiceObserver);
     30 };
     31 
     32 class CloudPolicyServiceTest : public testing::Test {
     33  public:
     34   CloudPolicyServiceTest()
     35       : policy_ns_key_(dm_protocol::kChromeUserPolicyType, std::string()),
     36         service_(policy_ns_key_, &client_, &store_) {}
     37 
     38   MOCK_METHOD1(OnPolicyRefresh, void(bool));
     39 
     40  protected:
     41   PolicyNamespaceKey policy_ns_key_;
     42   MockCloudPolicyClient client_;
     43   MockCloudPolicyStore store_;
     44   CloudPolicyService service_;
     45 };
     46 
     47 MATCHER_P(ProtoMatches, proto, "") {
     48   return arg.SerializePartialAsString() == proto.SerializePartialAsString();
     49 }
     50 
     51 TEST_F(CloudPolicyServiceTest, ManagedByEmptyPolicy) {
     52   EXPECT_EQ("", service_.ManagedBy());
     53 }
     54 
     55 TEST_F(CloudPolicyServiceTest, ManagedByValidPolicy) {
     56   store_.policy_.reset(new em::PolicyData());
     57   store_.policy_->set_username("user (at) example.com");
     58   EXPECT_EQ("example.com", service_.ManagedBy());
     59 }
     60 
     61 TEST_F(CloudPolicyServiceTest, PolicyUpdateSuccess) {
     62   em::PolicyFetchResponse policy;
     63   policy.set_policy_data("fake policy");
     64   client_.SetPolicy(policy_ns_key_, policy);
     65   EXPECT_CALL(store_, Store(ProtoMatches(policy))).Times(1);
     66   client_.NotifyPolicyFetched();
     67 
     68   // After |store_| initializes, credentials and other meta data should be
     69   // transferred to |client_|.
     70   store_.policy_.reset(new em::PolicyData());
     71   store_.policy_->set_request_token("fake token");
     72   store_.policy_->set_device_id("fake client id");
     73   store_.policy_->set_timestamp(32);
     74   store_.policy_->set_valid_serial_number_missing(true);
     75   store_.policy_->set_public_key_version(17);
     76   EXPECT_CALL(client_,
     77               SetupRegistration(store_.policy_->request_token(),
     78                                 store_.policy_->device_id())).Times(1);
     79   store_.NotifyStoreLoaded();
     80   EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMilliseconds(32),
     81             client_.last_policy_timestamp_);
     82   EXPECT_TRUE(client_.submit_machine_id_);
     83   EXPECT_TRUE(client_.public_key_version_valid_);
     84   EXPECT_EQ(17, client_.public_key_version_);
     85 }
     86 
     87 TEST_F(CloudPolicyServiceTest, PolicyUpdateClientFailure) {
     88   client_.SetStatus(DM_STATUS_REQUEST_FAILED);
     89   EXPECT_CALL(store_, Store(_)).Times(0);
     90   client_.NotifyPolicyFetched();
     91 }
     92 
     93 TEST_F(CloudPolicyServiceTest, RefreshPolicySuccess) {
     94   testing::InSequence seq;
     95 
     96   EXPECT_CALL(*this, OnPolicyRefresh(_)).Times(0);
     97   client_.SetDMToken("fake token");
     98 
     99   // Trigger a fetch on the client.
    100   EXPECT_CALL(client_, FetchPolicy()).Times(1);
    101   service_.RefreshPolicy(base::Bind(&CloudPolicyServiceTest::OnPolicyRefresh,
    102                                     base::Unretained(this)));
    103 
    104   // Client responds, push policy to store.
    105   em::PolicyFetchResponse policy;
    106   policy.set_policy_data("fake policy");
    107   client_.SetPolicy(policy_ns_key_, policy);
    108   client_.fetched_invalidation_version_ = 12345;
    109   EXPECT_CALL(store_, Store(ProtoMatches(policy))).Times(1);
    110   EXPECT_EQ(0, store_.invalidation_version());
    111   client_.NotifyPolicyFetched();
    112   EXPECT_EQ(12345, store_.invalidation_version());
    113 
    114   // Store reloads policy, callback gets triggered.
    115   store_.policy_.reset(new em::PolicyData());
    116   store_.policy_->set_request_token("token");
    117   store_.policy_->set_device_id("device-id");
    118   EXPECT_CALL(*this, OnPolicyRefresh(true)).Times(1);
    119   store_.NotifyStoreLoaded();
    120 }
    121 
    122 TEST_F(CloudPolicyServiceTest, RefreshPolicyNotRegistered) {
    123   // Clear the token so the client is not registered.
    124   client_.SetDMToken(std::string());
    125 
    126   EXPECT_CALL(client_, FetchPolicy()).Times(0);
    127   EXPECT_CALL(*this, OnPolicyRefresh(false)).Times(1);
    128   service_.RefreshPolicy(base::Bind(&CloudPolicyServiceTest::OnPolicyRefresh,
    129                                     base::Unretained(this)));
    130 }
    131 
    132 TEST_F(CloudPolicyServiceTest, RefreshPolicyClientError) {
    133   testing::InSequence seq;
    134 
    135   EXPECT_CALL(*this, OnPolicyRefresh(_)).Times(0);
    136   client_.SetDMToken("fake token");
    137 
    138   // Trigger a fetch on the client.
    139   EXPECT_CALL(client_, FetchPolicy()).Times(1);
    140   service_.RefreshPolicy(base::Bind(&CloudPolicyServiceTest::OnPolicyRefresh,
    141                                     base::Unretained(this)));
    142 
    143   // Client responds with an error, which should trigger the callback.
    144   client_.SetStatus(DM_STATUS_REQUEST_FAILED);
    145   EXPECT_CALL(*this, OnPolicyRefresh(false)).Times(1);
    146   client_.NotifyClientError();
    147 }
    148 
    149 TEST_F(CloudPolicyServiceTest, RefreshPolicyStoreError) {
    150   testing::InSequence seq;
    151 
    152   EXPECT_CALL(*this, OnPolicyRefresh(_)).Times(0);
    153   client_.SetDMToken("fake token");
    154 
    155   // Trigger a fetch on the client.
    156   EXPECT_CALL(client_, FetchPolicy()).Times(1);
    157   service_.RefreshPolicy(base::Bind(&CloudPolicyServiceTest::OnPolicyRefresh,
    158                                     base::Unretained(this)));
    159 
    160   // Client responds, push policy to store.
    161   em::PolicyFetchResponse policy;
    162   policy.set_policy_data("fake policy");
    163   client_.SetPolicy(policy_ns_key_, policy);
    164   EXPECT_CALL(store_, Store(ProtoMatches(policy))).Times(1);
    165   client_.NotifyPolicyFetched();
    166 
    167   // Store fails, which should trigger the callback.
    168   EXPECT_CALL(*this, OnPolicyRefresh(false)).Times(1);
    169   store_.NotifyStoreError();
    170 }
    171 
    172 TEST_F(CloudPolicyServiceTest, RefreshPolicyConcurrent) {
    173   testing::InSequence seq;
    174 
    175   EXPECT_CALL(*this, OnPolicyRefresh(_)).Times(0);
    176   client_.SetDMToken("fake token");
    177 
    178   // Trigger a fetch on the client.
    179   EXPECT_CALL(client_, FetchPolicy()).Times(1);
    180   service_.RefreshPolicy(base::Bind(&CloudPolicyServiceTest::OnPolicyRefresh,
    181                                     base::Unretained(this)));
    182 
    183   // Triggering another policy refresh should generate a new fetch request.
    184   EXPECT_CALL(client_, FetchPolicy()).Times(1);
    185   service_.RefreshPolicy(base::Bind(&CloudPolicyServiceTest::OnPolicyRefresh,
    186                                     base::Unretained(this)));
    187 
    188   // Client responds, push policy to store.
    189   em::PolicyFetchResponse policy;
    190   policy.set_policy_data("fake policy");
    191   client_.SetPolicy(policy_ns_key_, policy);
    192   EXPECT_CALL(store_, Store(ProtoMatches(policy))).Times(1);
    193   client_.NotifyPolicyFetched();
    194 
    195   // Trigger another policy fetch.
    196   EXPECT_CALL(client_, FetchPolicy()).Times(1);
    197   service_.RefreshPolicy(base::Bind(&CloudPolicyServiceTest::OnPolicyRefresh,
    198                                     base::Unretained(this)));
    199 
    200   // The store finishing the first load should not generate callbacks.
    201   EXPECT_CALL(*this, OnPolicyRefresh(_)).Times(0);
    202   store_.NotifyStoreLoaded();
    203 
    204   // Second policy fetch finishes.
    205   EXPECT_CALL(store_, Store(ProtoMatches(policy))).Times(1);
    206   client_.NotifyPolicyFetched();
    207 
    208   // Corresponding store operation finishes, all _three_ callbacks fire.
    209   EXPECT_CALL(*this, OnPolicyRefresh(true)).Times(3);
    210   store_.NotifyStoreLoaded();
    211 }
    212 
    213 TEST_F(CloudPolicyServiceTest, StoreAlreadyInitialized) {
    214   // Service should start off initialized if the store has already loaded
    215   // policy.
    216   store_.NotifyStoreLoaded();
    217   CloudPolicyService service(policy_ns_key_, &client_, &store_);
    218   EXPECT_TRUE(service.IsInitializationComplete());
    219 }
    220 
    221 TEST_F(CloudPolicyServiceTest, StoreLoadAfterCreation) {
    222   // Service should start off un-initialized if the store has not yet loaded
    223   // policy.
    224   EXPECT_FALSE(service_.IsInitializationComplete());
    225   MockCloudPolicyServiceObserver observer;
    226   service_.AddObserver(&observer);
    227   // Service should be marked as initialized and observer should be called back.
    228   EXPECT_CALL(observer, OnInitializationCompleted(&service_)).Times(1);
    229   store_.NotifyStoreLoaded();
    230   EXPECT_TRUE(service_.IsInitializationComplete());
    231   testing::Mock::VerifyAndClearExpectations(&observer);
    232 
    233   // Now, the next time the store is loaded, the observer should not be called
    234   // again.
    235   EXPECT_CALL(observer, OnInitializationCompleted(&service_)).Times(0);
    236   store_.NotifyStoreLoaded();
    237   service_.RemoveObserver(&observer);
    238 }
    239 
    240 }  // namespace policy
    241