Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Unified Diff: chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc

Issue 19733003: Implement cloud policy invalidations using the invalidation service framework. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0dd9e4d6a67948bc70353534f756d5d15fab1205
--- /dev/null
+++ b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
@@ -0,0 +1,724 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_samples.h"
+#include "base/metrics/sample_map.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/invalidation/fake_invalidation_service.h"
+#include "chrome/browser/policy/cloud/cloud_policy_core.h"
+#include "chrome/browser/policy/cloud/cloud_policy_invalidator.h"
+#include "chrome/browser/policy/cloud/cloud_policy_service.h"
+#include "chrome/browser/policy/cloud/enterprise_metrics.h"
+#include "chrome/browser/policy/cloud/mock_cloud_policy_client.h"
+#include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
+#include "chrome/browser/policy/policy_types.h"
+#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
+#include "policy/policy_constants.h"
+#include "sync/notifier/invalidation_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+class CloudPolicyInvalidatorTest : public testing::Test,
+ public CloudPolicyInvalidationHandler {
+ protected:
+ // Policy objects which can be used in tests.
+ enum PolicyObject {
+ POLICY_OBJECT_NONE,
+ POLICY_OBJECT_A,
+ POLICY_OBJECT_B
+ };
+
+ CloudPolicyInvalidatorTest();
+
+ virtual void SetUp() OVERRIDE;
+
+ virtual void TearDown() OVERRIDE;
+
+ // Starts the invalidator which will be tested.
+ void StartInvalidator(bool initialize);
+ void StartInvalidator() {
+ StartInvalidator(true /* initialize */);
+ }
+
+ // Simulates storing a new policy to the policy store.
+ // |object| determines which policy object the store will report the
+ // invalidator should register for. May be POLICY_OBJECT_NONE for no object.
+ // |invalidation_version| determines what invalidation the store will report.
+ // |policy_changed| determines whether the store will report that the
+ // policy changed.
+ // |timestamp| determines the response timestamp the store will report.
+ void StorePolicy(
+ PolicyObject object,
+ int64 invalidation_version,
+ bool policy_changed,
+ int64 timestamp);
+ void StorePolicy(
+ PolicyObject object,
+ int64 invalidation_version,
+ bool policy_changed) {
+ StorePolicy(object, invalidation_version, policy_changed, ++timestamp_);
+ }
+ void StorePolicy(PolicyObject object, int64 invalidation_version) {
+ StorePolicy(object, invalidation_version, false);
+ }
+ void StorePolicy(PolicyObject object) {
+ StorePolicy(object, 0);
+ }
+
+ // Disables the invalidation service. It is enabled by default.
+ void DisableInvalidationService();
+
+ // Enables the invalidation service. It is enabled by default.
+ void EnableInvalidationService();
+
+ // Causes the invalidation service to fire an invalidation. Returns an ack
+ // handle which be used to verify that the invalidation was acknowledged.
+ syncer::AckHandle FireInvalidation(
+ PolicyObject object,
+ int64 version,
+ const std::string& payload);
+
+ // Causes the invalidation service to fire an invalidation with unknown
+ // version. Returns an ack handle which be used to verify that the
+ // invalidation was acknowledged.
+ syncer::AckHandle FireInvalidation(PolicyObject object);
+
+ // Checks the expected value of the currently set invalidation info.
+ bool CheckInvalidationInfo(int64 version, const std::string& payload);
+
+ // Checks that the invalidate callback was not called.
+ bool CheckInvalidateNotCalled();
+
+ // Checks that the invalidate callback was called within an appropriate
+ // timeframe depending on whether the invalidation had unknown version.
+ bool CheckInvalidateCalled(bool unknown_version);
+ bool CheckInvalidateCalled() {
+ return CheckInvalidateCalled(true);
+ }
+
+ // Checks that the state changed callback of the invalidation handler was not
+ // called.
+ bool CheckStateChangedNotCalled();
+
+ // Checks that the state changed callback of the invalidation handler was
+ // called with the given state.
+ bool CheckStateChangedCalled(bool invalidations_enabled);
+
+ // Determines if the invalidation with the given ack handle has been
+ // acknowledged.
+ bool IsInvalidationAcknowledged(const syncer::AckHandle& ack_handle);
+
+ // Get the current count for the given metric.
+ base::HistogramBase::Count GetCount(MetricPolicyRefresh metric);
+ base::HistogramBase::Count GetInvalidationCount(bool with_payload);
+
+ // CloudPolicyInvalidationHandler:
+ virtual void SetInvalidationInfo(
+ int64 version,
+ const std::string& payload) OVERRIDE;
+ virtual void InvalidatePolicy() OVERRIDE;
+ virtual void OnInvalidatorStateChanged(bool invalidations_enabled) OVERRIDE;
+
+ private:
+ // Returns the object id of the given policy object.
+ const invalidation::ObjectId& GetPolicyObjectId(PolicyObject object) const;
+
+ // Get histogram samples for the given histogram.
+ scoped_ptr<base::HistogramSamples> GetHistogramSamples(
+ const std::string& name) const;
+
+ // Objects the invalidator depends on.
+ invalidation::FakeInvalidationService invalidation_service_;
+ MockCloudPolicyStore store_;
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+
+ // The invalidator which will be tested.
+ scoped_ptr<CloudPolicyInvalidator> invalidator_;
+
+ // The latest invalidation info set by the invalidator.
+ int64 invalidation_version_;
+ std::string invalidation_payload_;
+
+ // Object ids for the test policy objects.
+ invalidation::ObjectId object_id_a_;
+ invalidation::ObjectId object_id_b_;
+
+ // Increasing policy timestamp.
+ int64 timestamp_;
+
+ // Fake policy values which are alternated to cause the store to report a
+ // changed policy.
+ const char* policy_value_a_;
+ const char* policy_value_b_;
+
+ // The currently used policy value.
+ const char* policy_value_cur_;
+
+ // Stores how many times the invalidate callback was called.
+ int invalidate_callback_count_;
+
+ // Stores how many times the state change callback was called for each state.
+ int state_change_enabled_callback_count_;
+ int state_change_disabled_callback_count_;
+
+ // Stores starting histogram counts for kMetricPolicyRefresh.
+ scoped_ptr<base::HistogramSamples> refresh_samples_;
+
+ // Stores starting histogram counts for kMetricPolicyInvalidations.
+ scoped_ptr<base::HistogramSamples> invalidations_samples_;
+};
+
+CloudPolicyInvalidatorTest::CloudPolicyInvalidatorTest()
+ : task_runner_(new base::TestSimpleTaskRunner()),
+ invalidation_version_(0),
+ object_id_a_(135, "asdf"),
+ object_id_b_(246, "zxcv"),
+ timestamp_(123456),
+ policy_value_a_("asdf"),
+ policy_value_b_("zxcv"),
+ policy_value_cur_(policy_value_a_),
+ invalidate_callback_count_(0),
+ state_change_enabled_callback_count_(0),
+ state_change_disabled_callback_count_(0) {}
+
+void CloudPolicyInvalidatorTest::SetUp() {
+ base::StatisticsRecorder::Initialize();
+ refresh_samples_ = GetHistogramSamples(kMetricPolicyRefresh);
+ invalidations_samples_ = GetHistogramSamples(kMetricPolicyInvalidations);
+}
+
+void CloudPolicyInvalidatorTest::TearDown() {
+ EXPECT_FALSE(invalidation_service_.ReceivedInvalidAcknowledgement());
+ if (invalidator_)
+ invalidator_->Shutdown();
+}
+
+void CloudPolicyInvalidatorTest::StartInvalidator(bool initialize) {
+ invalidator_.reset(new CloudPolicyInvalidator(
+ this /* invalidation_handler */,
+ &store_,
+ task_runner_));
+ if (initialize)
+ invalidator_->InitializeWithService(&invalidation_service_);
+}
+
+void CloudPolicyInvalidatorTest::StorePolicy(
+ PolicyObject object,
+ int64 invalidation_version,
+ bool policy_changed,
+ int64 timestamp) {
+ enterprise_management::PolicyData* data =
+ new enterprise_management::PolicyData();
+ if (object != POLICY_OBJECT_NONE) {
+ data->set_invalidation_source(GetPolicyObjectId(object).source());
+ data->set_invalidation_name(GetPolicyObjectId(object).name());
+ }
+ data->set_timestamp(timestamp);
+ // Swap the policy value if a policy change is desired.
+ if (policy_changed)
+ policy_value_cur_ = policy_value_cur_ == policy_value_a_ ?
+ policy_value_b_ : policy_value_a_;
+ data->set_policy_value(policy_value_cur_);
+ store_.invalidation_version_ = invalidation_version;
+ store_.policy_.reset(data);
+ base::DictionaryValue policies;
+ policies.SetInteger(
+ key::kMaxInvalidationFetchDelay,
+ CloudPolicyInvalidator::kMaxFetchDelayMin);
+ store_.policy_map_.LoadFrom(
+ &policies,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_MACHINE);
+ store_.NotifyStoreLoaded();
+}
+
+void CloudPolicyInvalidatorTest::DisableInvalidationService() {
+ invalidation_service_.SetInvalidatorState(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+}
+
+void CloudPolicyInvalidatorTest::EnableInvalidationService() {
+ invalidation_service_.SetInvalidatorState(syncer::INVALIDATIONS_ENABLED);
+}
+
+syncer::AckHandle CloudPolicyInvalidatorTest::FireInvalidation(
+ PolicyObject object,
+ int64 version,
+ const std::string& payload) {
+ return invalidation_service_.EmitInvalidationForTest(
+ GetPolicyObjectId(object),
+ version,
+ payload);
+}
+
+syncer::AckHandle CloudPolicyInvalidatorTest::FireInvalidation(
+ PolicyObject object) {
+ return invalidation_service_.EmitInvalidationForTest(
+ GetPolicyObjectId(object),
+ syncer::Invalidation::kUnknownVersion,
+ std::string());
+}
+
+bool CloudPolicyInvalidatorTest::CheckInvalidationInfo(
+ int64 version,
+ const std::string& payload) {
+ return version == invalidation_version_ && payload == invalidation_payload_;
+}
+
+bool CloudPolicyInvalidatorTest::CheckInvalidateNotCalled() {
+ bool result = true;
+ if (invalidate_callback_count_ != 0)
+ result = false;
+ task_runner_->RunUntilIdle();
+ if (invalidate_callback_count_ != 0)
+ result = false;
+ return result;
+}
+
+bool CloudPolicyInvalidatorTest::CheckInvalidateCalled(bool unknown_version) {
+ base::TimeDelta min_delay;
+ base::TimeDelta max_delay = base::TimeDelta::FromMilliseconds(
+ CloudPolicyInvalidator::kMaxFetchDelayMin);
+ if (unknown_version) {
+ base::TimeDelta additional_delay = base::TimeDelta::FromMinutes(
+ CloudPolicyInvalidator::kMissingPayloadDelay);
+ min_delay += additional_delay;
+ max_delay += additional_delay;
+ }
+
+ if (task_runner_->GetPendingTasks().empty())
+ return false;
+ base::TimeDelta actual_delay = task_runner_->GetPendingTasks().back().delay;
+ EXPECT_GE(actual_delay, min_delay);
+ EXPECT_LE(actual_delay, max_delay);
+
+ bool result = true;
+ if (invalidate_callback_count_ != 0)
+ result = false;
+ task_runner_->RunUntilIdle();
+ if (invalidate_callback_count_ != 1)
+ result = false;
+ invalidate_callback_count_ = 0;
+ return result;
+}
+
+bool CloudPolicyInvalidatorTest::CheckStateChangedNotCalled() {
+ return state_change_enabled_callback_count_ == 0 &&
+ state_change_disabled_callback_count_ == 0;
+}
+
+bool CloudPolicyInvalidatorTest::CheckStateChangedCalled(
+ bool invalidations_enabled) {
+ int expected_enabled_count_ = invalidations_enabled ? 1 : 0;
+ int expected_disabled_count_ = invalidations_enabled ? 0 : 1;
+ bool result = state_change_enabled_callback_count_ == expected_enabled_count_
+ && state_change_disabled_callback_count_ == expected_disabled_count_;
+ state_change_enabled_callback_count_ = 0;
+ state_change_disabled_callback_count_ = 0;
+ return result;
+}
+
+bool CloudPolicyInvalidatorTest::IsInvalidationAcknowledged(
+ const syncer::AckHandle& ack_handle) {
+ return invalidation_service_.IsInvalidationAcknowledged(ack_handle);
+}
+
+base::HistogramBase::Count CloudPolicyInvalidatorTest::GetCount(
+ MetricPolicyRefresh metric) {
+ return GetHistogramSamples(kMetricPolicyRefresh)->GetCount(metric) -
+ refresh_samples_->GetCount(metric);
+}
+
+base::HistogramBase::Count CloudPolicyInvalidatorTest::GetInvalidationCount(
+ bool with_payload) {
+ int metric = with_payload ? 1 : 0;
+ return GetHistogramSamples(kMetricPolicyInvalidations)->GetCount(metric) -
+ invalidations_samples_->GetCount(metric);
+}
+
+void CloudPolicyInvalidatorTest::SetInvalidationInfo(
+ int64 version,
+ const std::string& payload) {
+ invalidation_version_ = version;
+ invalidation_payload_ = payload;
+}
+
+void CloudPolicyInvalidatorTest::InvalidatePolicy() {
+ ++invalidate_callback_count_;
+}
+
+void CloudPolicyInvalidatorTest::OnInvalidatorStateChanged(
+ bool invalidations_enabled) {
+ if (invalidator_.get())
+ EXPECT_EQ(invalidations_enabled, invalidator_->invalidations_enabled());
+ if (invalidations_enabled)
+ ++state_change_enabled_callback_count_;
+ else
+ ++state_change_disabled_callback_count_;
+}
+
+const invalidation::ObjectId& CloudPolicyInvalidatorTest::GetPolicyObjectId(
+ PolicyObject object) const {
+ EXPECT_TRUE(object == POLICY_OBJECT_A || object == POLICY_OBJECT_B);
+ return object == POLICY_OBJECT_A ? object_id_a_ : object_id_b_;
+}
+
+scoped_ptr<base::HistogramSamples>
+ CloudPolicyInvalidatorTest::GetHistogramSamples(
+ const std::string& name) const {
+ base::HistogramBase* histogram =
+ base::StatisticsRecorder::FindHistogram(name);
+ if (!histogram)
+ return scoped_ptr<base::HistogramSamples>(new base::SampleMap());
+ return histogram->SnapshotSamples();
+}
+
+TEST_F(CloudPolicyInvalidatorTest, Uninitialized) {
+ // No invalidations should be processed if the invalidator is not intialized.
+ StartInvalidator(false /* initialize */);
+ StorePolicy(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+}
+
+TEST_F(CloudPolicyInvalidatorTest, RegisterOnStoreLoaded) {
+ // No registration when store is not loaded.
+ StartInvalidator();
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+ FireInvalidation(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+
+ // No registration when store is loaded with no invalidation object id.
+ StorePolicy(POLICY_OBJECT_NONE);
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+ FireInvalidation(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+
+ // Check registration when store is loaded for object A.
+ StorePolicy(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidateCalled());
+ FireInvalidation(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+}
+
+TEST_F(CloudPolicyInvalidatorTest, ChangeRegistration) {
+ // Register for object A.
+ StartInvalidator();
+ StorePolicy(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidateCalled());
+ FireInvalidation(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+ syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A);
+
+ // Check re-registration for object B. Make sure the pending invalidation for
+ // object A is acknowledged without making the callback.
+ StorePolicy(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack));
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+
+ // Make sure future invalidations for object A are ignored and for object B
+ // are processed.
+ FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+ FireInvalidation(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckInvalidateCalled());
+}
+
+TEST_F(CloudPolicyInvalidatorTest, UnregisterOnStoreLoaded) {
+ // Register for object A.
+ StartInvalidator();
+ StorePolicy(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidateCalled());
+
+ // Check unregistration when store is loaded with no invalidation object id.
+ syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_FALSE(IsInvalidationAcknowledged(ack));
+ StorePolicy(POLICY_OBJECT_NONE);
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack));
+ EXPECT_TRUE(CheckStateChangedCalled(false));
+ FireInvalidation(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+
+ // Check re-registration for object B.
+ StorePolicy(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ FireInvalidation(POLICY_OBJECT_B);
+ EXPECT_TRUE(CheckInvalidateCalled());
+}
+
+TEST_F(CloudPolicyInvalidatorTest, HandleInvalidation) {
+ // Register and fire invalidation
+ StorePolicy(POLICY_OBJECT_A);
+ StartInvalidator();
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A, 12, "test_payload");
+
+ // Make sure client info is set as soon as the invalidation is received.
+ EXPECT_TRUE(CheckInvalidationInfo(12, "test_payload"));
+ EXPECT_TRUE(CheckInvalidateCalled(false /* unknown_version */));
+
+ // Make sure invalidation is not acknowledged until the store is loaded.
+ EXPECT_FALSE(IsInvalidationAcknowledged(ack));
+ EXPECT_TRUE(CheckInvalidationInfo(12, "test_payload"));
+ StorePolicy(POLICY_OBJECT_A, 12);
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack));
+ EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
+}
+
+TEST_F(CloudPolicyInvalidatorTest, HandleInvalidationWithUnknownVersion) {
+ // Register and fire invalidation with unknown version.
+ StorePolicy(POLICY_OBJECT_A);
+ StartInvalidator();
+ syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A);
+
+ // Make sure client info is not set until after the invalidation callback is
+ // made.
+ EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
+ EXPECT_TRUE(CheckInvalidateCalled());
+ EXPECT_TRUE(CheckInvalidationInfo(-1, std::string()));
+
+ // Make sure invalidation is not acknowledged until the store is loaded.
+ EXPECT_FALSE(IsInvalidationAcknowledged(ack));
+ StorePolicy(POLICY_OBJECT_A, -1);
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack));
+ EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
+}
+
+TEST_F(CloudPolicyInvalidatorTest, HandleMultipleInvalidations) {
+ // Generate multiple invalidations.
+ StorePolicy(POLICY_OBJECT_A);
+ StartInvalidator();
+ syncer::AckHandle ack1 = FireInvalidation(POLICY_OBJECT_A, 1, "test1");
+ EXPECT_TRUE(CheckInvalidationInfo(1, "test1"));
+ syncer::AckHandle ack2 = FireInvalidation(POLICY_OBJECT_A, 2, "test2");
+ EXPECT_TRUE(CheckInvalidationInfo(2, "test2"));
+ syncer::AckHandle ack3= FireInvalidation(POLICY_OBJECT_A, 3, "test3");
+ EXPECT_TRUE(CheckInvalidationInfo(3, "test3"));
+
+ // Make sure the replaced invalidations are acknowledged.
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack1));
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack2));
+
+ // Make sure the invalidate callback is called once.
+ EXPECT_TRUE(CheckInvalidateCalled(false /* unknown_version */));
+
+ // Make sure that the last invalidation is only acknowledged after the store
+ // is loaded with the latest version.
+ StorePolicy(POLICY_OBJECT_A, 1);
+ EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
+ StorePolicy(POLICY_OBJECT_A, 2);
+ EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
+ StorePolicy(POLICY_OBJECT_A, 3);
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack3));
+}
+
+TEST_F(CloudPolicyInvalidatorTest,
+ HandleMultipleInvalidationsWithUnknownVersion) {
+ // Validate that multiple invalidations with unknown version each generate
+ // unique invalidation version numbers.
+ StorePolicy(POLICY_OBJECT_A);
+ StartInvalidator();
+ syncer::AckHandle ack1 = FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
+ EXPECT_TRUE(CheckInvalidateCalled());
+ EXPECT_TRUE(CheckInvalidationInfo(-1, std::string()));
+ syncer::AckHandle ack2 = FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
+ EXPECT_TRUE(CheckInvalidateCalled());
+ EXPECT_TRUE(CheckInvalidationInfo(-2, std::string()));
+ syncer::AckHandle ack3 = FireInvalidation(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckInvalidationInfo(0, std::string()));
+ EXPECT_TRUE(CheckInvalidateCalled());
+ EXPECT_TRUE(CheckInvalidationInfo(-3, std::string()));
+
+ // Make sure the replaced invalidations are acknowledged.
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack1));
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack2));
+
+ // Make sure that the last invalidation is only acknowledged after the store
+ // is loaded with the last unknown version.
+ StorePolicy(POLICY_OBJECT_A, -1);
+ EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
+ StorePolicy(POLICY_OBJECT_A, -2);
+ EXPECT_FALSE(IsInvalidationAcknowledged(ack3));
+ StorePolicy(POLICY_OBJECT_A, -3);
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack3));
+}
+
+TEST_F(CloudPolicyInvalidatorTest, AcknowledgeBeforeInvalidateCallback) {
+ // Generate an invalidation.
+ StorePolicy(POLICY_OBJECT_A);
+ StartInvalidator();
+ syncer::AckHandle ack = FireInvalidation(POLICY_OBJECT_A, 3, "test");
+
+ // Ensure that the invalidate callback is not made and the invalidation is
+ // acknowledged if the store is loaded with the latest version before the
+ // callback is invoked.
+ StorePolicy(POLICY_OBJECT_A, 3);
+ EXPECT_TRUE(IsInvalidationAcknowledged(ack));
+ EXPECT_TRUE(CheckInvalidateNotCalled());
+}
+
+TEST_F(CloudPolicyInvalidatorTest, StateChanged) {
+ // Before registration, changes to the invalidation service state should not
+ // generate change state notifications.
+ StartInvalidator();
+ DisableInvalidationService();
+ EnableInvalidationService();
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+
+ // After registration, changes to the invalidation service state should
+ // generate notifications.
+ StorePolicy(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ DisableInvalidationService();
+ EXPECT_TRUE(CheckStateChangedCalled(false));
+ DisableInvalidationService();
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+ EnableInvalidationService();
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ EnableInvalidationService();
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+
+ // When the invalidation service is enabled, changes to the registration
+ // state should generate notifications.
+ StorePolicy(POLICY_OBJECT_NONE);
+ EXPECT_TRUE(CheckStateChangedCalled(false));
+ StorePolicy(POLICY_OBJECT_NONE);
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+ StorePolicy(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckStateChangedCalled(true));
+ StorePolicy(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+
+ // When the invalidation service is disabled, changes to the registration
+ // state should not generate notifications.
+ DisableInvalidationService();
+ EXPECT_TRUE(CheckStateChangedCalled(false));
+ StorePolicy(POLICY_OBJECT_NONE);
+ StorePolicy(POLICY_OBJECT_A);
+ EXPECT_TRUE(CheckStateChangedNotCalled());
+}
+
+TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsUnregistered) {
+ // Store loads occurring before invalidation registration are not counted.
+ StartInvalidator();
+ StorePolicy(POLICY_OBJECT_NONE, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_NONE, 0, true /* policy_changed */);
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
+}
+
+TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsNoInvalidations) {
+ // Store loads occurring while registered should be differentiated depending
+ // on whether the invalidation service was enabled or not.
+ StorePolicy(POLICY_OBJECT_A);
+ StartInvalidator();
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
+ DisableInvalidationService();
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
+ EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_CHANGED));
+ EXPECT_EQ(2, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
+ EXPECT_EQ(3, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
+}
+
+TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsStoreSameTimestamp) {
+ // Store loads with the same timestamp as the load which causes registration
+ // are not counted.
+ StartInvalidator();
+ StorePolicy(
+ POLICY_OBJECT_A, 0, false /* policy_changed */, 12 /* timestamp */);
+ StorePolicy(
+ POLICY_OBJECT_A, 0, false /* policy_changed */, 12 /* timestamp */);
+ StorePolicy(
+ POLICY_OBJECT_A, 0, true /* policy_changed */, 12 /* timestamp */);
+
+ // The next load with a different timestamp counts.
+ StorePolicy(
+ POLICY_OBJECT_A, 0, true /* policy_changed */, 13 /* timestamp */);
+
+ EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_CHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
+}
+
+TEST_F(CloudPolicyInvalidatorTest, RefreshMetricsInvalidation) {
+ // Store loads after an invalidation are counted as invalidated, even if
+ // the loads do not result in the invalidation being acknowledged.
+ StartInvalidator();
+ StorePolicy(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_A, 5, "test");
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 5, true /* policy_changed */);
+
+ // Store loads after the invalidation is complete are not counted as
+ // invalidated.
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */);
+ StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */);
+
+ EXPECT_EQ(3, GetCount(METRIC_POLICY_REFRESH_CHANGED));
+ EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS));
+ EXPECT_EQ(4, GetCount(METRIC_POLICY_REFRESH_UNCHANGED));
+ EXPECT_EQ(2, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED));
+ EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED));
+}
+
+TEST_F(CloudPolicyInvalidatorTest, InvalidationMetrics) {
+ // Generate a mix of versioned and unknown-version invalidations.
+ StorePolicy(POLICY_OBJECT_A);
+ StartInvalidator();
+ FireInvalidation(POLICY_OBJECT_B);
+ FireInvalidation(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_B, 1, "test");
+ FireInvalidation(POLICY_OBJECT_A, 1, "test");
+ FireInvalidation(POLICY_OBJECT_A, 2, "test");
+ FireInvalidation(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_A);
+ FireInvalidation(POLICY_OBJECT_A, 3, "test");
+ FireInvalidation(POLICY_OBJECT_A, 4, "test");
+
+ // Verify that received invalidations metrics are correct.
+ EXPECT_EQ(3, GetInvalidationCount(false /* with_payload */));
+ EXPECT_EQ(4, GetInvalidationCount(true /* with_payload */));
+}
+
+} // namespace policy

Powered by Google App Engine
This is Rietveld 408576698