root/components/url_matcher/url_matcher_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. TEST
  2. TEST
  3. TEST
  4. TEST
  5. TEST
  6. TEST
  7. Matches
  8. TEST
  9. TEST
  10. TEST
  11. TEST
  12. TEST
  13. TEST
  14. TEST
  15. TEST
  16. TEST
  17. TEST
  18. TEST

// 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.h"

#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace url_matcher {

//
// URLMatcherCondition
//

TEST(URLMatcherConditionTest, Constructors) {
  StringPattern pattern("example.com", 1);
  URLMatcherCondition m1(URLMatcherCondition::HOST_SUFFIX, &pattern);
  EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX, m1.criterion());
  EXPECT_EQ(&pattern, m1.string_pattern());

  URLMatcherCondition m2;
  m2 = m1;
  EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX, m2.criterion());
  EXPECT_EQ(&pattern, m2.string_pattern());

  URLMatcherCondition m3(m1);
  EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX, m3.criterion());
  EXPECT_EQ(&pattern, m3.string_pattern());
}

TEST(URLMatcherSchemeFilter, TestMatching) {
  URLMatcherSchemeFilter filter1("https");
  std::vector<std::string> filter2_content;
  filter2_content.push_back("http");
  filter2_content.push_back("https");
  URLMatcherSchemeFilter filter2(filter2_content);

  GURL matching_url("https://www.foobar.com");
  GURL non_matching_url("http://www.foobar.com");
  EXPECT_TRUE(filter1.IsMatch(matching_url));
  EXPECT_FALSE(filter1.IsMatch(non_matching_url));
  EXPECT_TRUE(filter2.IsMatch(matching_url));
  EXPECT_TRUE(filter2.IsMatch(non_matching_url));
}

TEST(URLMatcherPortFilter, TestMatching) {
  std::vector<URLMatcherPortFilter::Range> ranges;
  ranges.push_back(URLMatcherPortFilter::CreateRange(80, 90));
  ranges.push_back(URLMatcherPortFilter::CreateRange(8080));
  URLMatcherPortFilter filter(ranges);
  EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com")));
  EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:80")));
  EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:81")));
  EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:90")));
  EXPECT_TRUE(filter.IsMatch(GURL("http://www.example.com:8080")));
  EXPECT_FALSE(filter.IsMatch(GURL("http://www.example.com:79")));
  EXPECT_FALSE(filter.IsMatch(GURL("http://www.example.com:91")));
  EXPECT_FALSE(filter.IsMatch(GURL("https://www.example.com")));
}

TEST(URLMatcherConditionTest, IsFullURLCondition) {
  StringPattern pattern("example.com", 1);
  EXPECT_FALSE(URLMatcherCondition(URLMatcherCondition::HOST_SUFFIX,
      &pattern).IsFullURLCondition());

  EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::HOST_CONTAINS,
      &pattern).IsFullURLCondition());
  EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::PATH_CONTAINS,
      &pattern).IsFullURLCondition());
  EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::QUERY_CONTAINS,
      &pattern).IsFullURLCondition());

  EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_PREFIX,
      &pattern).IsFullURLCondition());
  EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_SUFFIX,
      &pattern).IsFullURLCondition());
  EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_CONTAINS,
      &pattern).IsFullURLCondition());
  EXPECT_TRUE(URLMatcherCondition(URLMatcherCondition::URL_EQUALS,
      &pattern).IsFullURLCondition());
}

TEST(URLMatcherConditionTest, IsMatch) {
  GURL url1("http://www.example.com/www.foobar.com/index.html");
  GURL url2("http://www.foobar.com/example.com/index.html");

  StringPattern pattern("example.com", 1);
  URLMatcherCondition m1(URLMatcherCondition::HOST_SUFFIX, &pattern);

  std::set<StringPattern::ID> matching_patterns;

  // matches = {0} --> matcher did not indicate that m1 was a match.
  matching_patterns.insert(0);
  EXPECT_FALSE(m1.IsMatch(matching_patterns, url1));

  // matches = {0, 1} --> matcher did indicate that m1 was a match.
  matching_patterns.insert(1);
  EXPECT_TRUE(m1.IsMatch(matching_patterns, url1));

  // For m2 we use a HOST_CONTAINS test, which requires a post-validation
  // whether the match reported by the SubstringSetMatcher occurs really
  // in the correct url component.
  URLMatcherCondition m2(URLMatcherCondition::HOST_CONTAINS, &pattern);
  EXPECT_TRUE(m2.IsMatch(matching_patterns, url1));
  EXPECT_FALSE(m2.IsMatch(matching_patterns, url2));
}

TEST(URLMatcherConditionTest, Comparison) {
  StringPattern p1("foobar.com", 1);
  StringPattern p2("foobar.com", 2);
  // The first component of each test is expected to be < than the second.
  URLMatcherCondition test_smaller[][2] = {
      {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
       URLMatcherCondition(URLMatcherCondition::HOST_SUFFIX, &p1)},
      {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
       URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p2)},
      {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, NULL),
       URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p2)},
      {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
       URLMatcherCondition(URLMatcherCondition::HOST_SUFFIX, NULL)},
  };
  for (size_t i = 0; i < arraysize(test_smaller); ++i) {
    EXPECT_TRUE(test_smaller[i][0] < test_smaller[i][1])
        << "Test " << i << " of test_smaller failed";
    EXPECT_FALSE(test_smaller[i][1] < test_smaller[i][0])
        << "Test " << i << " of test_smaller failed";
  }
  URLMatcherCondition test_equal[][2] = {
      {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1),
       URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, &p1)},
      {URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, NULL),
       URLMatcherCondition(URLMatcherCondition::HOST_PREFIX, NULL)},
  };
  for (size_t i = 0; i < arraysize(test_equal); ++i) {
    EXPECT_FALSE(test_equal[i][0] < test_equal[i][1])
        << "Test " << i << " of test_equal failed";
    EXPECT_FALSE(test_equal[i][1] < test_equal[i][0])
        << "Test " << i << " of test_equal failed";
  }
}

//
// URLMatcherConditionFactory
//

namespace {

bool Matches(const URLMatcherCondition& condition, std::string text) {
  return text.find(condition.string_pattern()->pattern()) !=
      std::string::npos;
}

}  // namespace

TEST(URLMatcherConditionFactoryTest, GURLCharacterSet) {
  // GURL guarantees that neither domain, nor path, nor query may contain
  // non ASCII-7 characters. We test this here, because a change to this
  // guarantee breaks this implementation horribly.
  GURL url("http://www.föö.com/föö?föö#föö");
  EXPECT_TRUE(IsStringASCII(url.host()));
  EXPECT_TRUE(IsStringASCII(url.path()));
  EXPECT_TRUE(IsStringASCII(url.query()));
  EXPECT_FALSE(IsStringASCII(url.ref()));
}

TEST(URLMatcherConditionFactoryTest, Criteria) {
  URLMatcherConditionFactory factory;
  EXPECT_EQ(URLMatcherCondition::HOST_PREFIX,
            factory.CreateHostPrefixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX,
            factory.CreateHostSuffixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::HOST_CONTAINS,
            factory.CreateHostContainsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::HOST_EQUALS,
            factory.CreateHostEqualsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::PATH_PREFIX,
            factory.CreatePathPrefixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::PATH_SUFFIX,
            factory.CreatePathSuffixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::PATH_CONTAINS,
            factory.CreatePathContainsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::PATH_EQUALS,
            factory.CreatePathEqualsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::QUERY_PREFIX,
            factory.CreateQueryPrefixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::QUERY_SUFFIX,
            factory.CreateQuerySuffixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::QUERY_CONTAINS,
            factory.CreateQueryContainsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::QUERY_EQUALS,
            factory.CreateQueryEqualsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::HOST_SUFFIX_PATH_PREFIX,
            factory.CreateHostSuffixPathPrefixCondition("foo",
                                                        "bar").criterion());
  EXPECT_EQ(URLMatcherCondition::HOST_EQUALS_PATH_PREFIX,
            factory.CreateHostEqualsPathPrefixCondition("foo",
                                                        "bar").criterion());
  EXPECT_EQ(URLMatcherCondition::URL_PREFIX,
            factory.CreateURLPrefixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::URL_SUFFIX,
            factory.CreateURLSuffixCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::URL_CONTAINS,
            factory.CreateURLContainsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::URL_EQUALS,
            factory.CreateURLEqualsCondition("foo").criterion());
  EXPECT_EQ(URLMatcherCondition::URL_MATCHES,
            factory.CreateURLMatchesCondition("foo").criterion());
}

TEST(URLMatcherConditionFactoryTest, TestSingletonProperty) {
  URLMatcherConditionFactory factory;
  URLMatcherCondition c1 = factory.CreateHostEqualsCondition("www.google.com");
  URLMatcherCondition c2 = factory.CreateHostEqualsCondition("www.google.com");
  EXPECT_EQ(c1.criterion(), c2.criterion());
  EXPECT_EQ(c1.string_pattern(), c2.string_pattern());
  URLMatcherCondition c3 = factory.CreateHostEqualsCondition("www.google.de");
  EXPECT_EQ(c2.criterion(), c3.criterion());
  EXPECT_NE(c2.string_pattern(), c3.string_pattern());
  EXPECT_NE(c2.string_pattern()->id(), c3.string_pattern()->id());
  EXPECT_NE(c2.string_pattern()->pattern(),
            c3.string_pattern()->pattern());
  URLMatcherCondition c4 = factory.CreateURLMatchesCondition("www.google.com");
  URLMatcherCondition c5 = factory.CreateURLContainsCondition("www.google.com");
  // Regex patterns and substring patterns do not share IDs.
  EXPECT_EQ(c5.string_pattern()->pattern(), c4.string_pattern()->pattern());
  EXPECT_NE(c5.string_pattern(), c4.string_pattern());
  EXPECT_NE(c5.string_pattern()->id(), c4.string_pattern()->id());

  // Check that all StringPattern singletons are freed if we call
  // ForgetUnusedPatterns.
  StringPattern::ID old_id_1 = c1.string_pattern()->id();
  StringPattern::ID old_id_4 = c4.string_pattern()->id();
  factory.ForgetUnusedPatterns(std::set<StringPattern::ID>());
  EXPECT_TRUE(factory.IsEmpty());
  URLMatcherCondition c6 = factory.CreateHostEqualsCondition("www.google.com");
  EXPECT_NE(old_id_1, c6.string_pattern()->id());
  URLMatcherCondition c7 = factory.CreateURLMatchesCondition("www.google.com");
  EXPECT_NE(old_id_4, c7.string_pattern()->id());
}

TEST(URLMatcherConditionFactoryTest, TestComponentSearches) {
  GURL gurl("https://www.google.com:1234/webhp?sourceid=chrome-instant&ie=UTF-8"
      "&ion=1#hl=en&output=search&sclient=psy-ab&q=chrome%20is%20awesome");
  URLMatcherConditionFactory factory;
  std::string url = factory.CanonicalizeURLForComponentSearches(gurl);

  // Test host component.
  EXPECT_TRUE(Matches(factory.CreateHostPrefixCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreateHostPrefixCondition("www.goog"), url));
  EXPECT_TRUE(
      Matches(factory.CreateHostPrefixCondition("www.google.com"), url));
  EXPECT_TRUE(
      Matches(factory.CreateHostPrefixCondition(".www.google.com"), url));
  EXPECT_FALSE(Matches(factory.CreateHostPrefixCondition("google.com"), url));
  EXPECT_FALSE(
      Matches(factory.CreateHostPrefixCondition("www.google.com/"), url));
  EXPECT_FALSE(Matches(factory.CreateHostPrefixCondition("webhp"), url));

  EXPECT_TRUE(Matches(factory.CreateHostSuffixCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreateHostSuffixCondition("com"), url));
  EXPECT_TRUE(Matches(factory.CreateHostSuffixCondition(".com"), url));
  EXPECT_TRUE(
      Matches(factory.CreateHostSuffixCondition("www.google.com"), url));
  EXPECT_TRUE(
      Matches(factory.CreateHostSuffixCondition(".www.google.com"), url));
  EXPECT_FALSE(Matches(factory.CreateHostSuffixCondition("www"), url));
  EXPECT_FALSE(
      Matches(factory.CreateHostSuffixCondition("www.google.com/"), url));
  EXPECT_FALSE(Matches(factory.CreateHostSuffixCondition("webhp"), url));

  EXPECT_FALSE(Matches(factory.CreateHostEqualsCondition(std::string()), url));
  EXPECT_FALSE(Matches(factory.CreateHostEqualsCondition("www"), url));
  EXPECT_TRUE(
      Matches(factory.CreateHostEqualsCondition("www.google.com"), url));
  EXPECT_FALSE(
      Matches(factory.CreateHostEqualsCondition("www.google.com/"), url));


  // Test path component.
  EXPECT_TRUE(Matches(factory.CreatePathPrefixCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreatePathPrefixCondition("/web"), url));
  EXPECT_TRUE(Matches(factory.CreatePathPrefixCondition("/webhp"), url));
  EXPECT_FALSE(Matches(factory.CreatePathPrefixCondition("webhp"), url));
  EXPECT_FALSE(Matches(factory.CreatePathPrefixCondition("/webhp?"), url));
  EXPECT_FALSE(Matches(factory.CreatePathPrefixCondition("?sourceid"), url));

  EXPECT_TRUE(Matches(factory.CreatePathSuffixCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreatePathSuffixCondition("webhp"), url));
  EXPECT_TRUE(Matches(factory.CreatePathSuffixCondition("/webhp"), url));
  EXPECT_FALSE(Matches(factory.CreatePathSuffixCondition("/web"), url));
  EXPECT_FALSE(Matches(factory.CreatePathSuffixCondition("/webhp?"), url));

  EXPECT_TRUE(Matches(factory.CreatePathEqualsCondition("/webhp"), url));
  EXPECT_FALSE(Matches(factory.CreatePathEqualsCondition("webhp"), url));
  EXPECT_FALSE(Matches(factory.CreatePathEqualsCondition("/webhp?"), url));
  EXPECT_FALSE(
      Matches(factory.CreatePathEqualsCondition("www.google.com"), url));


  // Test query component.
  EXPECT_TRUE(Matches(factory.CreateQueryPrefixCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreateQueryPrefixCondition("sourceid"), url));
  // The '?' at the beginning is just ignored.
  EXPECT_TRUE(Matches(factory.CreateQueryPrefixCondition("?sourceid"), url));

  EXPECT_TRUE(Matches(factory.CreateQuerySuffixCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreateQuerySuffixCondition("ion=1"), url));
  EXPECT_FALSE(Matches(factory.CreateQuerySuffixCondition("www"), url));
  // "Suffix" condition + pattern starting with '?' = "equals" condition.
  EXPECT_FALSE(Matches(factory.CreateQuerySuffixCondition(
      "?sourceid=chrome-instant&ie=UTF-8&ion="), url));
  EXPECT_TRUE(Matches(factory.CreateQuerySuffixCondition(
      "?sourceid=chrome-instant&ie=UTF-8&ion=1"), url));

  EXPECT_FALSE(Matches(factory.CreateQueryEqualsCondition(
      "?sourceid=chrome-instant&ie=UTF-8&ion="), url));
  EXPECT_FALSE(Matches(factory.CreateQueryEqualsCondition(
      "sourceid=chrome-instant&ie=UTF-8&ion="), url));
  EXPECT_TRUE(Matches(factory.CreateQueryEqualsCondition(
      "sourceid=chrome-instant&ie=UTF-8&ion=1"), url));
  // The '?' at the beginning is just ignored.
  EXPECT_TRUE(Matches(factory.CreateQueryEqualsCondition(
      "?sourceid=chrome-instant&ie=UTF-8&ion=1"), url));
  EXPECT_FALSE(
      Matches(factory.CreateQueryEqualsCondition("www.google.com"), url));


  // Test adjacent components
  EXPECT_TRUE(Matches(factory.CreateHostSuffixPathPrefixCondition(
      "google.com", "/webhp"), url));
  EXPECT_TRUE(Matches(
      factory.CreateHostSuffixPathPrefixCondition(std::string(), "/webhp"),
      url));
  EXPECT_TRUE(Matches(
      factory.CreateHostSuffixPathPrefixCondition("google.com", std::string()),
      url));
  EXPECT_FALSE(Matches(
      factory.CreateHostSuffixPathPrefixCondition("www", std::string()), url));

  EXPECT_TRUE(Matches(factory.CreateHostEqualsPathPrefixCondition(
      "www.google.com", "/webhp"), url));
  EXPECT_FALSE(Matches(
      factory.CreateHostEqualsPathPrefixCondition(std::string(), "/webhp"),
      url));
  EXPECT_TRUE(Matches(factory.CreateHostEqualsPathPrefixCondition(
                          "www.google.com", std::string()),
                      url));
  EXPECT_FALSE(Matches(
      factory.CreateHostEqualsPathPrefixCondition("google.com", std::string()),
      url));
}

TEST(URLMatcherConditionFactoryTest, TestFullSearches) {
  // The Port 443 is stripped because it is the default port for https.
  GURL gurl("https://www.google.com:443/webhp?sourceid=chrome-instant&ie=UTF-8"
      "&ion=1#hl=en&output=search&sclient=psy-ab&q=chrome%20is%20awesome");
  URLMatcherConditionFactory factory;
  std::string url = factory.CanonicalizeURLForFullSearches(gurl);

  EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(std::string()), url));
  EXPECT_TRUE(
      Matches(factory.CreateURLPrefixCondition("https://www.goog"), url));
  EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(
      "https://www.google.com"), url));
  EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(
      "https://www.google.com/webhp?"), url));
  EXPECT_FALSE(Matches(factory.CreateURLPrefixCondition(
      "http://www.google.com"), url));
  EXPECT_FALSE(Matches(factory.CreateURLPrefixCondition("webhp"), url));

  EXPECT_TRUE(Matches(factory.CreateURLSuffixCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreateURLSuffixCondition("ion=1"), url));
  EXPECT_FALSE(Matches(factory.CreateURLSuffixCondition("www"), url));

  EXPECT_TRUE(Matches(factory.CreateURLContainsCondition(std::string()), url));
  EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("www.goog"), url));
  EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("webhp"), url));
  EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("?"), url));
  EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("sourceid"), url));
  EXPECT_TRUE(Matches(factory.CreateURLContainsCondition("ion=1"), url));
  EXPECT_FALSE(Matches(factory.CreateURLContainsCondition(".www.goog"), url));
  EXPECT_FALSE(Matches(factory.CreateURLContainsCondition("foobar"), url));
  EXPECT_FALSE(Matches(factory.CreateURLContainsCondition("search"), url));
  EXPECT_FALSE(Matches(factory.CreateURLContainsCondition(":443"), url));

  EXPECT_TRUE(Matches(factory.CreateURLEqualsCondition(
      "https://www.google.com/webhp?sourceid=chrome-instant&ie=UTF-8&ion=1"),
      url));
  EXPECT_FALSE(
      Matches(factory.CreateURLEqualsCondition("https://www.google.com"), url));

  // Same as above but this time with a non-standard port.
  gurl = GURL("https://www.google.com:1234/webhp?sourceid=chrome-instant&"
      "ie=UTF-8&ion=1#hl=en&output=search&sclient=psy-ab&q=chrome%20is%20"
      "awesome");
  url = factory.CanonicalizeURLForFullSearches(gurl);
  EXPECT_TRUE(Matches(factory.CreateURLPrefixCondition(
      "https://www.google.com:1234/webhp?"), url));
  EXPECT_TRUE(Matches(factory.CreateURLContainsCondition(":1234"), url));
}

//
// URLMatcherConditionSet
//

TEST(URLMatcherConditionSetTest, Constructor) {
  URLMatcherConditionFactory factory;
  URLMatcherCondition m1 = factory.CreateHostSuffixCondition("example.com");
  URLMatcherCondition m2 = factory.CreatePathContainsCondition("foo");

  std::set<URLMatcherCondition> conditions;
  conditions.insert(m1);
  conditions.insert(m2);

  scoped_refptr<URLMatcherConditionSet> condition_set(
      new URLMatcherConditionSet(1, conditions));
  EXPECT_EQ(1, condition_set->id());
  EXPECT_EQ(2u, condition_set->conditions().size());
}

TEST(URLMatcherConditionSetTest, Matching) {
  GURL url1("http://www.example.com/foo?bar=1");
  GURL url2("http://foo.example.com/index.html");
  GURL url3("http://www.example.com:80/foo?bar=1");
  GURL url4("http://www.example.com:8080/foo?bar=1");

  URLMatcherConditionFactory factory;
  URLMatcherCondition m1 = factory.CreateHostSuffixCondition("example.com");
  URLMatcherCondition m2 = factory.CreatePathContainsCondition("foo");

  std::set<URLMatcherCondition> conditions;
  conditions.insert(m1);
  conditions.insert(m2);

  scoped_refptr<URLMatcherConditionSet> condition_set(
      new URLMatcherConditionSet(1, conditions));
  EXPECT_EQ(1, condition_set->id());
  EXPECT_EQ(2u, condition_set->conditions().size());

  std::set<StringPattern::ID> matching_patterns;
  matching_patterns.insert(m1.string_pattern()->id());
  EXPECT_FALSE(condition_set->IsMatch(matching_patterns, url1));

  matching_patterns.insert(m2.string_pattern()->id());
  EXPECT_TRUE(condition_set->IsMatch(matching_patterns, url1));
  EXPECT_FALSE(condition_set->IsMatch(matching_patterns, url2));

  // Test scheme filters.
  scoped_refptr<URLMatcherConditionSet> condition_set2(
      new URLMatcherConditionSet(1,
                                 conditions,
                                 scoped_ptr<URLMatcherSchemeFilter>(
                                     new URLMatcherSchemeFilter("https")),
                                 scoped_ptr<URLMatcherPortFilter>()));
  EXPECT_FALSE(condition_set2->IsMatch(matching_patterns, url1));
  scoped_refptr<URLMatcherConditionSet> condition_set3(
      new URLMatcherConditionSet(1,
                                 conditions,
                                 scoped_ptr<URLMatcherSchemeFilter>(
                                     new URLMatcherSchemeFilter("http")),
                                 scoped_ptr<URLMatcherPortFilter>()));
  EXPECT_TRUE(condition_set3->IsMatch(matching_patterns, url1));

  // Test port filters.
  std::vector<URLMatcherPortFilter::Range> ranges;
  ranges.push_back(URLMatcherPortFilter::CreateRange(80));
  scoped_ptr<URLMatcherPortFilter> filter(new URLMatcherPortFilter(ranges));
  scoped_refptr<URLMatcherConditionSet> condition_set4(
      new URLMatcherConditionSet(
          1, conditions, scoped_ptr<URLMatcherSchemeFilter>(), filter.Pass()));
  EXPECT_TRUE(condition_set4->IsMatch(matching_patterns, url1));
  EXPECT_TRUE(condition_set4->IsMatch(matching_patterns, url3));
  EXPECT_FALSE(condition_set4->IsMatch(matching_patterns, url4));

  // Test regex patterns.
  matching_patterns.clear();
  URLMatcherCondition r1 = factory.CreateURLMatchesCondition("/fo?oo");
  std::set<URLMatcherCondition> regex_conditions;
  regex_conditions.insert(r1);
  scoped_refptr<URLMatcherConditionSet> condition_set5(
      new URLMatcherConditionSet(1, regex_conditions));
  EXPECT_FALSE(condition_set5->IsMatch(matching_patterns, url1));
  matching_patterns.insert(r1.string_pattern()->id());
  EXPECT_TRUE(condition_set5->IsMatch(matching_patterns, url1));

  regex_conditions.insert(m1);
  scoped_refptr<URLMatcherConditionSet> condition_set6(
      new URLMatcherConditionSet(1, regex_conditions));
  EXPECT_FALSE(condition_set6->IsMatch(matching_patterns, url1));
  matching_patterns.insert(m1.string_pattern()->id());
  EXPECT_TRUE(condition_set6->IsMatch(matching_patterns, url1));

  matching_patterns.clear();
  regex_conditions.clear();
  URLMatcherCondition r2 = factory.CreateOriginAndPathMatchesCondition("b[a]r");
  regex_conditions.insert(r2);
  scoped_refptr<URLMatcherConditionSet> condition_set7(
      new URLMatcherConditionSet(1, regex_conditions));
  EXPECT_FALSE(condition_set7->IsMatch(matching_patterns, url1));
  matching_patterns.insert(r2.string_pattern()->id());
  EXPECT_TRUE(condition_set7->IsMatch(matching_patterns, url1));
}


//
// URLMatcher
//

TEST(URLMatcherTest, FullTest) {
  GURL url1("http://www.example.com/foo?bar=1");
  GURL url2("http://foo.example.com/index.html");

  URLMatcher matcher;
  URLMatcherConditionFactory* factory = matcher.condition_factory();

  // First insert.
  URLMatcherConditionSet::Conditions conditions1;
  conditions1.insert(factory->CreateHostSuffixCondition("example.com"));
  conditions1.insert(factory->CreatePathContainsCondition("foo"));

  const int kConditionSetId1 = 1;
  URLMatcherConditionSet::Vector insert1;
  insert1.push_back(make_scoped_refptr(
      new URLMatcherConditionSet(kConditionSetId1, conditions1)));
  matcher.AddConditionSets(insert1);
  EXPECT_EQ(1u, matcher.MatchURL(url1).size());
  EXPECT_EQ(0u, matcher.MatchURL(url2).size());

  // Second insert.
  URLMatcherConditionSet::Conditions conditions2;
  conditions2.insert(factory->CreateHostSuffixCondition("example.com"));

  const int kConditionSetId2 = 2;
  URLMatcherConditionSet::Vector insert2;
  insert2.push_back(make_scoped_refptr(
      new URLMatcherConditionSet(kConditionSetId2, conditions2)));
  matcher.AddConditionSets(insert2);
  EXPECT_EQ(2u, matcher.MatchURL(url1).size());
  EXPECT_EQ(1u, matcher.MatchURL(url2).size());

  // This should be the cached singleton.
  int patternId1 = factory->CreateHostSuffixCondition(
      "example.com").string_pattern()->id();

  // Third insert.
  URLMatcherConditionSet::Conditions conditions3;
  conditions3.insert(factory->CreateHostSuffixCondition("example.com"));
  conditions3.insert(factory->CreateURLMatchesCondition("x.*[0-9]"));

  const int kConditionSetId3 = 3;
  URLMatcherConditionSet::Vector insert3;
  insert3.push_back(make_scoped_refptr(
      new URLMatcherConditionSet(kConditionSetId3, conditions3)));
  matcher.AddConditionSets(insert3);
  EXPECT_EQ(3u, matcher.MatchURL(url1).size());
  EXPECT_EQ(1u, matcher.MatchURL(url2).size());

  // Removal of third insert.
  std::vector<URLMatcherConditionSet::ID> remove3;
  remove3.push_back(kConditionSetId3);
  matcher.RemoveConditionSets(remove3);
  EXPECT_EQ(2u, matcher.MatchURL(url1).size());
  EXPECT_EQ(1u, matcher.MatchURL(url2).size());

  // Removal of second insert.
  std::vector<URLMatcherConditionSet::ID> remove2;
  remove2.push_back(kConditionSetId2);
  matcher.RemoveConditionSets(remove2);
  EXPECT_EQ(1u, matcher.MatchURL(url1).size());
  EXPECT_EQ(0u, matcher.MatchURL(url2).size());

  // Removal of first insert.
  std::vector<URLMatcherConditionSet::ID> remove1;
  remove1.push_back(kConditionSetId1);
  matcher.RemoveConditionSets(remove1);
  EXPECT_EQ(0u, matcher.MatchURL(url1).size());
  EXPECT_EQ(0u, matcher.MatchURL(url2).size());

  EXPECT_TRUE(matcher.IsEmpty());

  // The cached singleton in matcher.condition_factory_ should be destroyed to
  // free memory.
  int patternId2 = factory->CreateHostSuffixCondition(
      "example.com").string_pattern()->id();
  // If patternId1 and patternId2 are different that indicates that
  // matcher.condition_factory_ does not leak memory by holding onto
  // unused patterns.
  EXPECT_NE(patternId1, patternId2);
}

TEST(URLMatcherTest, TestComponentsImplyContains) {
  // Due to a different implementation of component (prefix, suffix and equals)
  // and *Contains conditions we need to check that when a pattern matches a
  // given part of a URL as equal, prefix or suffix, it also matches it in the
  // "contains" test.
  GURL url("https://www.google.com:1234/webhp?test=val&a=b");

  URLMatcher matcher;
  URLMatcherConditionFactory* factory = matcher.condition_factory();

  URLMatcherConditionSet::Conditions conditions;

  // First insert all the matching equals => contains pairs.
  conditions.insert(factory->CreateHostEqualsCondition("www.google.com"));
  conditions.insert(factory->CreateHostContainsCondition("www.google.com"));

  conditions.insert(factory->CreateHostPrefixCondition("www."));
  conditions.insert(factory->CreateHostContainsCondition("www."));

  conditions.insert(factory->CreateHostSuffixCondition("com"));
  conditions.insert(factory->CreateHostContainsCondition("com"));

  conditions.insert(factory->CreatePathEqualsCondition("/webhp"));
  conditions.insert(factory->CreatePathContainsCondition("/webhp"));

  conditions.insert(factory->CreatePathPrefixCondition("/we"));
  conditions.insert(factory->CreatePathContainsCondition("/we"));

  conditions.insert(factory->CreatePathSuffixCondition("hp"));
  conditions.insert(factory->CreatePathContainsCondition("hp"));

  conditions.insert(factory->CreateQueryEqualsCondition("test=val&a=b"));
  conditions.insert(factory->CreateQueryContainsCondition("test=val&a=b"));

  conditions.insert(factory->CreateQueryPrefixCondition("test=v"));
  conditions.insert(factory->CreateQueryContainsCondition("test=v"));

  conditions.insert(factory->CreateQuerySuffixCondition("l&a=b"));
  conditions.insert(factory->CreateQueryContainsCondition("l&a=b"));

  // The '?' for equality is just ignored.
  conditions.insert(factory->CreateQueryEqualsCondition("?test=val&a=b"));
  // Due to '?' the condition created here is a prefix-testing condition.
  conditions.insert(factory->CreateQueryContainsCondition("?test=val&a=b"));

  const int kConditionSetId = 1;
  URLMatcherConditionSet::Vector insert;
  insert.push_back(make_scoped_refptr(
      new URLMatcherConditionSet(kConditionSetId, conditions)));
  matcher.AddConditionSets(insert);
  EXPECT_EQ(1u, matcher.MatchURL(url).size());
}

// Check that matches in everything but the query are found.
TEST(URLMatcherTest, TestOriginAndPathRegExPositive) {
  GURL url("https://www.google.com:1234/webhp?test=val&a=b");

  URLMatcher matcher;
  URLMatcherConditionFactory* factory = matcher.condition_factory();

  URLMatcherConditionSet::Conditions conditions;

  conditions.insert(factory->CreateOriginAndPathMatchesCondition("w..hp"));
  const int kConditionSetId = 1;
  URLMatcherConditionSet::Vector insert;
  insert.push_back(make_scoped_refptr(
      new URLMatcherConditionSet(kConditionSetId, conditions)));
  matcher.AddConditionSets(insert);
  EXPECT_EQ(1u, matcher.MatchURL(url).size());
}

// Check that matches in the query are ignored.
TEST(URLMatcherTest, TestOriginAndPathRegExNegative) {
  GURL url("https://www.google.com:1234/webhp?test=val&a=b");

  URLMatcher matcher;
  URLMatcherConditionFactory* factory = matcher.condition_factory();

  URLMatcherConditionSet::Conditions conditions;

  conditions.insert(factory->CreateOriginAndPathMatchesCondition("val"));
  const int kConditionSetId = 1;
  URLMatcherConditionSet::Vector insert;
  insert.push_back(make_scoped_refptr(
      new URLMatcherConditionSet(kConditionSetId, conditions)));
  matcher.AddConditionSets(insert);
  EXPECT_EQ(0u, matcher.MatchURL(url).size());
}

}  // namespace url_matcher

/* [<][>][^][v][top][bottom][index][help] */