| 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
|
|
|