summaryrefslogtreecommitdiffstats
path: root/components/url_matcher/url_matcher_factory_unittest.cc
diff options
context:
space:
mode:
authorjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-13 20:36:53 +0000
committerjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-13 20:36:53 +0000
commit716c016d95025a8f4d42baab6639b9dc90498f2d (patch)
tree9efb703e070ecbfb1b73bfac9b350a3b81af14f6 /components/url_matcher/url_matcher_factory_unittest.cc
parent32c90a98f03fa68da4ba3d97a8e56ca70e92a07d (diff)
downloadchromium_src-716c016d95025a8f4d42baab6639b9dc90498f2d.zip
chromium_src-716c016d95025a8f4d42baab6639b9dc90498f2d.tar.gz
chromium_src-716c016d95025a8f4d42baab6639b9dc90498f2d.tar.bz2
Move extensions/common/matcher into components/url_matcher.
This allows using that code in builds that don't include extensions without having to introduce layering exceptions. This is meant for inclusion on the iOS build. BUG=271392 TBR=brettw@chromium.org Review URL: https://codereview.chromium.org/113903002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240736 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/url_matcher/url_matcher_factory_unittest.cc')
-rw-r--r--components/url_matcher/url_matcher_factory_unittest.cc339
1 files changed, 339 insertions, 0 deletions
diff --git a/components/url_matcher/url_matcher_factory_unittest.cc b/components/url_matcher/url_matcher_factory_unittest.cc
new file mode 100644
index 0000000..9d6632e
--- /dev/null
+++ b/components/url_matcher/url_matcher_factory_unittest.cc
@@ -0,0 +1,339 @@
+// 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/url_matcher/url_matcher_factory.h"
+
+#include "base/basictypes.h"
+#include "base/format_macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "components/url_matcher/url_matcher_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace url_matcher {
+
+namespace keys = url_matcher_constants;
+
+TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) {
+ URLMatcher matcher;
+
+ std::string error;
+ scoped_refptr<URLMatcherConditionSet> result;
+
+ // Invalid key: {"invalid": "foobar"}
+ DictionaryValue invalid_condition;
+ invalid_condition.SetString("invalid", "foobar");
+
+ // Invalid value type: {"hostSuffix": []}
+ DictionaryValue invalid_condition2;
+ invalid_condition2.Set(keys::kHostSuffixKey, new ListValue);
+
+ // Invalid regex value: {"urlMatches": "*"}
+ DictionaryValue invalid_condition3;
+ invalid_condition3.SetString(keys::kURLMatchesKey, "*");
+
+ // Invalid regex value: {"originAndPathMatches": "*"}
+ DictionaryValue invalid_condition4;
+ invalid_condition4.SetString(keys::kOriginAndPathMatchesKey, "*");
+
+ // Valid values:
+ // {
+ // "port_range": [80, [1000, 1010]],
+ // "schemes": ["http"],
+ // "hostSuffix": "example.com"
+ // "hostPrefix": "www"
+ // }
+
+ // Port range: Allow 80;1000-1010.
+ ListValue* port_range = new ListValue();
+ port_range->Append(Value::CreateIntegerValue(1000));
+ port_range->Append(Value::CreateIntegerValue(1010));
+ ListValue* port_ranges = new ListValue();
+ port_ranges->Append(Value::CreateIntegerValue(80));
+ port_ranges->Append(port_range);
+
+ ListValue* scheme_list = new ListValue();
+ scheme_list->Append(Value::CreateStringValue("http"));
+
+ DictionaryValue valid_condition;
+ valid_condition.SetString(keys::kHostSuffixKey, "example.com");
+ valid_condition.SetString(keys::kHostPrefixKey, "www");
+ valid_condition.Set(keys::kPortsKey, port_ranges);
+ valid_condition.Set(keys::kSchemesKey, scheme_list);
+
+ // Test wrong condition name passed.
+ error.clear();
+ result = URLMatcherFactory::CreateFromURLFilterDictionary(
+ matcher.condition_factory(), &invalid_condition, 1, &error);
+ EXPECT_FALSE(error.empty());
+ EXPECT_FALSE(result.get());
+
+ // Test wrong datatype in hostSuffix.
+ error.clear();
+ result = URLMatcherFactory::CreateFromURLFilterDictionary(
+ matcher.condition_factory(), &invalid_condition2, 2, &error);
+ EXPECT_FALSE(error.empty());
+ EXPECT_FALSE(result.get());
+
+ // Test invalid regex in urlMatches.
+ error.clear();
+ result = URLMatcherFactory::CreateFromURLFilterDictionary(
+ matcher.condition_factory(), &invalid_condition3, 3, &error);
+ EXPECT_FALSE(error.empty());
+ EXPECT_FALSE(result.get());
+
+ error.clear();
+ result = URLMatcherFactory::CreateFromURLFilterDictionary(
+ matcher.condition_factory(), &invalid_condition4, 4, &error);
+ EXPECT_FALSE(error.empty());
+ EXPECT_FALSE(result.get());
+
+ // Test success.
+ error.clear();
+ result = URLMatcherFactory::CreateFromURLFilterDictionary(
+ matcher.condition_factory(), &valid_condition, 100, &error);
+ EXPECT_EQ("", error);
+ ASSERT_TRUE(result.get());
+
+ URLMatcherConditionSet::Vector conditions;
+ conditions.push_back(result);
+ matcher.AddConditionSets(conditions);
+
+ EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com")).size());
+ EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:80")).size());
+ EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:1000")).size());
+ // Wrong scheme.
+ EXPECT_EQ(0u, matcher.MatchURL(GURL("https://www.example.com:80")).size());
+ // Wrong port.
+ EXPECT_EQ(0u, matcher.MatchURL(GURL("http://www.example.com:81")).size());
+ // Unfulfilled host prefix.
+ EXPECT_EQ(0u, matcher.MatchURL(GURL("http://mail.example.com:81")).size());
+}
+
+// Using upper case letters for scheme and host values is currently an error.
+// See more context at http://crbug.com/160702#c6 .
+TEST(URLMatcherFactoryTest, UpperCase) {
+ URLMatcher matcher;
+ std::string error;
+ scoped_refptr<URLMatcherConditionSet> result;
+
+ // {"hostContains": "exaMple"}
+ DictionaryValue invalid_condition1;
+ invalid_condition1.SetString(keys::kHostContainsKey, "exaMple");
+
+ // {"hostSuffix": ".Com"}
+ DictionaryValue invalid_condition2;
+ invalid_condition2.SetString(keys::kHostSuffixKey, ".Com");
+
+ // {"hostPrefix": "WWw."}
+ DictionaryValue invalid_condition3;
+ invalid_condition3.SetString(keys::kHostPrefixKey, "WWw.");
+
+ // {"hostEquals": "WWW.example.Com"}
+ DictionaryValue invalid_condition4;
+ invalid_condition4.SetString(keys::kHostEqualsKey, "WWW.example.Com");
+
+ // {"scheme": ["HTTP"]}
+ ListValue* scheme_list = new ListValue();
+ scheme_list->Append(Value::CreateStringValue("HTTP"));
+ DictionaryValue invalid_condition5;
+ invalid_condition5.Set(keys::kSchemesKey, scheme_list);
+
+ const DictionaryValue* invalid_conditions[] = {
+ &invalid_condition1,
+ &invalid_condition2,
+ &invalid_condition3,
+ &invalid_condition4,
+ &invalid_condition5
+ };
+
+ for (size_t i = 0; i < arraysize(invalid_conditions); ++i) {
+ error.clear();
+ result = URLMatcherFactory::CreateFromURLFilterDictionary(
+ matcher.condition_factory(), invalid_conditions[i], 1, &error);
+ EXPECT_FALSE(error.empty()) << "in iteration " << i;
+ EXPECT_FALSE(result.get()) << "in iteration " << i;
+ }
+}
+
+// This class wraps a case sensitivity test for a single UrlFilter condition.
+class UrlConditionCaseTest {
+ public:
+ // The condition is identified by the key |condition_key|. If that key is
+ // associated with string values, then |use_list_of_strings| should be false,
+ // if the key is associated with list-of-string values, then
+ // |use_list_of_strings| should be true. In |url| is the URL to test against.
+ UrlConditionCaseTest(const char* condition_key,
+ bool use_list_of_strings,
+ const std::string& expected_value,
+ const std::string& incorrect_case_value,
+ bool case_sensitive,
+ bool lower_case_enforced,
+ const GURL& url)
+ : condition_key_(condition_key),
+ use_list_of_strings_(use_list_of_strings),
+ expected_value_(expected_value),
+ incorrect_case_value_(incorrect_case_value),
+ expected_result_for_wrong_case_(ExpectedResult(case_sensitive,
+ lower_case_enforced)),
+ url_(url) {}
+
+ ~UrlConditionCaseTest() {}
+
+ // Match the condition against |url_|. Checks via EXPECT_* macros that
+ // |expected_value_| matches always, and that |incorrect_case_value_| matches
+ // iff |case_sensitive_| is false.
+ void Test() const;
+
+ private:
+ enum ResultType { OK, NOT_FULFILLED, CREATE_FAILURE };
+
+ // What is the expected result of |CheckCondition| if a wrong-case |value|
+ // containing upper case letters is supplied.
+ static ResultType ExpectedResult(bool case_sensitive,
+ bool lower_case_enforced) {
+ if (lower_case_enforced)
+ return CREATE_FAILURE;
+ if (case_sensitive)
+ return NOT_FULFILLED;
+ return OK;
+ }
+
+ // Test the condition |condition_key_| = |value| against |url_|.
+ // Check, via EXPECT_* macros, that either the condition cannot be constructed
+ // at all, or that the condition is not fulfilled, or that it is fulfilled,
+ // depending on the value of |expected_result|.
+ void CheckCondition(const std::string& value,
+ ResultType expected_result) const;
+
+ const char* condition_key_;
+ const bool use_list_of_strings_;
+ const std::string& expected_value_;
+ const std::string& incorrect_case_value_;
+ const ResultType expected_result_for_wrong_case_;
+ const GURL& url_;
+
+ // Allow implicit copy and assign, because a public copy constructor is
+ // needed, but never used (!), for the definition of arrays of this class.
+};
+
+void UrlConditionCaseTest::Test() const {
+ CheckCondition(expected_value_, OK);
+ CheckCondition(incorrect_case_value_, expected_result_for_wrong_case_);
+}
+
+void UrlConditionCaseTest::CheckCondition(
+ const std::string& value,
+ UrlConditionCaseTest::ResultType expected_result) const {
+ DictionaryValue condition;
+ if (use_list_of_strings_) {
+ ListValue* list = new ListValue();
+ list->Append(Value::CreateStringValue(value));
+ condition.SetWithoutPathExpansion(condition_key_, list);
+ } else {
+ condition.SetStringWithoutPathExpansion(condition_key_, value);
+ }
+
+ URLMatcher matcher;
+ std::string error;
+ scoped_refptr<URLMatcherConditionSet> result;
+
+ result = URLMatcherFactory::CreateFromURLFilterDictionary(
+ matcher.condition_factory(), &condition, 1, &error);
+ if (expected_result == CREATE_FAILURE) {
+ EXPECT_FALSE(error.empty());
+ EXPECT_FALSE(result.get());
+ return;
+ }
+ EXPECT_EQ("", error);
+ ASSERT_TRUE(result.get());
+
+ URLMatcherConditionSet::Vector conditions;
+ conditions.push_back(result);
+ matcher.AddConditionSets(conditions);
+ EXPECT_EQ((expected_result == OK ? 1u : 0u), matcher.MatchURL(url_).size())
+ << "while matching condition " << condition_key_ << " with value "
+ << value << " against url " << url_;
+}
+
+// This tests that the UrlFilter handles case sensitivity on various parts of
+// URLs correctly.
+TEST(URLMatcherFactoryTest, CaseSensitivity) {
+ const std::string kScheme("https");
+ const std::string kSchemeUpper("HTTPS");
+ const std::string kHost("www.example.com");
+ const std::string kHostUpper("WWW.EXAMPLE.COM");
+ const std::string kPath("/path");
+ const std::string kPathUpper("/PATH");
+ const std::string kQuery("?option=value&A=B");
+ const std::string kQueryUpper("?OPTION=VALUE&A=B");
+ const std::string kUrl(kScheme + "://" + kHost + ":1234" + kPath + kQuery);
+ const std::string kUrlUpper(
+ kSchemeUpper + "://" + kHostUpper + ":1234" + kPathUpper + kQueryUpper);
+ const GURL url(kUrl);
+ // Note: according to RFC 3986, and RFC 1034, schema and host, respectively
+ // should be case insensitive. See crbug.com/160702#6 for why we still
+ // require them to be case sensitive in UrlFilter, and enforce lower case.
+ const bool kIsSchemeLowerCaseEnforced = true;
+ const bool kIsHostLowerCaseEnforced = true;
+ const bool kIsPathLowerCaseEnforced = false;
+ const bool kIsQueryLowerCaseEnforced = false;
+ const bool kIsUrlLowerCaseEnforced = false;
+ const bool kIsSchemeCaseSensitive = true;
+ const bool kIsHostCaseSensitive = true;
+ const bool kIsPathCaseSensitive = true;
+ const bool kIsQueryCaseSensitive = true;
+ const bool kIsUrlCaseSensitive = kIsSchemeCaseSensitive ||
+ kIsHostCaseSensitive ||
+ kIsPathCaseSensitive ||
+ kIsQueryCaseSensitive;
+
+ const UrlConditionCaseTest case_tests[] = {
+ UrlConditionCaseTest(keys::kSchemesKey, true, kScheme, kSchemeUpper,
+ kIsSchemeCaseSensitive, kIsSchemeLowerCaseEnforced,
+ url),
+ UrlConditionCaseTest(keys::kHostContainsKey, false, kHost, kHostUpper,
+ kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kHostEqualsKey, false, kHost, kHostUpper,
+ kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kHostPrefixKey, false, kHost, kHostUpper,
+ kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kHostSuffixKey, false, kHost, kHostUpper,
+ kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kPathContainsKey, false, kPath, kPathUpper,
+ kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kPathEqualsKey, false, kPath, kPathUpper,
+ kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kPathPrefixKey, false, kPath, kPathUpper,
+ kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kPathSuffixKey, false, kPath, kPathUpper,
+ kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kQueryContainsKey, false, kQuery, kQueryUpper,
+ kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kQueryEqualsKey, false, kQuery, kQueryUpper,
+ kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kQueryPrefixKey, false, kQuery, kQueryUpper,
+ kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kQuerySuffixKey, false, kQuery, kQueryUpper,
+ kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
+ // Excluding kURLMatchesKey because case sensitivity can be specified in the
+ // RE2 expression.
+ UrlConditionCaseTest(keys::kURLContainsKey, false, kUrl, kUrlUpper,
+ kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kURLEqualsKey, false, kUrl, kUrlUpper,
+ kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kURLPrefixKey, false, kUrl, kUrlUpper,
+ kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
+ UrlConditionCaseTest(keys::kURLSuffixKey, false, kUrl, kUrlUpper,
+ kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(case_tests); ++i) {
+ SCOPED_TRACE(base::StringPrintf("Iteration: %" PRIuS, i));
+ case_tests[i].Test();
+ }
+}
+
+} // namespace url_matcher