Index: tools/json_schema_compiler/test/features_generation_unittest.cc |
diff --git a/tools/json_schema_compiler/test/features_generation_unittest.cc b/tools/json_schema_compiler/test/features_generation_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7a175a05dc97b5cd394067b91760e9c37a333065 |
--- /dev/null |
+++ b/tools/json_schema_compiler/test/features_generation_unittest.cc |
@@ -0,0 +1,226 @@ |
+// Copyright 2016 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 "extensions/common/features/api_feature.h" |
+#include "extensions/common/features/complex_feature.h" |
+#include "extensions/common/features/feature.h" |
+#include "extensions/common/features/simple_feature.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "tools/json_schema_compiler/test/features_test.h" |
+ |
+namespace extensions { |
+ |
+namespace { |
+ |
+template <typename T> |
+void ExpectVectorsEqual(std::vector<T> expected, |
+ std::vector<T> actual, |
+ const std::string& name) { |
+ std::sort(expected.begin(), expected.end()); |
+ std::sort(actual.begin(), actual.end()); |
+ EXPECT_EQ(expected, actual) << name; |
+} |
+ |
+SimpleFeature::Location kDefaultLocation = SimpleFeature::UNSPECIFIED_LOCATION; |
+const int kDefaultMinVersion = 0; |
+const int kDefaultMaxVersion = 0; |
+const bool kDefaultAutoGrant = true; |
+const bool kDefaultInternal = false; |
+ |
+} // namespace |
+ |
+// A utility object for comparing a feature with its expected value. |
+struct FeatureComparator { |
+ public: |
+ FeatureComparator(const std::string& name); |
+ ~FeatureComparator(); |
+ |
+ void CompareFeature(SimpleFeature* feature); |
+ |
+ std::string name; |
+ std::vector<std::string> blacklist; |
+ std::vector<std::string> whitelist; |
+ std::vector<std::string> dependencies; |
+ std::vector<Manifest::Type> extension_types; |
+ std::vector<Feature::Context> contexts; |
+ std::vector<Feature::Platform> platforms; |
+ URLPatternSet matches; |
+ SimpleFeature::Location location; |
+ int min_manifest_version; |
+ int max_manifest_version; |
+ bool component_extensions_auto_granted; |
+ std::string command_line_switch; |
+ std::unique_ptr<version_info::Channel> channel; |
+ bool internal; |
+}; |
+ |
+FeatureComparator::FeatureComparator(const std::string& name) |
+ : name(name), |
+ location(kDefaultLocation), |
+ min_manifest_version(kDefaultMinVersion), |
+ max_manifest_version(kDefaultMaxVersion), |
+ component_extensions_auto_granted(kDefaultAutoGrant), |
+ internal(kDefaultInternal) {} |
+ |
+FeatureComparator::~FeatureComparator() {} |
+ |
+void FeatureComparator::CompareFeature(SimpleFeature* feature) { |
+ ASSERT_TRUE(feature); |
+ EXPECT_EQ(name, feature->name()); |
+ ExpectVectorsEqual(blacklist, feature->blacklist(), name); |
+ ExpectVectorsEqual(whitelist, feature->whitelist(), name); |
+ ExpectVectorsEqual(dependencies, feature->dependencies(), name); |
+ ExpectVectorsEqual(extension_types, feature->extension_types(), name); |
+ ExpectVectorsEqual(contexts, feature->contexts(), name); |
+ ExpectVectorsEqual(platforms, feature->platforms(), name); |
+ EXPECT_EQ(matches, feature->matches()) << name; |
+ EXPECT_EQ(location, feature->location()) << name; |
+ EXPECT_EQ(min_manifest_version, feature->min_manifest_version()) << name; |
+ EXPECT_EQ(max_manifest_version, feature->max_manifest_version()) << name; |
+ EXPECT_EQ(component_extensions_auto_granted, |
+ feature->component_extensions_auto_granted()) |
+ << name; |
+ EXPECT_EQ(command_line_switch, feature->command_line_switch()) << name; |
+ ASSERT_EQ(channel.get() != nullptr, feature->has_channel()) << name; |
+ if (channel) |
+ EXPECT_EQ(*channel, feature->channel()) << name; |
+ EXPECT_EQ(internal, feature->IsInternal()) << name; |
+} |
+ |
+TEST(FeaturesGenerationTest, FeaturesTest) { |
+ TestAPIFeatureProvider provider; |
+ |
+ auto GetAPIFeature = [&provider](const std::string& name) { |
+ Feature* feature = provider.GetFeature(name); |
+ // Shame we can't test this more safely, but if our feature is declared as |
+ // the wrong class, things should blow up in a spectacular fashion. |
+ return static_cast<APIFeature*>(feature); |
+ }; |
+ |
+ // Check some simple features for accuracy. |
+ { |
+ APIFeature* feature = GetAPIFeature("alpha"); |
+ FeatureComparator comparator("alpha"); |
+ comparator.dependencies = {"permission:alpha"}; |
+ comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; |
+ comparator.channel.reset( |
+ new version_info::Channel(version_info::Channel::STABLE)); |
+ comparator.CompareFeature(feature); |
+ } |
+ { |
+ APIFeature* feature = GetAPIFeature("beta"); |
+ FeatureComparator comparator("beta"); |
+ comparator.extension_types = {Manifest::TYPE_EXTENSION, |
+ Manifest::TYPE_PLATFORM_APP}; |
+ comparator.whitelist = {"aaa", "bbb"}; |
+ comparator.blacklist = {"zzz", "yyy"}; |
+ comparator.component_extensions_auto_granted = false; |
+ comparator.CompareFeature(feature); |
+ } |
+ { |
+ APIFeature* feature = GetAPIFeature("gamma"); |
+ FeatureComparator comparator("gamma"); |
+ comparator.channel.reset( |
+ new version_info::Channel(version_info::Channel::BETA)); |
+ comparator.platforms = {Feature::WIN_PLATFORM, Feature::MACOSX_PLATFORM}; |
+ comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; |
+ comparator.extension_types = {Manifest::TYPE_EXTENSION}; |
+ comparator.internal = true; |
+ comparator.CompareFeature(feature); |
+ |
+ // A child feature should inherit all fields from its parent, except in the |
+ // case that it specifies its own value. Thus, we reuse |comparator|. |
+ feature = GetAPIFeature("gamma.child"); |
+ comparator.name = "gamma.child"; |
+ comparator.dependencies = {"permission:gamma.child"}; |
+ comparator.whitelist = {"ccc"}; |
+ comparator.platforms = {Feature::LINUX_PLATFORM}; |
+ comparator.CompareFeature(feature); |
+ } |
+ { |
+ // Features that specify 'noparent' should not inherit features from any |
+ // other feature. |
+ APIFeature* feature = GetAPIFeature("gamma.unparented"); |
+ FeatureComparator comparator("gamma.unparented"); |
+ comparator.blacklist = {"ddd"}; |
+ comparator.contexts = {Feature::UNBLESSED_EXTENSION_CONTEXT}; |
+ comparator.CompareFeature(feature); |
+ } |
+ { |
+ APIFeature* feature = GetAPIFeature("delta"); |
+ FeatureComparator comparator("delta"); |
+ comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT, |
+ Feature::WEBUI_CONTEXT}; |
+ comparator.matches.AddPattern( |
+ URLPattern(URLPattern::SCHEME_ALL, "*://example.com/*")); |
+ comparator.CompareFeature(feature); |
+ } |
+ { |
+ // Omega is imported from a second .json file. |
+ APIFeature* feature = GetAPIFeature("omega"); |
+ FeatureComparator comparator("omega"); |
+ comparator.contexts = {Feature::WEB_PAGE_CONTEXT}; |
+ comparator.min_manifest_version = 2; |
+ comparator.CompareFeature(feature); |
+ } |
+ { |
+ // Features specifying 'nocompile' should not be generated at all. |
+ APIFeature* feature = GetAPIFeature("uncompiled"); |
+ EXPECT_FALSE(feature); |
+ } |
+ |
+ // Test complex features. |
+ { |
+ ComplexFeature* feature = |
+ static_cast<ComplexFeature*>(provider.GetFeature("complex")); |
+ ASSERT_TRUE(feature); |
+ EXPECT_EQ(2u, feature->features_.size()); |
+ // Find the default parent. This is a little tedious because it might not |
+ // be guaranteed that the default_parent is in a specific index, but it |
+ // specifies channel as 'stable'. |
+ SimpleFeature* default_parent = nullptr; |
+ SimpleFeature* other_parent = nullptr; |
+ { |
+ SimpleFeature* parent1 = |
+ static_cast<SimpleFeature*>(feature->features_[0].get()); |
+ SimpleFeature* parent2 = |
+ static_cast<SimpleFeature*>(feature->features_[1].get()); |
+ if (parent1->channel() == version_info::Channel::STABLE) { |
+ default_parent = parent1; |
+ other_parent = parent2; |
+ } else { |
+ other_parent = parent1; |
+ default_parent = parent2; |
+ } |
+ } |
+ { |
+ // Check the default parent. |
+ FeatureComparator comparator("complex"); |
+ comparator.channel.reset( |
+ new version_info::Channel(version_info::Channel::STABLE)); |
+ comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; |
+ comparator.extension_types = {Manifest::TYPE_EXTENSION}; |
+ comparator.CompareFeature(default_parent); |
+ // Check the child of the complex feature. It should inherit its |
+ // properties from the default parent. |
+ APIFeature* child_feature = GetAPIFeature("complex.child"); |
+ comparator.name = "complex.child"; |
+ comparator.platforms = {Feature::WIN_PLATFORM}; |
+ comparator.dependencies = {"permission:complex.child"}; |
+ comparator.CompareFeature(child_feature); |
+ } |
+ { |
+ // Finally, check the branch of the complex feature. |
+ FeatureComparator comparator("complex"); |
+ comparator.channel.reset( |
+ new version_info::Channel(version_info::Channel::BETA)); |
+ comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; |
+ comparator.extension_types = {Manifest::TYPE_EXTENSION}; |
+ comparator.whitelist = {"aaa"}; |
+ comparator.CompareFeature(other_parent); |
+ } |
+ } |
+} |
+ |
+} // namespace extensions |