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