cloud_policy_invalidator_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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 <string>
6
7#include "base/basictypes.h"
8#include "base/bind.h"
9#include "base/memory/ref_counted.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/message_loop/message_loop.h"
12#include "base/metrics/histogram.h"
13#include "base/metrics/histogram_samples.h"
14#include "base/metrics/sample_map.h"
15#include "base/metrics/statistics_recorder.h"
16#include "base/run_loop.h"
17#include "base/test/test_simple_task_runner.h"
18#include "base/time/time.h"
19#include "base/values.h"
20#include "chrome/browser/invalidation/fake_invalidation_service.h"
21#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
22#include "chrome/browser/policy/cloud/cloud_policy_core.h"
23#include "chrome/browser/policy/cloud/cloud_policy_invalidator.h"
24#include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
25#include "chrome/browser/policy/cloud/enterprise_metrics.h"
26#include "chrome/browser/policy/cloud/mock_cloud_policy_client.h"
27#include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
28#include "chrome/browser/policy/policy_types.h"
29#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
30#include "policy/policy_constants.h"
31#include "sync/notifier/invalidation_util.h"
32#include "testing/gmock/include/gmock/gmock.h"
33#include "testing/gtest/include/gtest/gtest.h"
34
35namespace policy {
36
37class CloudPolicyInvalidatorTest : public testing::Test {
38 protected:
39  // Policy objects which can be used in tests.
40  enum PolicyObject {
41    POLICY_OBJECT_NONE,
42    POLICY_OBJECT_A,
43    POLICY_OBJECT_B
44  };
45
46  CloudPolicyInvalidatorTest();
47
48  virtual void SetUp() OVERRIDE;
49
50  virtual void TearDown() OVERRIDE;
51
52  // Starts the invalidator which will be tested.
53  // |initialize| determines if the invalidator should be initialized.
54  // |start_refresh_scheduler| determines if the refresh scheduler should start.
55  void StartInvalidator(bool initialize, bool start_refresh_scheduler);
56  void StartInvalidator() {
57    StartInvalidator(true /* initialize */, true /* start_refresh_scheduler */);
58  }
59
60  // Calls Initialize on the invalidator.
61  void InitializeInvalidator();
62
63  // Calls Shutdown on the invalidator. Test must call DestroyInvalidator
64  // afterwards to prevent Shutdown from being called twice.
65  void ShutdownInvalidator();
66
67  // Destroys the invalidator.
68  void DestroyInvalidator();
69
70  // Connects the cloud policy core.
71  void ConnectCore();
72
73  // Starts the refresh scheduler.
74  void StartRefreshScheduler();
75
76  // Disconnects the cloud policy core.
77  void DisconnectCore();
78
79  // Simulates storing a new policy to the policy store.
80  // |object| determines which policy object the store will report the
81  // invalidator should register for. May be POLICY_OBJECT_NONE for no object.
82  // |invalidation_version| determines what invalidation the store will report.
83  // |policy_changed| determines whether a policy value different from the
84  // current value will be stored.
85  // |timestamp| determines the response timestamp the store will report.
86  void StorePolicy(
87      PolicyObject object,
88      int64 invalidation_version,
89      bool policy_changed,
90      int64 timestamp);
91  void StorePolicy(
92      PolicyObject object,
93      int64 invalidation_version,
94      bool policy_changed) {
95    StorePolicy(object, invalidation_version, policy_changed, ++timestamp_);
96  }
97  void StorePolicy(PolicyObject object, int64 invalidation_version) {
98    StorePolicy(object, invalidation_version, false);
99  }
100  void StorePolicy(PolicyObject object) {
101    StorePolicy(object, 0);
102  }
103
104  // Disables the invalidation service. It is enabled by default.
105  void DisableInvalidationService();
106
107  // Enables the invalidation service. It is enabled by default.
108  void EnableInvalidationService();
109
110  // Causes the invalidation service to fire an invalidation. Returns an ack
111  // handle which be used to verify that the invalidation was acknowledged.
112  syncer::AckHandle FireInvalidation(
113      PolicyObject object,
114      int64 version,
115      const std::string& payload);
116
117  // Causes the invalidation service to fire an invalidation with unknown
118  // version. Returns an ack handle which be used to verify that the
119  // invalidation was acknowledged.
120  syncer::AckHandle FireInvalidation(PolicyObject object);
121
122  // Checks the expected value of the currently set invalidation info.
123  bool CheckInvalidationInfo(int64 version, const std::string& payload);
124
125  // Checks that the policy was not refreshed due to an invalidation.
126  bool CheckPolicyNotRefreshed();
127
128  // Checks that the policy was refreshed due to an invalidation within an
129  // appropriate timeframe depending on whether the invalidation had unknown
130  // version.
131  bool CheckPolicyRefreshed();
132  bool CheckPolicyRefreshedWithUnknownVersion();
133
134  // Returns the invalidations enabled state set by the invalidator on the
135  // refresh scheduler.
136  bool InvalidationsEnabled();
137
138  // Determines if the invalidation with the given ack handle has been
139  // acknowledged.
140  bool IsInvalidationAcknowledged(const syncer::AckHandle& ack_handle);
141
142  // Determines if the invalidator has registered for an object with the
143  // invalidation service.
144  bool IsInvalidatorRegistered();
145
146  // Get the current count for the given metric.
147  base::HistogramBase::Count GetCount(MetricPolicyRefresh metric);
148  base::HistogramBase::Count GetInvalidationCount(bool with_payload);
149
150 private:
151  // Checks that the policy was refreshed due to an invalidation with the given
152  // base delay.
153  bool CheckPolicyRefreshed(base::TimeDelta delay);
154
155  // Checks that the policy was refreshed the given number of times.
156  bool CheckPolicyRefreshCount(int count);
157
158  // Returns the object id of the given policy object.
159  const invalidation::ObjectId& GetPolicyObjectId(PolicyObject object) const;
160
161  // Get histogram samples for the given histogram.
162  scoped_ptr<base::HistogramSamples> GetHistogramSamples(
163      const std::string& name) const;
164
165  base::MessageLoop loop_;
166
167  // Objects the invalidator depends on.
168  invalidation::FakeInvalidationService invalidation_service_;
169  MockCloudPolicyStore store_;
170  CloudPolicyCore core_;
171  MockCloudPolicyClient* client_;
172  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
173
174  // The invalidator which will be tested.
175  scoped_ptr<CloudPolicyInvalidator> invalidator_;
176
177  // Object ids for the test policy objects.
178  invalidation::ObjectId object_id_a_;
179  invalidation::ObjectId object_id_b_;
180
181  // Increasing policy timestamp.
182  int64 timestamp_;
183
184  // Fake policy values which are alternated to cause the store to report a
185  // changed policy.
186  const char* policy_value_a_;
187  const char* policy_value_b_;
188
189  // The currently used policy value.
190  const char* policy_value_cur_;
191
192  // Stores starting histogram counts for kMetricPolicyRefresh.
193  scoped_ptr<base::HistogramSamples> refresh_samples_;
194
195  // Stores starting histogram counts for kMetricPolicyInvalidations.
196  scoped_ptr<base::HistogramSamples> invalidations_samples_;
197};
198
199CloudPolicyInvalidatorTest::CloudPolicyInvalidatorTest()
200    : core_(PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType,
201                               std::string()),
202            &store_,
203            loop_.message_loop_proxy()),
204      client_(NULL),
205      task_runner_(new base::TestSimpleTaskRunner()),
206      object_id_a_(135, "asdf"),
207      object_id_b_(246, "zxcv"),
208      timestamp_(123456),
209      policy_value_a_("asdf"),
210      policy_value_b_("zxcv"),
211      policy_value_cur_(policy_value_a_) {}
212
213void CloudPolicyInvalidatorTest::SetUp() {
214  base::StatisticsRecorder::Initialize();
215  refresh_samples_ = GetHistogramSamples(kMetricPolicyRefresh);
216  invalidations_samples_ = GetHistogramSamples(kMetricPolicyInvalidations);
217}
218
219void CloudPolicyInvalidatorTest::TearDown() {
220  EXPECT_FALSE(invalidation_service_.ReceivedInvalidAcknowledgement());
221  if (invalidator_)
222    invalidator_->Shutdown();
223  core_.Disconnect();
224}
225
226void CloudPolicyInvalidatorTest::StartInvalidator(
227    bool initialize,
228    bool start_refresh_scheduler) {
229  invalidator_.reset(new CloudPolicyInvalidator(&core_, task_runner_));
230  if (start_refresh_scheduler) {
231    ConnectCore();
232    StartRefreshScheduler();
233  }
234  if (initialize)
235    InitializeInvalidator();
236}
237
238void CloudPolicyInvalidatorTest::InitializeInvalidator() {
239  invalidator_->Initialize(&invalidation_service_);
240}
241
242void CloudPolicyInvalidatorTest::ShutdownInvalidator() {
243  invalidator_->Shutdown();
244}
245
246void CloudPolicyInvalidatorTest::DestroyInvalidator() {
247  invalidator_.reset();
248}
249
250void CloudPolicyInvalidatorTest::ConnectCore() {
251  client_ = new MockCloudPolicyClient();
252  client_->SetDMToken("dm");
253  core_.Connect(scoped_ptr<CloudPolicyClient>(client_));
254}
255
256void CloudPolicyInvalidatorTest::StartRefreshScheduler() {
257  core_.StartRefreshScheduler();
258}
259
260void CloudPolicyInvalidatorTest::DisconnectCore() {
261  client_ = NULL;
262  core_.Disconnect();
263}
264
265void CloudPolicyInvalidatorTest::StorePolicy(
266    PolicyObject object,
267    int64 invalidation_version,
268    bool policy_changed,
269    int64 timestamp) {
270  enterprise_management::PolicyData* data =
271      new enterprise_management::PolicyData();
272  if (object != POLICY_OBJECT_NONE) {
273    data->set_invalidation_source(GetPolicyObjectId(object).source());
274    data->set_invalidation_name(GetPolicyObjectId(object).name());
275  }
276  data->set_timestamp(timestamp);
277  // Swap the policy value if a policy change is desired.
278  if (policy_changed)
279    policy_value_cur_ = policy_value_cur_ == policy_value_a_ ?
280        policy_value_b_ : policy_value_a_;
281  data->set_policy_value(policy_value_cur_);
282  store_.invalidation_version_ = invalidation_version;
283  store_.policy_.reset(data);
284  base::DictionaryValue policies;
285  policies.SetInteger(
286      key::kMaxInvalidationFetchDelay,
287      CloudPolicyInvalidator::kMaxFetchDelayMin);
288  store_.policy_map_.LoadFrom(
289      &policies,
290      POLICY_LEVEL_MANDATORY,
291      POLICY_SCOPE_MACHINE);
292  store_.NotifyStoreLoaded();
293}
294
295void CloudPolicyInvalidatorTest::DisableInvalidationService() {
296  invalidation_service_.SetInvalidatorState(
297      syncer::TRANSIENT_INVALIDATION_ERROR);
298}
299
300void CloudPolicyInvalidatorTest::EnableInvalidationService() {
301  invalidation_service_.SetInvalidatorState(syncer::INVALIDATIONS_ENABLED);
302}
303
304syncer::AckHandle CloudPolicyInvalidatorTest::FireInvalidation(
305    PolicyObject object,
306    int64 version,
307    const std::string& payload) {
308  return invalidation_service_.EmitInvalidationForTest(
309      GetPolicyObjectId(object),
310      version,
311      payload);
312}
313
314syncer::AckHandle CloudPolicyInvalidatorTest::FireInvalidation(
315    PolicyObject object) {
316  return invalidation_service_.EmitInvalidationForTest(
317      GetPolicyObjectId(object),
318      syncer::Invalidation::kUnknownVersion,
319      std::string());
320}
321
322bool CloudPolicyInvalidatorTest::CheckInvalidationInfo(
323    int64 version,
324    const std::string& payload) {
325  MockCloudPolicyClient* client =
326      static_cast<MockCloudPolicyClient*>(core_.client());
327  return version == client->invalidation_version_ &&
328      payload == client->invalidation_payload_;
329}
330
331bool CloudPolicyInvalidatorTest::CheckPolicyNotRefreshed() {
332  return CheckPolicyRefreshCount(0);
333}
334
335bool CloudPolicyInvalidatorTest::CheckPolicyRefreshed() {
336  return CheckPolicyRefreshed(base::TimeDelta());
337}
338
339bool CloudPolicyInvalidatorTest::CheckPolicyRefreshedWithUnknownVersion() {
340  return CheckPolicyRefreshed(base::TimeDelta::FromMinutes(
341        CloudPolicyInvalidator::kMissingPayloadDelay));
342}
343
344bool CloudPolicyInvalidatorTest::InvalidationsEnabled() {
345  return core_.refresh_scheduler()->invalidations_available();
346}
347
348bool CloudPolicyInvalidatorTest::IsInvalidationAcknowledged(
349    const syncer::AckHandle& ack_handle) {
350  return invalidation_service_.IsInvalidationAcknowledged(ack_handle);
351}
352
353bool CloudPolicyInvalidatorTest::IsInvalidatorRegistered() {
354  return !invalidation_service_.invalidator_registrar()
355      .GetRegisteredIds(invalidator_.get()).empty();
356}
357
358base::HistogramBase::Count CloudPolicyInvalidatorTest::GetCount(
359    MetricPolicyRefresh metric) {
360  return GetHistogramSamples(kMetricPolicyRefresh)->GetCount(metric) -
361      refresh_samples_->GetCount(metric);
362}
363
364base::HistogramBase::Count CloudPolicyInvalidatorTest::GetInvalidationCount(
365    bool with_payload) {
366  int metric = with_payload ? 1 : 0;
367  return GetHistogramSamples(kMetricPolicyInvalidations)->GetCount(metric) -
368      invalidations_samples_->GetCount(metric);
369}
370
371bool CloudPolicyInvalidatorTest::CheckPolicyRefreshed(base::TimeDelta delay) {
372  base::TimeDelta max_delay = delay + base::TimeDelta::FromMilliseconds(
373      CloudPolicyInvalidator::kMaxFetchDelayMin);
374
375  if (task_runner_->GetPendingTasks().empty())
376    return false;
377  base::TimeDelta actual_delay = task_runner_->GetPendingTasks().back().delay;
378  EXPECT_GE(actual_delay, delay);
379  EXPECT_LE(actual_delay, max_delay);
380
381  return CheckPolicyRefreshCount(1);
382}
383
384bool CloudPolicyInvalidatorTest::CheckPolicyRefreshCount(int count) {
385  if (!client_) {
386    task_runner_->RunUntilIdle();
387    return count == 0;
388  }
389
390  // Clear any non-invalidation refreshes which may be pending.
391  EXPECT_CALL(*client_, FetchPolicy()).Times(testing::AnyNumber());
392  base::RunLoop().RunUntilIdle();
393  testing::Mock::VerifyAndClearExpectations(client_);
394
395  // Run the invalidator tasks then check for invalidation refreshes.
396  EXPECT_CALL(*client_, FetchPolicy()).Times(count);
397  task_runner_->RunUntilIdle();
398  base::RunLoop().RunUntilIdle();
399  return testing::Mock::VerifyAndClearExpectations(client_);
400}
401
402const invalidation::ObjectId& CloudPolicyInvalidatorTest::GetPolicyObjectId(
403    PolicyObject object) const {
404  EXPECT_TRUE(object == POLICY_OBJECT_A || object == POLICY_OBJECT_B);
405  return object == POLICY_OBJECT_A ? object_id_a_ : object_id_b_;
406}
407
408scoped_ptr<base::HistogramSamples>
409    CloudPolicyInvalidatorTest::GetHistogramSamples(
410        const std::string& name) const {
411  base::HistogramBase* histogram =
412      base::StatisticsRecorder::FindHistogram(name);
413  if (!histogram)
414    return scoped_ptr<base::HistogramSamples>(new base::SampleMap());
415  return histogram->SnapshotSamples();
416}
417
418TEST_F(CloudPolicyInvalidatorTest, Uninitialized) {
419  // No invalidations should be processed if the invalidator is not initialized.
420  StartInvalidator(false /* initialize */, true /* start_refresh_scheduler */);
421  StorePolicy(POLICY_OBJECT_A);
422  EXPECT_FALSE(IsInvalidatorRegistered());
423  FireInvalidation(POLICY_OBJECT_A);
424  EXPECT_TRUE(CheckPolicyNotRefreshed());
425}
426
427TEST_F(CloudPolicyInvalidatorTest, RefreshSchedulerNotStarted) {
428  // No invalidations should be processed if the refresh scheduler is not
429  // started.
430  StartInvalidator(true /* initialize */, false /* start_refresh_scheduler */);
431  StorePolicy(POLICY_OBJECT_A);
432  EXPECT_FALSE(IsInvalidatorRegistered());
433  FireInvalidation(POLICY_OBJECT_A);
434  EXPECT_TRUE(CheckPolicyNotRefreshed());
435}
436
437TEST_F(CloudPolicyInvalidatorTest, DisconnectCoreThenInitialize) {
438  // No invalidations should be processed if the core is disconnected before
439  // initialization.
440  StartInvalidator(false /* initialize */, true /* start_refresh_scheduler */);
441  DisconnectCore();
442  InitializeInvalidator();
443  StorePolicy(POLICY_OBJECT_A);
444  EXPECT_FALSE(IsInvalidatorRegistered());
445  FireInvalidation(POLICY_OBJECT_A);
446  EXPECT_TRUE(CheckPolicyNotRefreshed());
447}
448
449TEST_F(CloudPolicyInvalidatorTest, InitializeThenStartRefreshScheduler) {
450  // Make sure registration occurs and invalidations are processed when
451  // Initialize is called before starting the refresh scheduler.
452  // Note that the reverse case (start refresh scheduler then initialize) is
453  // the default behavior for the test fixture, so will be tested in most other
454  // tests.
455  StartInvalidator(true /* initialize */, false /* start_refresh_scheduler */);
456  ConnectCore();
457  StartRefreshScheduler();
458  StorePolicy(POLICY_OBJECT_A);
459  EXPECT_TRUE(IsInvalidatorRegistered());
460  FireInvalidation(POLICY_OBJECT_A);
461  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
462}
463
464TEST_F(CloudPolicyInvalidatorTest, RegisterOnStoreLoaded) {
465  // No registration when store is not loaded.
466  StartInvalidator();
467  EXPECT_FALSE(IsInvalidatorRegistered());
468  EXPECT_FALSE(InvalidationsEnabled());
469  FireInvalidation(POLICY_OBJECT_A);
470  FireInvalidation(POLICY_OBJECT_B);
471  EXPECT_TRUE(CheckPolicyNotRefreshed());
472
473  // No registration when store is loaded with no invalidation object id.
474  StorePolicy(POLICY_OBJECT_NONE);
475  EXPECT_FALSE(IsInvalidatorRegistered());
476  EXPECT_FALSE(InvalidationsEnabled());
477  FireInvalidation(POLICY_OBJECT_A);
478  FireInvalidation(POLICY_OBJECT_B);
479  EXPECT_TRUE(CheckPolicyNotRefreshed());
480
481  // Check registration when store is loaded for object A.
482  StorePolicy(POLICY_OBJECT_A);
483  EXPECT_TRUE(IsInvalidatorRegistered());
484  EXPECT_TRUE(InvalidationsEnabled());
485  FireInvalidation(POLICY_OBJECT_A);
486  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
487  FireInvalidation(POLICY_OBJECT_B);
488  EXPECT_TRUE(CheckPolicyNotRefreshed());
489}
490
491TEST_F(CloudPolicyInvalidatorTest, ChangeRegistration) {
492  // Register for object A.
493  StartInvalidator();
494  StorePolicy(POLICY_OBJECT_A);
495  EXPECT_TRUE(IsInvalidatorRegistered());
496  EXPECT_TRUE(InvalidationsEnabled());
497  FireInvalidation(POLICY_OBJECT_A);
498  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
499  FireInvalidation(POLICY_OBJECT_B);
500  EXPECT_TRUE(CheckPolicyNotRefreshed());
501  syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A);
502
503  // Check re-registration for object B. Make sure the pending invalidation for
504  // object A is acknowledged without making the callback.
505  StorePolicy(POLICY_OBJECT_B);
506  EXPECT_TRUE(IsInvalidatorRegistered());
507  EXPECT_TRUE(InvalidationsEnabled());
508  EXPECT_TRUE(IsInvalidationAcknowledged(ack));
509  EXPECT_TRUE(CheckPolicyNotRefreshed());
510
511  // Make sure future invalidations for object A are ignored and for object B
512  // are processed.
513  FireInvalidation(POLICY_OBJECT_A);
514  EXPECT_TRUE(CheckPolicyNotRefreshed());
515  FireInvalidation(POLICY_OBJECT_B);
516  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
517}
518
519TEST_F(CloudPolicyInvalidatorTest, UnregisterOnStoreLoaded) {
520  // Register for object A.
521  StartInvalidator();
522  StorePolicy(POLICY_OBJECT_A);
523  EXPECT_TRUE(IsInvalidatorRegistered());
524  EXPECT_TRUE(InvalidationsEnabled());
525  FireInvalidation(POLICY_OBJECT_A);
526  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
527
528  // Check unregistration when store is loaded with no invalidation object id.
529  syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A);
530  EXPECT_FALSE(IsInvalidationAcknowledged(ack));
531  StorePolicy(POLICY_OBJECT_NONE);
532  EXPECT_FALSE(IsInvalidatorRegistered());
533  EXPECT_TRUE(IsInvalidationAcknowledged(ack));
534  EXPECT_FALSE(InvalidationsEnabled());
535  FireInvalidation(POLICY_OBJECT_A);
536  FireInvalidation(POLICY_OBJECT_B);
537  EXPECT_TRUE(CheckPolicyNotRefreshed());
538
539  // Check re-registration for object B.
540  StorePolicy(POLICY_OBJECT_B);
541  EXPECT_TRUE(IsInvalidatorRegistered());
542  EXPECT_TRUE(InvalidationsEnabled());
543  FireInvalidation(POLICY_OBJECT_B);
544  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
545}
546
547TEST_F(CloudPolicyInvalidatorTest, HandleInvalidation) {
548  // Register and fire invalidation
549  StorePolicy(POLICY_OBJECT_A);
550  StartInvalidator();
551  EXPECT_TRUE(InvalidationsEnabled());
552  syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A, 12, "test_payload");
553
554  // Make sure client info is set as soon as the invalidation is received.
555  EXPECT_TRUE(CheckInvalidationInfo(12, "test_payload"));
556  EXPECT_TRUE(CheckPolicyRefreshed());
557
558  // Make sure invalidation is not acknowledged until the store is loaded.
559  EXPECT_FALSE(IsInvalidationAcknowledged(ack));
560  EXPECT_TRUE(CheckInvalidationInfo(12, "test_payload"));
561  StorePolicy(POLICY_OBJECT_A, 12);
562  EXPECT_TRUE(IsInvalidationAcknowledged(ack));
563  EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
564}
565
566TEST_F(CloudPolicyInvalidatorTest, HandleInvalidationWithUnknownVersion) {
567  // Register and fire invalidation with unknown version.
568  StorePolicy(POLICY_OBJECT_A);
569  StartInvalidator();
570  syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A);
571
572  // Make sure client info is not set until after the invalidation callback is
573  // made.
574  EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
575  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
576  EXPECT_TRUE(CheckInvalidationInfo(-1, std::string()));
577
578  // Make sure invalidation is not acknowledged until the store is loaded.
579  EXPECT_FALSE(IsInvalidationAcknowledged(ack));
580  StorePolicy(POLICY_OBJECT_A, -1);
581  EXPECT_TRUE(IsInvalidationAcknowledged(ack));
582  EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
583}
584
585TEST_F(CloudPolicyInvalidatorTest, HandleMultipleInvalidations) {
586  // Generate multiple invalidations.
587  StorePolicy(POLICY_OBJECT_A);
588  StartInvalidator();
589  syncer::AckHandle ack1 = FireInvalidation(POLICY_OBJECT_A, 1, "test1");
590  EXPECT_TRUE(CheckInvalidationInfo(1, "test1"));
591  syncer::AckHandle ack2 = FireInvalidation(POLICY_OBJECT_A, 2, "test2");
592  EXPECT_TRUE(CheckInvalidationInfo(2, "test2"));
593  syncer::AckHandle ack3= FireInvalidation(POLICY_OBJECT_A, 3, "test3");
594  EXPECT_TRUE(CheckInvalidationInfo(3, "test3"));
595
596  // Make sure the replaced invalidations are acknowledged.
597  EXPECT_TRUE(IsInvalidationAcknowledged(ack1));
598  EXPECT_TRUE(IsInvalidationAcknowledged(ack2));
599
600  // Make sure the policy is refreshed once.
601  EXPECT_TRUE(CheckPolicyRefreshed());
602
603  // Make sure that the last invalidation is only acknowledged after the store
604  // is loaded with the latest version.
605  StorePolicy(POLICY_OBJECT_A, 1);
606  EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
607  StorePolicy(POLICY_OBJECT_A, 2);
608  EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
609  StorePolicy(POLICY_OBJECT_A, 3);
610  EXPECT_TRUE(IsInvalidationAcknowledged(ack3));
611}
612
613TEST_F(CloudPolicyInvalidatorTest,
614       HandleMultipleInvalidationsWithUnknownVersion) {
615  // Validate that multiple invalidations with unknown version each generate
616  // unique invalidation version numbers.
617  StorePolicy(POLICY_OBJECT_A);
618  StartInvalidator();
619  syncer::AckHandle ack1 = FireInvalidation(POLICY_OBJECT_A);
620  EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
621  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
622  EXPECT_TRUE(CheckInvalidationInfo(-1, std::string()));
623  syncer::AckHandle ack2 = FireInvalidation(POLICY_OBJECT_A);
624  EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
625  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
626  EXPECT_TRUE(CheckInvalidationInfo(-2, std::string()));
627  syncer::AckHandle ack3 = FireInvalidation(POLICY_OBJECT_A);
628  EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
629  EXPECT_TRUE(CheckPolicyRefreshedWithUnknownVersion());
630  EXPECT_TRUE(CheckInvalidationInfo(-3, std::string()));
631
632  // Make sure the replaced invalidations are acknowledged.
633  EXPECT_TRUE(IsInvalidationAcknowledged(ack1));
634  EXPECT_TRUE(IsInvalidationAcknowledged(ack2));
635
636  // Make sure that the last invalidation is only acknowledged after the store
637  // is loaded with the last unknown version.
638  StorePolicy(POLICY_OBJECT_A, -1);
639  EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
640  StorePolicy(POLICY_OBJECT_A, -2);
641  EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
642  StorePolicy(POLICY_OBJECT_A, -3);
643  EXPECT_TRUE(IsInvalidationAcknowledged(ack3));
644}
645
646TEST_F(CloudPolicyInvalidatorTest, AcknowledgeBeforeRefresh) {
647  // Generate an invalidation.
648  StorePolicy(POLICY_OBJECT_A);
649  StartInvalidator();
650  syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A, 3, "test");
651
652  // Ensure that the policy is not refreshed and the invalidation is
653  // acknowledged if the store is loaded with the latest version before the
654  // refresh can occur.
655  StorePolicy(POLICY_OBJECT_A, 3);
656  EXPECT_TRUE(IsInvalidationAcknowledged(ack));
657  EXPECT_TRUE(CheckPolicyNotRefreshed());
658}
659
660TEST_F(CloudPolicyInvalidatorTest, NoCallbackAfterShutdown) {
661  // Generate an invalidation.
662  StorePolicy(POLICY_OBJECT_A);
663  StartInvalidator();
664  syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A, 3, "test");
665
666  // Ensure that the policy refresh is not made after the invalidator is shut
667  // down.
668  ShutdownInvalidator();
669  EXPECT_TRUE(CheckPolicyNotRefreshed());
670  DestroyInvalidator();
671}
672
673TEST_F(CloudPolicyInvalidatorTest, StateChanged) {
674  // Test invalidation service state changes while not registered.
675  StartInvalidator();
676  DisableInvalidationService();
677  EnableInvalidationService();
678  EXPECT_FALSE(InvalidationsEnabled());
679
680  // Test invalidation service state changes while registered.
681  StorePolicy(POLICY_OBJECT_A);
682  EXPECT_TRUE(InvalidationsEnabled());
683  DisableInvalidationService();
684  EXPECT_FALSE(InvalidationsEnabled());
685  DisableInvalidationService();
686  EXPECT_FALSE(InvalidationsEnabled());
687  EnableInvalidationService();
688  EXPECT_TRUE(InvalidationsEnabled());
689  EnableInvalidationService();
690  EXPECT_TRUE(InvalidationsEnabled());
691
692  // Test registration changes with invalidation service enabled.
693  StorePolicy(POLICY_OBJECT_NONE);
694  EXPECT_FALSE(InvalidationsEnabled());
695  StorePolicy(POLICY_OBJECT_NONE);
696  EXPECT_FALSE(InvalidationsEnabled());
697  StorePolicy(POLICY_OBJECT_A);
698  EXPECT_TRUE(InvalidationsEnabled());
699  StorePolicy(POLICY_OBJECT_A);
700  EXPECT_TRUE(InvalidationsEnabled());
701
702  // Test registration changes with invalidation service disabled.
703  DisableInvalidationService();
704  EXPECT_FALSE(InvalidationsEnabled());
705  StorePolicy(POLICY_OBJECT_NONE);
706  StorePolicy(POLICY_OBJECT_A);
707  EXPECT_FALSE(InvalidationsEnabled());
708}
709
710TEST_F(CloudPolicyInvalidatorTest, Disconnect) {
711  // Generate an invalidation.
712  StorePolicy(POLICY_OBJECT_A);
713  StartInvalidator();
714  syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A, 1, "test");
715  EXPECT_TRUE(InvalidationsEnabled());
716
717  // Ensure that the policy is not refreshed after disconnecting the core, but
718  // a call to indicate that invalidations are disabled is made.
719  DisconnectCore();
720  EXPECT_TRUE(CheckPolicyNotRefreshed());
721
722  // Ensure that invalidation service events do not cause refreshes while the
723  // invalidator is stopped.
724  FireInvalidation(POLICY_OBJECT_A, 2, "test");
725  EXPECT_TRUE(CheckPolicyNotRefreshed());
726  DisableInvalidationService();
727  EnableInvalidationService();
728
729  // Connect and disconnect without starting the refresh scheduler.
730  ConnectCore();
731  FireInvalidation(POLICY_OBJECT_A, 3, "test");
732  EXPECT_TRUE(CheckPolicyNotRefreshed());
733  DisconnectCore();
734  FireInvalidation(POLICY_OBJECT_A, 4, "test");
735  EXPECT_TRUE(CheckPolicyNotRefreshed());
736
737  // Ensure that the invalidator returns to normal after reconnecting.
738  ConnectCore();
739  StartRefreshScheduler();
740  EXPECT_TRUE(CheckPolicyNotRefreshed());
741  EXPECT_TRUE(InvalidationsEnabled());
742  FireInvalidation(POLICY_OBJECT_A, 5, "test");
743  EXPECT_TRUE(CheckInvalidationInfo(5, "test"));
744  EXPECT_TRUE(CheckPolicyRefreshed());
745  DisableInvalidationService();
746  EXPECT_FALSE(InvalidationsEnabled());
747}
748
749TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsUnregistered) {
750  // Store loads occurring before invalidation registration are not counted.
751  StartInvalidator();
752  StorePolicy(POLICY_OBJECT_NONE, 0, false /* policy_changed */);
753  StorePolicy(POLICY_OBJECT_NONE, 0, true /* policy_changed */);
754  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED));
755  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
756  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
757  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
758  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
759}
760
761TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsNoInvalidations) {
762  // Store loads occurring while registered should be differentiated depending
763  // on whether the invalidation service was enabled or not.
764  StorePolicy(POLICY_OBJECT_A);
765  StartInvalidator();
766  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
767  StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
768  DisableInvalidationService();
769  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
770  StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
771  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
772  StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
773  EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_CHANGED));
774  EXPECT_EQ(2, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
775  EXPECT_EQ(3, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
776  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
777  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
778}
779
780TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsStoreSameTimestamp) {
781  // Store loads with the same timestamp as the load which causes registration
782  // are not counted.
783  StartInvalidator();
784  StorePolicy(
785      POLICY_OBJECT_A, 0, false /* policy_changed */, 12 /* timestamp */);
786  StorePolicy(
787      POLICY_OBJECT_A, 0, false /* policy_changed */, 12 /* timestamp */);
788  StorePolicy(
789      POLICY_OBJECT_A, 0, true /* policy_changed */, 12 /* timestamp */);
790
791  // The next load with a different timestamp counts.
792  StorePolicy(
793      POLICY_OBJECT_A, 0, true /* policy_changed */, 13 /* timestamp */);
794
795  EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_CHANGED));
796  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
797  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
798  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
799  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
800}
801
802TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsInvalidation) {
803  // Store loads after an invalidation are counted as invalidated, even if
804  // the loads do not result in the invalidation being acknowledged.
805  StartInvalidator();
806  StorePolicy(POLICY_OBJECT_A);
807  FireInvalidation(POLICY_OBJECT_A, 5, "test");
808  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
809  StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
810  StorePolicy(POLICY_OBJECT_A, 5, true /* policy_changed */);
811
812  // Store loads after the invalidation is complete are not counted as
813  // invalidated.
814  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
815  StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
816  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
817  StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
818  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
819  StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
820  StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
821
822  EXPECT_EQ(3, GetCount(METRIC_POLICY_REFRESH_CHANGED));
823  EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
824  EXPECT_EQ(4, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
825  EXPECT_EQ(2, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
826  EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
827}
828
829TEST_F(CloudPolicyInvalidatorTest, InvalidationMetrics) {
830  // Generate a mix of versioned and unknown-version invalidations.
831  StorePolicy(POLICY_OBJECT_A);
832  StartInvalidator();
833  FireInvalidation(POLICY_OBJECT_B);
834  FireInvalidation(POLICY_OBJECT_A);
835  FireInvalidation(POLICY_OBJECT_B, 1, "test");
836  FireInvalidation(POLICY_OBJECT_A, 1, "test");
837  FireInvalidation(POLICY_OBJECT_A, 2, "test");
838  FireInvalidation(POLICY_OBJECT_A);
839  FireInvalidation(POLICY_OBJECT_A);
840  FireInvalidation(POLICY_OBJECT_A, 3, "test");
841  FireInvalidation(POLICY_OBJECT_A, 4, "test");
842
843  // Verify that received invalidations metrics are correct.
844  EXPECT_EQ(3, GetInvalidationCount(false /* with_payload */));
845  EXPECT_EQ(4, GetInvalidationCount(true /* with_payload */));
846}
847
848}  // namespace policy
849