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