summaryrefslogtreecommitdiff
path: root/components/policy/core/common/schema_registry_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/policy/core/common/schema_registry_unittest.cc')
-rw-r--r--components/policy/core/common/schema_registry_unittest.cc329
1 files changed, 329 insertions, 0 deletions
diff --git a/components/policy/core/common/schema_registry_unittest.cc b/components/policy/core/common/schema_registry_unittest.cc
new file mode 100644
index 0000000000..aea54d1cc3
--- /dev/null
+++ b/components/policy/core/common/schema_registry_unittest.cc
@@ -0,0 +1,329 @@
+// 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/schema_registry.h"
+
+#include <memory>
+
+#include "components/policy/core/common/policy_namespace.h"
+#include "components/policy/core/common/schema.h"
+#include "extensions/buildflags/buildflags.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Mock;
+using ::testing::_;
+
+namespace policy {
+
+namespace {
+
+const char kTestSchema[] =
+ "{"
+ " \"type\": \"object\","
+ " \"properties\": {"
+ " \"string\": { \"type\": \"string\" },"
+ " \"integer\": { \"type\": \"integer\" },"
+ " \"boolean\": { \"type\": \"boolean\" },"
+ " \"null\": { \"type\": \"null\" },"
+ " \"double\": { \"type\": \"number\" },"
+ " \"list\": {"
+ " \"type\": \"array\","
+ " \"items\": { \"type\": \"string\" }"
+ " },"
+ " \"object\": {"
+ " \"type\": \"object\","
+ " \"properties\": {"
+ " \"a\": { \"type\": \"string\" },"
+ " \"b\": { \"type\": \"integer\" }"
+ " }"
+ " }"
+ " }"
+ "}";
+
+class MockSchemaRegistryObserver : public SchemaRegistry::Observer {
+ public:
+ MockSchemaRegistryObserver() {}
+ ~MockSchemaRegistryObserver() override {}
+
+ MOCK_METHOD1(OnSchemaRegistryUpdated, void(bool));
+ MOCK_METHOD0(OnSchemaRegistryReady, void());
+};
+
+bool SchemaMapEquals(const scoped_refptr<SchemaMap>& schema_map1,
+ const scoped_refptr<SchemaMap>& schema_map2) {
+ PolicyNamespaceList added;
+ PolicyNamespaceList removed;
+ schema_map1->GetChanges(schema_map2, &removed, &added);
+ return added.empty() && removed.empty();
+}
+
+} // namespace
+
+TEST(SchemaRegistryTest, Notifications) {
+ std::string error;
+ Schema schema = Schema::Parse(kTestSchema, &error);
+ ASSERT_TRUE(schema.valid()) << error;
+
+ MockSchemaRegistryObserver observer;
+ SchemaRegistry registry;
+ registry.AddObserver(&observer);
+
+ ASSERT_TRUE(registry.schema_map().get());
+ EXPECT_FALSE(registry.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ registry.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
+ schema);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Re-register also triggers notifications, because the Schema might have
+ // changed.
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ registry.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
+ schema);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_TRUE(registry.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
+ registry.UnregisterComponent(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_FALSE(registry.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
+
+ // Registering multiple components at once issues only one notification.
+ ComponentMap components;
+ components["abc"] = schema;
+ components["def"] = schema;
+ components["xyz"] = schema;
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ registry.RegisterComponents(POLICY_DOMAIN_EXTENSIONS, components);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ registry.RemoveObserver(&observer);
+}
+
+TEST(SchemaRegistryTest, IsReady) {
+ SchemaRegistry registry;
+ MockSchemaRegistryObserver observer;
+ registry.AddObserver(&observer);
+
+ EXPECT_FALSE(registry.IsReady());
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+ EXPECT_CALL(observer, OnSchemaRegistryReady()).Times(0);
+ registry.SetExtensionsDomainsReady();
+ Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_FALSE(registry.IsReady());
+#endif
+ EXPECT_CALL(observer, OnSchemaRegistryReady());
+ registry.SetDomainReady(POLICY_DOMAIN_CHROME);
+ Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_TRUE(registry.IsReady());
+ EXPECT_CALL(observer, OnSchemaRegistryReady()).Times(0);
+ registry.SetDomainReady(POLICY_DOMAIN_CHROME);
+ Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_TRUE(registry.IsReady());
+
+ CombinedSchemaRegistry combined;
+ EXPECT_TRUE(combined.IsReady());
+
+ registry.RemoveObserver(&observer);
+}
+
+TEST(SchemaRegistryTest, Combined) {
+ std::string error;
+ Schema schema = Schema::Parse(kTestSchema, &error);
+ ASSERT_TRUE(schema.valid()) << error;
+
+ MockSchemaRegistryObserver observer;
+ std::unique_ptr<SchemaRegistry> registry1(new SchemaRegistry);
+ std::unique_ptr<SchemaRegistry> registry2(new SchemaRegistry);
+ CombinedSchemaRegistry combined;
+ combined.AddObserver(&observer);
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
+ registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
+ schema);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Starting to track a registry issues notifications when it comes with new
+ // schemas.
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ combined.Track(registry1.get());
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Adding a new empty registry does not trigger notifications.
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
+ combined.Track(registry2.get());
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Adding the same component to the combined registry itself triggers
+ // notifications.
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ combined.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
+ schema);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Adding components to the sub-registries triggers notifications.
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ registry2->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
+ schema);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // If the same component is published in 2 sub-registries then the combined
+ // registry publishes one of them.
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
+ schema);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ ASSERT_EQ(1u, combined.schema_map()->GetDomains().size());
+ ASSERT_TRUE(combined.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS));
+ ASSERT_EQ(
+ 2u,
+ combined.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS)->size());
+ EXPECT_TRUE(combined.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
+ EXPECT_TRUE(combined.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
+ EXPECT_FALSE(combined.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz")));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
+ registry1->UnregisterComponent(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
+ Mock::VerifyAndClearExpectations(&observer);
+ // Still registered at the combined registry.
+ EXPECT_TRUE(combined.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
+ combined.UnregisterComponent(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
+ Mock::VerifyAndClearExpectations(&observer);
+ // Now it's gone.
+ EXPECT_FALSE(combined.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
+ registry1->UnregisterComponent(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
+ Mock::VerifyAndClearExpectations(&observer);
+ // Still registered at registry2.
+ EXPECT_TRUE(combined.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
+ registry2->UnregisterComponent(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
+ Mock::VerifyAndClearExpectations(&observer);
+ // Now it's gone.
+ EXPECT_FALSE(combined.schema_map()->GetSchema(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true)).Times(2);
+ registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
+ schema);
+ registry2->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "hij"),
+ schema);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Untracking |registry1| doesn't trigger an update notification, because it
+ // doesn't contain any components.
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
+ registry1.reset();
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
+ registry2.reset();
+ Mock::VerifyAndClearExpectations(&observer);
+
+ combined.RemoveObserver(&observer);
+}
+
+TEST(SchemaRegistryTest, ForwardingSchemaRegistry) {
+ std::unique_ptr<SchemaRegistry> registry(new SchemaRegistry);
+ ForwardingSchemaRegistry forwarding(registry.get());
+ MockSchemaRegistryObserver observer;
+ forwarding.AddObserver(&observer);
+
+ EXPECT_FALSE(registry->IsReady());
+ EXPECT_FALSE(forwarding.IsReady());
+ // They always have the same SchemaMap.
+ EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
+ registry->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
+ Schema());
+ Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
+
+ EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
+ registry->UnregisterComponent(
+ PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
+ Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
+
+ // No notifications expected for these calls.
+ EXPECT_FALSE(registry->IsReady());
+ EXPECT_FALSE(forwarding.IsReady());
+
+ registry->SetExtensionsDomainsReady();
+ EXPECT_FALSE(registry->IsReady());
+ EXPECT_FALSE(forwarding.IsReady());
+
+ EXPECT_CALL(observer, OnSchemaRegistryReady());
+ registry->SetDomainReady(POLICY_DOMAIN_CHROME);
+ EXPECT_TRUE(registry->IsReady());
+ EXPECT_TRUE(forwarding.IsReady());
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ forwarding.SetExtensionsDomainsReady();
+ forwarding.SetDomainReady(POLICY_DOMAIN_CHROME);
+ EXPECT_TRUE(forwarding.IsReady());
+
+ // Keep the same SchemaMap when the original registry is gone.
+ // No notifications are expected in this case either.
+ scoped_refptr<SchemaMap> schema_map = registry->schema_map();
+ registry.reset();
+ EXPECT_TRUE(SchemaMapEquals(schema_map, forwarding.schema_map()));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ forwarding.RemoveObserver(&observer);
+}
+
+TEST(SchemaRegistryTest, ForwardingSchemaRegistryReadiness) {
+ std::unique_ptr<SchemaRegistry> registry(new SchemaRegistry);
+
+ ForwardingSchemaRegistry forwarding_1(registry.get());
+ EXPECT_FALSE(registry->IsReady());
+ EXPECT_FALSE(forwarding_1.IsReady());
+
+ // Once the wrapped registry gets ready, the forwarding schema registry
+ // becomes ready too.
+ registry->SetAllDomainsReady();
+ EXPECT_TRUE(registry->IsReady());
+ EXPECT_TRUE(forwarding_1.IsReady());
+
+ // The wrapped registry was ready at the time when the forwarding registry was
+ // constructed, so the forwarding registry is immediately ready too.
+ ForwardingSchemaRegistry forwarding_2(registry.get());
+ EXPECT_TRUE(forwarding_2.IsReady());
+
+ // Destruction of the wrapped registry doesn't change the readiness of the
+ // forwarding registry.
+ registry.reset();
+ EXPECT_TRUE(forwarding_1.IsReady());
+ EXPECT_TRUE(forwarding_2.IsReady());
+}
+
+} // namespace policy