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.
5 #include "components/policy/core/common/schema_registry.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "components/policy/core/common/policy_namespace.h"
9 #include "components/policy/core/common/schema.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 using ::testing::Mock
;
20 const char kTestSchema
[] =
22 " \"type\": \"object\","
24 " \"string\": { \"type\": \"string\" },"
25 " \"integer\": { \"type\": \"integer\" },"
26 " \"boolean\": { \"type\": \"boolean\" },"
27 " \"null\": { \"type\": \"null\" },"
28 " \"double\": { \"type\": \"number\" },"
30 " \"type\": \"array\","
31 " \"items\": { \"type\": \"string\" }"
34 " \"type\": \"object\","
36 " \"a\": { \"type\": \"string\" },"
37 " \"b\": { \"type\": \"integer\" }"
43 class MockSchemaRegistryObserver
: public SchemaRegistry::Observer
{
45 MockSchemaRegistryObserver() {}
46 virtual ~MockSchemaRegistryObserver() {}
48 MOCK_METHOD1(OnSchemaRegistryUpdated
, void(bool));
49 MOCK_METHOD0(OnSchemaRegistryReady
, void());
52 bool SchemaMapEquals(const scoped_refptr
<SchemaMap
>& schema_map1
,
53 const scoped_refptr
<SchemaMap
>& schema_map2
) {
54 PolicyNamespaceList added
;
55 PolicyNamespaceList removed
;
56 schema_map1
->GetChanges(schema_map2
, &removed
, &added
);
57 return added
.empty() && removed
.empty();
62 TEST(SchemaRegistryTest
, Notifications
) {
64 Schema schema
= Schema::Parse(kTestSchema
, &error
);
65 ASSERT_TRUE(schema
.valid()) << error
;
67 MockSchemaRegistryObserver observer
;
68 SchemaRegistry registry
;
69 registry
.AddObserver(&observer
);
71 ASSERT_TRUE(registry
.schema_map().get());
72 EXPECT_FALSE(registry
.schema_map()->GetSchema(
73 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc")));
75 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
76 registry
.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"),
78 Mock::VerifyAndClearExpectations(&observer
);
80 // Re-register also triggers notifications, because the Schema might have
82 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
83 registry
.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"),
85 Mock::VerifyAndClearExpectations(&observer
);
87 EXPECT_TRUE(registry
.schema_map()->GetSchema(
88 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc")));
90 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(false));
91 registry
.UnregisterComponent(
92 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"));
93 Mock::VerifyAndClearExpectations(&observer
);
95 EXPECT_FALSE(registry
.schema_map()->GetSchema(
96 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc")));
98 // Registering multiple components at once issues only one notification.
99 ComponentMap components
;
100 components
["abc"] = schema
;
101 components
["def"] = schema
;
102 components
["xyz"] = schema
;
103 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
104 registry
.RegisterComponents(POLICY_DOMAIN_EXTENSIONS
, components
);
105 Mock::VerifyAndClearExpectations(&observer
);
107 registry
.RemoveObserver(&observer
);
110 TEST(SchemaRegistryTest
, IsReady
) {
111 SchemaRegistry registry
;
112 MockSchemaRegistryObserver observer
;
113 registry
.AddObserver(&observer
);
115 EXPECT_FALSE(registry
.IsReady());
116 #if defined(ENABLE_EXTENSIONS)
117 EXPECT_CALL(observer
, OnSchemaRegistryReady()).Times(0);
118 registry
.SetReady(POLICY_DOMAIN_EXTENSIONS
);
119 Mock::VerifyAndClearExpectations(&observer
);
120 EXPECT_FALSE(registry
.IsReady());
122 EXPECT_CALL(observer
, OnSchemaRegistryReady());
123 registry
.SetReady(POLICY_DOMAIN_CHROME
);
124 Mock::VerifyAndClearExpectations(&observer
);
125 EXPECT_TRUE(registry
.IsReady());
126 EXPECT_CALL(observer
, OnSchemaRegistryReady()).Times(0);
127 registry
.SetReady(POLICY_DOMAIN_CHROME
);
128 Mock::VerifyAndClearExpectations(&observer
);
129 EXPECT_TRUE(registry
.IsReady());
131 CombinedSchemaRegistry combined
;
132 EXPECT_TRUE(combined
.IsReady());
134 registry
.RemoveObserver(&observer
);
137 TEST(SchemaRegistryTest
, Combined
) {
139 Schema schema
= Schema::Parse(kTestSchema
, &error
);
140 ASSERT_TRUE(schema
.valid()) << error
;
142 MockSchemaRegistryObserver observer
;
143 scoped_ptr
<SchemaRegistry
> registry1(new SchemaRegistry
);
144 scoped_ptr
<SchemaRegistry
> registry2(new SchemaRegistry
);
145 CombinedSchemaRegistry combined
;
146 combined
.AddObserver(&observer
);
148 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(_
)).Times(0);
149 registry1
->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"),
151 Mock::VerifyAndClearExpectations(&observer
);
153 // Starting to track a registry issues notifications when it comes with new
155 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
156 combined
.Track(registry1
.get());
157 Mock::VerifyAndClearExpectations(&observer
);
159 // Adding a new empty registry does not trigger notifications.
160 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(_
)).Times(0);
161 combined
.Track(registry2
.get());
162 Mock::VerifyAndClearExpectations(&observer
);
164 // Adding the same component to the combined registry itself triggers
166 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
167 combined
.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"),
169 Mock::VerifyAndClearExpectations(&observer
);
171 // Adding components to the sub-registries triggers notifications.
172 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
173 registry2
->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "def"),
175 Mock::VerifyAndClearExpectations(&observer
);
177 // If the same component is published in 2 sub-registries then the combined
178 // registry publishes one of them.
179 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
180 registry1
->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "def"),
182 Mock::VerifyAndClearExpectations(&observer
);
184 ASSERT_EQ(1u, combined
.schema_map()->GetDomains().size());
185 ASSERT_TRUE(combined
.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS
));
188 combined
.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS
)->size());
189 EXPECT_TRUE(combined
.schema_map()->GetSchema(
190 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc")));
191 EXPECT_TRUE(combined
.schema_map()->GetSchema(
192 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "def")));
193 EXPECT_FALSE(combined
.schema_map()->GetSchema(
194 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "xyz")));
196 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(false));
197 registry1
->UnregisterComponent(
198 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"));
199 Mock::VerifyAndClearExpectations(&observer
);
200 // Still registered at the combined registry.
201 EXPECT_TRUE(combined
.schema_map()->GetSchema(
202 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc")));
204 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(false));
205 combined
.UnregisterComponent(
206 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"));
207 Mock::VerifyAndClearExpectations(&observer
);
209 EXPECT_FALSE(combined
.schema_map()->GetSchema(
210 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc")));
212 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(false));
213 registry1
->UnregisterComponent(
214 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "def"));
215 Mock::VerifyAndClearExpectations(&observer
);
216 // Still registered at registry2.
217 EXPECT_TRUE(combined
.schema_map()->GetSchema(
218 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "def")));
220 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(false));
221 registry2
->UnregisterComponent(
222 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "def"));
223 Mock::VerifyAndClearExpectations(&observer
);
225 EXPECT_FALSE(combined
.schema_map()->GetSchema(
226 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "def")));
228 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true)).Times(2);
229 registry1
->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME
, ""),
231 registry2
->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "hij"),
233 Mock::VerifyAndClearExpectations(&observer
);
235 // Untracking |registry1| doesn't trigger an update notification, because it
236 // doesn't contain any components.
237 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(_
)).Times(0);
239 Mock::VerifyAndClearExpectations(&observer
);
241 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(false));
243 Mock::VerifyAndClearExpectations(&observer
);
245 combined
.RemoveObserver(&observer
);
248 TEST(SchemaRegistryTest
, ForwardingSchemaRegistry
) {
249 scoped_ptr
<SchemaRegistry
> registry(new SchemaRegistry
);
250 ForwardingSchemaRegistry
forwarding(registry
.get());
251 MockSchemaRegistryObserver observer
;
252 forwarding
.AddObserver(&observer
);
254 EXPECT_FALSE(registry
->IsReady());
255 EXPECT_FALSE(forwarding
.IsReady());
256 // They always have the same SchemaMap.
257 EXPECT_TRUE(SchemaMapEquals(registry
->schema_map(), forwarding
.schema_map()));
259 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(true));
260 registry
->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"),
262 Mock::VerifyAndClearExpectations(&observer
);
263 EXPECT_TRUE(SchemaMapEquals(registry
->schema_map(), forwarding
.schema_map()));
265 EXPECT_CALL(observer
, OnSchemaRegistryUpdated(false));
266 registry
->UnregisterComponent(
267 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS
, "abc"));
268 Mock::VerifyAndClearExpectations(&observer
);
269 EXPECT_TRUE(SchemaMapEquals(registry
->schema_map(), forwarding
.schema_map()));
271 // No notifications expected for these calls.
272 EXPECT_FALSE(registry
->IsReady());
273 EXPECT_FALSE(forwarding
.IsReady());
275 registry
->SetReady(POLICY_DOMAIN_EXTENSIONS
);
276 EXPECT_FALSE(registry
->IsReady());
277 EXPECT_FALSE(forwarding
.IsReady());
279 registry
->SetReady(POLICY_DOMAIN_CHROME
);
280 EXPECT_TRUE(registry
->IsReady());
281 // The ForwardingSchemaRegistry becomes ready independently of the wrapped
283 EXPECT_FALSE(forwarding
.IsReady());
285 EXPECT_TRUE(SchemaMapEquals(registry
->schema_map(), forwarding
.schema_map()));
286 Mock::VerifyAndClearExpectations(&observer
);
288 forwarding
.SetReady(POLICY_DOMAIN_EXTENSIONS
);
289 EXPECT_FALSE(forwarding
.IsReady());
290 Mock::VerifyAndClearExpectations(&observer
);
292 EXPECT_CALL(observer
, OnSchemaRegistryReady());
293 forwarding
.SetReady(POLICY_DOMAIN_CHROME
);
294 EXPECT_TRUE(forwarding
.IsReady());
295 Mock::VerifyAndClearExpectations(&observer
);
297 // Keep the same SchemaMap when the original registry is gone.
298 // No notifications are expected in this case either.
299 scoped_refptr
<SchemaMap
> schema_map
= registry
->schema_map();
301 EXPECT_TRUE(SchemaMapEquals(schema_map
, forwarding
.schema_map()));
302 Mock::VerifyAndClearExpectations(&observer
);
304 forwarding
.RemoveObserver(&observer
);
307 } // namespace policy