summaryrefslogtreecommitdiffstats
path: root/chromium/components/policy/core/common/async_policy_provider_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/policy/core/common/async_policy_provider_unittest.cc')
-rw-r--r--chromium/components/policy/core/common/async_policy_provider_unittest.cc229
1 files changed, 229 insertions, 0 deletions
diff --git a/chromium/components/policy/core/common/async_policy_provider_unittest.cc b/chromium/components/policy/core/common/async_policy_provider_unittest.cc
new file mode 100644
index 00000000000..64279bf968a
--- /dev/null
+++ b/chromium/components/policy/core/common/async_policy_provider_unittest.cc
@@ -0,0 +1,229 @@
+// Copyright 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 "components/policy/core/common/async_policy_provider.h"
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/values.h"
+#include "components/policy/core/common/async_policy_loader.h"
+#include "components/policy/core/common/external_data_fetcher.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/core/common/schema_registry.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Mock;
+using testing::Return;
+using testing::Sequence;
+
+namespace policy {
+
+namespace {
+
+// Helper to write a policy in |bundle| with less code.
+void SetPolicy(PolicyBundle* bundle,
+ const std::string& name,
+ const std::string& value) {
+ bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
+ .Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ POLICY_SOURCE_PLATFORM, base::Value(value), nullptr);
+}
+
+class MockPolicyLoader : public AsyncPolicyLoader {
+ public:
+ explicit MockPolicyLoader(
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+ MockPolicyLoader(const MockPolicyLoader&) = delete;
+ MockPolicyLoader& operator=(const MockPolicyLoader&) = delete;
+ ~MockPolicyLoader() override;
+
+ // Load() returns a std::unique_ptr<PolicyBundle> but it can't be mocked
+ // because std::unique_ptr is moveable but not copyable. This override
+ // forwards the call to MockLoad() which returns a PolicyBundle*, and returns
+ // a copy wrapped in a std::unique_ptr.
+ std::unique_ptr<PolicyBundle> Load() override;
+
+ MOCK_METHOD0(MockLoad, const PolicyBundle*());
+ MOCK_METHOD0(InitOnBackgroundThread, void());
+ MOCK_METHOD0(LastModificationTime, base::Time());
+};
+
+MockPolicyLoader::MockPolicyLoader(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : AsyncPolicyLoader(task_runner, /*periodic_updates=*/true) {}
+
+MockPolicyLoader::~MockPolicyLoader() {}
+
+std::unique_ptr<PolicyBundle> MockPolicyLoader::Load() {
+ std::unique_ptr<PolicyBundle> bundle;
+ const PolicyBundle* loaded = MockLoad();
+ if (loaded) {
+ bundle = std::make_unique<PolicyBundle>();
+ bundle->CopyFrom(*loaded);
+ }
+ return bundle;
+}
+
+} // namespace
+
+class AsyncPolicyProviderTest : public testing::Test {
+ public:
+ AsyncPolicyProviderTest(const AsyncPolicyProviderTest&) = delete;
+ AsyncPolicyProviderTest& operator=(const AsyncPolicyProviderTest&) = delete;
+
+ protected:
+ AsyncPolicyProviderTest();
+ ~AsyncPolicyProviderTest() override;
+
+ void SetUp() override;
+ void TearDown() override;
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ SchemaRegistry schema_registry_;
+ PolicyBundle initial_bundle_;
+ raw_ptr<MockPolicyLoader> loader_;
+ std::unique_ptr<AsyncPolicyProvider> provider_;
+};
+
+AsyncPolicyProviderTest::AsyncPolicyProviderTest() {}
+
+AsyncPolicyProviderTest::~AsyncPolicyProviderTest() {}
+
+void AsyncPolicyProviderTest::SetUp() {
+ SetPolicy(&initial_bundle_, "policy", "initial");
+ loader_ = new MockPolicyLoader(base::ThreadTaskRunnerHandle::Get());
+ EXPECT_CALL(*loader_, LastModificationTime())
+ .WillRepeatedly(Return(base::Time()));
+ EXPECT_CALL(*loader_, InitOnBackgroundThread()).Times(1);
+ EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&initial_bundle_));
+
+ provider_ = std::make_unique<AsyncPolicyProvider>(
+ &schema_registry_, std::unique_ptr<AsyncPolicyLoader>(loader_));
+ provider_->Init(&schema_registry_);
+ // Verify that the initial load is done synchronously:
+ EXPECT_TRUE(provider_->policies().Equals(initial_bundle_));
+
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(loader_);
+
+ EXPECT_CALL(*loader_, LastModificationTime())
+ .WillRepeatedly(Return(base::Time()));
+}
+
+void AsyncPolicyProviderTest::TearDown() {
+ if (provider_) {
+ provider_->Shutdown();
+ provider_.reset();
+ }
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AsyncPolicyProviderTest, RefreshPolicies) {
+ PolicyBundle refreshed_bundle;
+ SetPolicy(&refreshed_bundle, "policy", "refreshed");
+ EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&refreshed_bundle));
+
+ MockConfigurationPolicyObserver observer;
+ provider_->AddObserver(&observer);
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
+ provider_->RefreshPolicies();
+ base::RunLoop().RunUntilIdle();
+ // The refreshed policies are now provided.
+ EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
+ provider_->RemoveObserver(&observer);
+}
+
+TEST_F(AsyncPolicyProviderTest, RefreshPoliciesTwice) {
+ PolicyBundle refreshed_bundle;
+ SetPolicy(&refreshed_bundle, "policy", "refreshed");
+ EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&refreshed_bundle));
+
+ MockConfigurationPolicyObserver observer;
+ provider_->AddObserver(&observer);
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
+ provider_->RefreshPolicies();
+ // Doesn't refresh before going through the background thread.
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Doesn't refresh if another RefreshPolicies request is made.
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
+ provider_->RefreshPolicies();
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
+ base::RunLoop().RunUntilIdle();
+ // The refreshed policies are now provided.
+ EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
+ Mock::VerifyAndClearExpectations(&observer);
+ provider_->RemoveObserver(&observer);
+}
+
+TEST_F(AsyncPolicyProviderTest, RefreshPoliciesDuringReload) {
+ PolicyBundle reloaded_bundle;
+ SetPolicy(&reloaded_bundle, "policy", "reloaded");
+ PolicyBundle refreshed_bundle;
+ SetPolicy(&refreshed_bundle, "policy", "refreshed");
+
+ Sequence load_sequence;
+ // Reload.
+ EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence)
+ .WillOnce(Return(&reloaded_bundle));
+ // RefreshPolicies.
+ EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence)
+ .WillOnce(Return(&refreshed_bundle));
+
+ MockConfigurationPolicyObserver observer;
+ provider_->AddObserver(&observer);
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
+
+ // A Reload is triggered before RefreshPolicies, and it shouldn't trigger
+ // notifications.
+ loader_->Reload(true);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Doesn't refresh before going through the background thread.
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
+ provider_->RefreshPolicies();
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
+ base::RunLoop().RunUntilIdle();
+ // The refreshed policies are now provided, and the |reloaded_bundle| was
+ // dropped.
+ EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
+ Mock::VerifyAndClearExpectations(&observer);
+ provider_->RemoveObserver(&observer);
+}
+
+TEST_F(AsyncPolicyProviderTest, Shutdown) {
+ EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&initial_bundle_));
+
+ MockConfigurationPolicyObserver observer;
+ provider_->AddObserver(&observer);
+
+ // Though there is a pending Reload, the provider and the loader can be
+ // deleted at any time.
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
+ loader_->Reload(true);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
+ provider_->Shutdown();
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(&observer);
+
+ provider_->RemoveObserver(&observer);
+ provider_.reset();
+}
+
+} // namespace policy