15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/url_matcher/url_matcher_factory.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/format_macros.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/url_matcher/url_matcher_constants.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace url_matcher {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace keys = url_matcher_constants;
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcher matcher;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<URLMatcherConditionSet> result;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invalid key: {"invalid": "foobar"}
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_condition.SetString("invalid", "foobar");
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invalid value type: {"hostSuffix": []}
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition2;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  invalid_condition2.Set(keys::kHostSuffixKey, new base::ListValue);
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invalid regex value: {"urlMatches": "*"}
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition3;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_condition3.SetString(keys::kURLMatchesKey, "*");
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Invalid regex value: {"originAndPathMatches": "*"}
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition4;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  invalid_condition4.SetString(keys::kOriginAndPathMatchesKey, "*");
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Valid values:
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   "port_range": [80, [1000, 1010]],
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   "schemes": ["http"],
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   "hostSuffix": "example.com"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   "hostPrefix": "www"
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // }
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Port range: Allow 80;1000-1010.
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* port_range = new base::ListValue();
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  port_range->Append(new base::FundamentalValue(1000));
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  port_range->Append(new base::FundamentalValue(1010));
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* port_ranges = new base::ListValue();
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  port_ranges->Append(new base::FundamentalValue(80));
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  port_ranges->Append(port_range);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* scheme_list = new base::ListValue();
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scheme_list->Append(new base::StringValue("http"));
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue valid_condition;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  valid_condition.SetString(keys::kHostSuffixKey, "example.com");
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  valid_condition.SetString(keys::kHostPrefixKey, "www");
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  valid_condition.Set(keys::kPortsKey, port_ranges);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  valid_condition.Set(keys::kSchemesKey, scheme_list);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test wrong condition name passed.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error.clear();
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result = URLMatcherFactory::CreateFromURLFilterDictionary(
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matcher.condition_factory(), &invalid_condition, 1, &error);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(error.empty());
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result.get());
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test wrong datatype in hostSuffix.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error.clear();
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result = URLMatcherFactory::CreateFromURLFilterDictionary(
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matcher.condition_factory(), &invalid_condition2, 2, &error);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(error.empty());
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result.get());
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test invalid regex in urlMatches.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error.clear();
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result = URLMatcherFactory::CreateFromURLFilterDictionary(
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matcher.condition_factory(), &invalid_condition3, 3, &error);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(error.empty());
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(result.get());
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error.clear();
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result = URLMatcherFactory::CreateFromURLFilterDictionary(
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.condition_factory(), &invalid_condition4, 4, &error);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(error.empty());
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(result.get());
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test success.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error.clear();
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result = URLMatcherFactory::CreateFromURLFilterDictionary(
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matcher.condition_factory(), &valid_condition, 100, &error);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("", error);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(result.get());
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcherConditionSet::Vector conditions;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(result);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matcher.AddConditionSets(conditions);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com")).size());
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:80")).size());
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, matcher.MatchURL(GURL("http://www.example.com:1000")).size());
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wrong scheme.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, matcher.MatchURL(GURL("https://www.example.com:80")).size());
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wrong port.
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, matcher.MatchURL(GURL("http://www.example.com:81")).size());
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Unfulfilled host prefix.
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, matcher.MatchURL(GURL("http://mail.example.com:81")).size());
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Using upper case letters for scheme and host values is currently an error.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// See more context at http://crbug.com/160702#c6 .
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(URLMatcherFactoryTest, UpperCase) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcher matcher;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<URLMatcherConditionSet> result;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // {"hostContains": "exaMple"}
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition1;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_condition1.SetString(keys::kHostContainsKey, "exaMple");
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // {"hostSuffix": ".Com"}
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition2;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_condition2.SetString(keys::kHostSuffixKey, ".Com");
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // {"hostPrefix": "WWw."}
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition3;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_condition3.SetString(keys::kHostPrefixKey, "WWw.");
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // {"hostEquals": "WWW.example.Com"}
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition4;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_condition4.SetString(keys::kHostEqualsKey, "WWW.example.Com");
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // {"scheme": ["HTTP"]}
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* scheme_list = new base::ListValue();
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scheme_list->Append(new base::StringValue("HTTP"));
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue invalid_condition5;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_condition5.Set(keys::kSchemesKey, scheme_list);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* invalid_conditions[] = {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    &invalid_condition1,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    &invalid_condition2,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    &invalid_condition3,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    &invalid_condition4,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    &invalid_condition5
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(invalid_conditions); ++i) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error.clear();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result = URLMatcherFactory::CreateFromURLFilterDictionary(
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        matcher.condition_factory(), invalid_conditions[i], 1, &error);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(error.empty()) << "in iteration " << i;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(result.get()) << "in iteration " << i;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class wraps a case sensitivity test for a single UrlFilter condition.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class UrlConditionCaseTest {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The condition is identified by the key |condition_key|. If that key is
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // associated with string values, then |use_list_of_strings| should be false,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the key is associated with list-of-string values, then
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |use_list_of_strings| should be true. In |url| is the URL to test against.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UrlConditionCaseTest(const char* condition_key,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       bool use_list_of_strings,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const std::string& expected_value,
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const std::string& incorrect_case_value,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       bool case_sensitive,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       bool lower_case_enforced,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const GURL& url)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : condition_key_(condition_key),
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        use_list_of_strings_(use_list_of_strings),
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        expected_value_(expected_value),
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        incorrect_case_value_(incorrect_case_value),
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        expected_result_for_wrong_case_(ExpectedResult(case_sensitive,
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                       lower_case_enforced)),
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        url_(url) {}
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~UrlConditionCaseTest() {}
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Match the condition against |url_|. Checks via EXPECT_* macros that
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |expected_value_| matches always, and that |incorrect_case_value_| matches
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // iff |case_sensitive_| is false.
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Test() const;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum ResultType { OK, NOT_FULFILLED, CREATE_FAILURE };
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // What is the expected result of |CheckCondition| if a wrong-case |value|
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // containing upper case letters is supplied.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static ResultType ExpectedResult(bool case_sensitive,
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   bool lower_case_enforced) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (lower_case_enforced)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return CREATE_FAILURE;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (case_sensitive)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NOT_FULFILLED;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OK;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test the condition |condition_key_| = |value| against |url_|.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check, via EXPECT_* macros, that either the condition cannot be constructed
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // at all, or that the condition is not fulfilled, or that it is fulfilled,
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // depending on the value of |expected_result|.
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CheckCondition(const std::string& value,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      ResultType expected_result) const;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* condition_key_;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool use_list_of_strings_;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& expected_value_;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& incorrect_case_value_;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ResultType expected_result_for_wrong_case_;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL& url_;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allow implicit copy and assign, because a public copy constructor is
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // needed, but never used (!), for the definition of arrays of this class.
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UrlConditionCaseTest::Test() const {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckCondition(expected_value_, OK);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckCondition(incorrect_case_value_, expected_result_for_wrong_case_);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UrlConditionCaseTest::CheckCondition(
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& value,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest::ResultType expected_result) const {
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue condition;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (use_list_of_strings_) {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue* list = new base::ListValue();
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    list->Append(new base::StringValue(value));
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    condition.SetWithoutPathExpansion(condition_key_, list);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    condition.SetStringWithoutPathExpansion(condition_key_, value);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcher matcher;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<URLMatcherConditionSet> result;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result = URLMatcherFactory::CreateFromURLFilterDictionary(
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matcher.condition_factory(), &condition, 1, &error);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (expected_result == CREATE_FAILURE) {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(error.empty());
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_FALSE(result.get());
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("", error);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(result.get());
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLMatcherConditionSet::Vector conditions;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  conditions.push_back(result);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matcher.AddConditionSets(conditions);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ((expected_result == OK ? 1u : 0u), matcher.MatchURL(url_).size())
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "while matching condition " << condition_key_ << " with value "
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << value  << " against url " << url_;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This tests that the UrlFilter handles case sensitivity on various parts of
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// URLs correctly.
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(URLMatcherFactoryTest, CaseSensitivity) {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kScheme("https");
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kSchemeUpper("HTTPS");
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kHost("www.example.com");
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kHostUpper("WWW.EXAMPLE.COM");
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kPath("/path");
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kPathUpper("/PATH");
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kQuery("?option=value&A=B");
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kQueryUpper("?OPTION=VALUE&A=B");
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kUrl(kScheme + "://" + kHost + ":1234" + kPath + kQuery);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string kUrlUpper(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kSchemeUpper + "://" + kHostUpper + ":1234" + kPathUpper + kQueryUpper);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL url(kUrl);
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: according to RFC 3986, and RFC 1034, schema and host, respectively
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should be case insensitive. See crbug.com/160702#6 for why we still
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // require them to be case sensitive in UrlFilter, and enforce lower case.
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsSchemeLowerCaseEnforced = true;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsHostLowerCaseEnforced = true;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsPathLowerCaseEnforced = false;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsQueryLowerCaseEnforced = false;
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsUrlLowerCaseEnforced = false;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsSchemeCaseSensitive = true;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsHostCaseSensitive = true;
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsPathCaseSensitive = true;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsQueryCaseSensitive = true;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool kIsUrlCaseSensitive = kIsSchemeCaseSensitive ||
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   kIsHostCaseSensitive ||
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   kIsPathCaseSensitive ||
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   kIsQueryCaseSensitive;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const UrlConditionCaseTest case_tests[] = {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kSchemesKey, true, kScheme, kSchemeUpper,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsSchemeCaseSensitive, kIsSchemeLowerCaseEnforced,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         url),
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kHostContainsKey, false, kHost, kHostUpper,
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kHostEqualsKey, false, kHost, kHostUpper,
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kHostPrefixKey, false, kHost, kHostUpper,
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kHostSuffixKey, false, kHost, kHostUpper,
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsHostCaseSensitive, kIsHostLowerCaseEnforced, url),
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kPathContainsKey, false, kPath, kPathUpper,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kPathEqualsKey, false, kPath, kPathUpper,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kPathPrefixKey, false, kPath, kPathUpper,
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kPathSuffixKey, false, kPath, kPathUpper,
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsPathCaseSensitive, kIsPathLowerCaseEnforced, url),
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kQueryContainsKey, false, kQuery, kQueryUpper,
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kQueryEqualsKey, false, kQuery, kQueryUpper,
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kQueryPrefixKey, false, kQuery, kQueryUpper,
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kQuerySuffixKey, false, kQuery, kQueryUpper,
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsQueryCaseSensitive, kIsQueryLowerCaseEnforced, url),
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Excluding kURLMatchesKey because case sensitivity can be specified in the
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // RE2 expression.
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kURLContainsKey, false, kUrl, kUrlUpper,
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kURLEqualsKey, false, kUrl, kUrlUpper,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kURLPrefixKey, false, kUrl, kUrlUpper,
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UrlConditionCaseTest(keys::kURLSuffixKey, false, kUrl, kUrlUpper,
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kIsUrlCaseSensitive, kIsUrlLowerCaseEnforced, url),
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(case_tests); ++i) {
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("Iteration: %" PRIuS, i));
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case_tests[i].Test();
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace url_matcher
340