Home | History | Annotate | Download | only in common
      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.
      4 
      5 #include "components/policy/core/common/schema_registry.h"
      6 
      7 #include "components/policy/core/common/policy_namespace.h"
      8 #include "components/policy/core/common/schema.h"
      9 #include "testing/gmock/include/gmock/gmock.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 using ::testing::Mock;
     13 using ::testing::_;
     14 
     15 namespace policy {
     16 
     17 namespace {
     18 
     19 const char kTestSchema[] =
     20     "{"
     21     "  \"type\": \"object\","
     22     "  \"properties\": {"
     23     "    \"string\": { \"type\": \"string\" },"
     24     "    \"integer\": { \"type\": \"integer\" },"
     25     "    \"boolean\": { \"type\": \"boolean\" },"
     26     "    \"null\": { \"type\": \"null\" },"
     27     "    \"double\": { \"type\": \"number\" },"
     28     "    \"list\": {"
     29     "      \"type\": \"array\","
     30     "      \"items\": { \"type\": \"string\" }"
     31     "    },"
     32     "    \"object\": {"
     33     "      \"type\": \"object\","
     34     "      \"properties\": {"
     35     "        \"a\": { \"type\": \"string\" },"
     36     "        \"b\": { \"type\": \"integer\" }"
     37     "      }"
     38     "    }"
     39     "  }"
     40     "}";
     41 
     42 class MockSchemaRegistryObserver : public SchemaRegistry::Observer {
     43  public:
     44   MockSchemaRegistryObserver() {}
     45   virtual ~MockSchemaRegistryObserver() {}
     46 
     47   MOCK_METHOD1(OnSchemaRegistryUpdated, void(bool));
     48   MOCK_METHOD0(OnSchemaRegistryReady, void());
     49 };
     50 
     51 }  // namespace
     52 
     53 TEST(SchemaRegistryTest, Notifications) {
     54   std::string error;
     55   Schema schema = Schema::Parse(kTestSchema, &error);
     56   ASSERT_TRUE(schema.valid()) << error;
     57 
     58   MockSchemaRegistryObserver observer;
     59   SchemaRegistry registry;
     60   EXPECT_FALSE(registry.HasObservers());
     61   registry.AddObserver(&observer);
     62   EXPECT_TRUE(registry.HasObservers());
     63 
     64   ASSERT_TRUE(registry.schema_map());
     65   EXPECT_FALSE(registry.schema_map()->GetSchema(
     66       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
     67 
     68   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
     69   registry.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
     70                              schema);
     71   Mock::VerifyAndClearExpectations(&observer);
     72 
     73   // Re-register also triggers notifications, because the Schema might have
     74   // changed.
     75   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
     76   registry.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
     77                              schema);
     78   Mock::VerifyAndClearExpectations(&observer);
     79 
     80   EXPECT_TRUE(registry.schema_map()->GetSchema(
     81       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
     82 
     83   EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
     84   registry.UnregisterComponent(
     85       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
     86   Mock::VerifyAndClearExpectations(&observer);
     87 
     88   EXPECT_FALSE(registry.schema_map()->GetSchema(
     89       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
     90 
     91   // Registering multiple components at once issues only one notification.
     92   ComponentMap components;
     93   components["abc"] = schema;
     94   components["def"] = schema;
     95   components["xyz"] = schema;
     96   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
     97   registry.RegisterComponents(POLICY_DOMAIN_EXTENSIONS, components);
     98   Mock::VerifyAndClearExpectations(&observer);
     99 
    100   registry.RemoveObserver(&observer);
    101   EXPECT_FALSE(registry.HasObservers());
    102 }
    103 
    104 TEST(SchemaRegistryTest, IsReady) {
    105   SchemaRegistry registry;
    106   MockSchemaRegistryObserver observer;
    107   registry.AddObserver(&observer);
    108 
    109   EXPECT_FALSE(registry.IsReady());
    110 #if defined(ENABLE_EXTENSIONS)
    111   EXPECT_CALL(observer, OnSchemaRegistryReady()).Times(0);
    112   registry.SetReady(POLICY_DOMAIN_EXTENSIONS);
    113   Mock::VerifyAndClearExpectations(&observer);
    114   EXPECT_FALSE(registry.IsReady());
    115 #endif
    116   EXPECT_CALL(observer, OnSchemaRegistryReady());
    117   registry.SetReady(POLICY_DOMAIN_CHROME);
    118   Mock::VerifyAndClearExpectations(&observer);
    119   EXPECT_TRUE(registry.IsReady());
    120   EXPECT_CALL(observer, OnSchemaRegistryReady()).Times(0);
    121   registry.SetReady(POLICY_DOMAIN_CHROME);
    122   Mock::VerifyAndClearExpectations(&observer);
    123   EXPECT_TRUE(registry.IsReady());
    124 
    125   CombinedSchemaRegistry combined;
    126   EXPECT_TRUE(combined.IsReady());
    127 
    128   registry.RemoveObserver(&observer);
    129 }
    130 
    131 TEST(SchemaRegistryTest, Combined) {
    132   std::string error;
    133   Schema schema = Schema::Parse(kTestSchema, &error);
    134   ASSERT_TRUE(schema.valid()) << error;
    135 
    136   MockSchemaRegistryObserver observer;
    137   SchemaRegistry registry1;
    138   SchemaRegistry registry2;
    139   CombinedSchemaRegistry combined;
    140   combined.AddObserver(&observer);
    141 
    142   EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
    143   registry1.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
    144                               schema);
    145   Mock::VerifyAndClearExpectations(&observer);
    146 
    147   // Starting to track a registry issues notifications when it comes with new
    148   // schemas.
    149   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
    150   combined.Track(&registry1);
    151   Mock::VerifyAndClearExpectations(&observer);
    152 
    153   // Adding a new empty registry does not trigger notifications.
    154   EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
    155   combined.Track(&registry2);
    156   Mock::VerifyAndClearExpectations(&observer);
    157 
    158   // Adding the same component to the combined registry itself triggers
    159   // notifications.
    160   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
    161   combined.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
    162                              schema);
    163   Mock::VerifyAndClearExpectations(&observer);
    164 
    165   // Adding components to the sub-registries triggers notifications.
    166   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
    167   registry2.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
    168                               schema);
    169   Mock::VerifyAndClearExpectations(&observer);
    170 
    171   // If the same component is published in 2 sub-registries then the combined
    172   // registry publishes one of them.
    173   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
    174   registry1.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
    175                               schema);
    176   Mock::VerifyAndClearExpectations(&observer);
    177 
    178   ASSERT_EQ(1u, combined.schema_map()->GetDomains().size());
    179   ASSERT_TRUE(combined.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS));
    180   ASSERT_EQ(
    181       2u,
    182       combined.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS)->size());
    183   EXPECT_TRUE(combined.schema_map()->GetSchema(
    184       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
    185   EXPECT_TRUE(combined.schema_map()->GetSchema(
    186       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
    187   EXPECT_FALSE(combined.schema_map()->GetSchema(
    188       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz")));
    189 
    190   EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
    191   registry1.UnregisterComponent(
    192       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
    193   Mock::VerifyAndClearExpectations(&observer);
    194   // Still registered at the combined registry.
    195   EXPECT_TRUE(combined.schema_map()->GetSchema(
    196       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
    197 
    198   EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
    199   combined.UnregisterComponent(
    200       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
    201   Mock::VerifyAndClearExpectations(&observer);
    202   // Now it's gone.
    203   EXPECT_FALSE(combined.schema_map()->GetSchema(
    204       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
    205 
    206   EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
    207   registry1.UnregisterComponent(
    208       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
    209   Mock::VerifyAndClearExpectations(&observer);
    210   // Still registered at registry2.
    211   EXPECT_TRUE(combined.schema_map()->GetSchema(
    212       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
    213 
    214   EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
    215   registry2.UnregisterComponent(
    216       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
    217   Mock::VerifyAndClearExpectations(&observer);
    218   // Now it's gone.
    219   EXPECT_FALSE(combined.schema_map()->GetSchema(
    220       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
    221 
    222   EXPECT_CALL(observer, OnSchemaRegistryUpdated(true)).Times(2);
    223   registry1.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
    224                               schema);
    225   registry2.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "hij"),
    226                               schema);
    227   Mock::VerifyAndClearExpectations(&observer);
    228 
    229   // Untracking |registry1| doesn't trigger an update nofitication, because it
    230   // doesn't contain any components.
    231   EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
    232   combined.Untrack(&registry1);
    233   Mock::VerifyAndClearExpectations(&observer);
    234 
    235   EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
    236   combined.Untrack(&registry2);
    237   Mock::VerifyAndClearExpectations(&observer);
    238 
    239   combined.RemoveObserver(&observer);
    240 }
    241 
    242 }  // namespace policy
    243