Home | History | Annotate | Download | only in search_engines
      1 // Copyright (c) 2012 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 "base/file_util.h"
      6 #include "base/logging.h"
      7 #include "base/path_service.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "chrome/browser/search_engines/template_url.h"
     10 #include "chrome/browser/search_engines/template_url_parser.h"
     11 #include "chrome/common/chrome_paths.h"
     12 #include "components/search_engines/search_terms_data.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 using base::ASCIIToUTF16;
     16 
     17 // ParamFilterImpl ------------------------------------------------------------
     18 
     19 // Filters any param which as an occurrence of name_str_ in its name or an
     20 // occurrence of value_str_ in its value.
     21 class ParamFilterImpl : public TemplateURLParser::ParameterFilter {
     22  public:
     23   ParamFilterImpl(std::string name_str, std::string value_str);
     24   virtual ~ParamFilterImpl();
     25 
     26   virtual bool KeepParameter(const std::string& key,
     27                              const std::string& value) OVERRIDE;
     28 
     29  private:
     30   std::string name_str_;
     31   std::string value_str_;
     32 
     33   DISALLOW_COPY_AND_ASSIGN(ParamFilterImpl);
     34 };
     35 
     36 ParamFilterImpl::ParamFilterImpl(std::string name_str, std::string value_str)
     37    : name_str_(name_str),
     38      value_str_(value_str) {
     39 }
     40 
     41 ParamFilterImpl::~ParamFilterImpl() {
     42 }
     43 
     44 bool ParamFilterImpl::KeepParameter(const std::string& key,
     45                                     const std::string& value) {
     46   return (name_str_.empty() || key.find(name_str_) == std::string::npos) &&
     47          (value_str_.empty() || value.find(value_str_) == std::string::npos);
     48 }
     49 
     50 
     51 // TemplateURLParserTest ------------------------------------------------------
     52 
     53 class TemplateURLParserTest : public testing::Test {
     54  protected:
     55   TemplateURLParserTest();
     56   virtual ~TemplateURLParserTest();
     57 
     58   virtual void SetUp() OVERRIDE;
     59 
     60   bool is_disabled() const;
     61 
     62   // Parses the OpenSearch description document at file_name (relative to the
     63   // data dir). The TemplateURL is placed in |template_url_|.
     64   void ParseFile(const std::string& file_name,
     65                  TemplateURLParser::ParameterFilter* filter);
     66 
     67   // ParseFile parses the results into this template_url.
     68   scoped_ptr<TemplateURL> template_url_;
     69 
     70  private:
     71   base::FilePath full_path_;
     72 };
     73 
     74 TemplateURLParserTest::TemplateURLParserTest() {
     75 }
     76 
     77 TemplateURLParserTest::~TemplateURLParserTest() {
     78 }
     79 
     80 void TemplateURLParserTest::SetUp() {
     81   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &full_path_));
     82   full_path_ = full_path_.AppendASCII("osdd");
     83   if (!base::PathExists(full_path_)) {
     84     LOG(ERROR) <<
     85         "This test can't be run without some non-redistributable data";
     86     full_path_ = base::FilePath();
     87   }
     88 }
     89 
     90 bool TemplateURLParserTest::is_disabled() const {
     91   return full_path_.empty();
     92 }
     93 
     94 void TemplateURLParserTest::ParseFile(
     95     const std::string& file_name,
     96     TemplateURLParser::ParameterFilter* filter) {
     97   base::FilePath full_path;
     98   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &full_path));
     99   full_path = full_path.AppendASCII("osdd");
    100   full_path = full_path.AppendASCII(file_name);
    101   ASSERT_TRUE(base::PathExists(full_path));
    102 
    103   std::string contents;
    104   ASSERT_TRUE(base::ReadFileToString(full_path, &contents));
    105   template_url_.reset(TemplateURLParser::Parse(NULL, false, contents.data(),
    106                                                contents.length(), filter));
    107 }
    108 
    109 
    110 // Actual tests ---------------------------------------------------------------
    111 
    112 TEST_F(TemplateURLParserTest, FailOnBogusURL) {
    113   if (is_disabled())
    114     return;
    115   ASSERT_NO_FATAL_FAILURE(ParseFile("bogus.xml", NULL));
    116   EXPECT_FALSE(template_url_.get());
    117 }
    118 
    119 TEST_F(TemplateURLParserTest, PassOnHTTPS) {
    120   if (is_disabled())
    121     return;
    122   ASSERT_NO_FATAL_FAILURE(ParseFile("https.xml", NULL));
    123   EXPECT_TRUE(template_url_.get());
    124 }
    125 
    126 TEST_F(TemplateURLParserTest, FailOnPost) {
    127   if (is_disabled())
    128     return;
    129   ASSERT_NO_FATAL_FAILURE(ParseFile("post.xml", NULL));
    130   EXPECT_FALSE(template_url_.get());
    131 }
    132 
    133 TEST_F(TemplateURLParserTest, TestDictionary) {
    134   if (is_disabled())
    135     return;
    136   ASSERT_NO_FATAL_FAILURE(ParseFile("dictionary.xml", NULL));
    137   ASSERT_TRUE(template_url_.get());
    138   EXPECT_EQ(ASCIIToUTF16("Dictionary.com"), template_url_->short_name());
    139   EXPECT_EQ(GURL("http://cache.lexico.com/g/d/favicon.ico"),
    140             template_url_->favicon_url());
    141   EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
    142   EXPECT_EQ("http://dictionary.reference.com/browse/{searchTerms}?r=75",
    143             template_url_->url());
    144 }
    145 
    146 TEST_F(TemplateURLParserTest, TestMSDN) {
    147   if (is_disabled())
    148     return;
    149   ASSERT_NO_FATAL_FAILURE(ParseFile("msdn.xml", NULL));
    150   ASSERT_TRUE(template_url_.get());
    151   EXPECT_EQ(ASCIIToUTF16("Search \" MSDN"), template_url_->short_name());
    152   EXPECT_EQ(GURL("http://search.msdn.microsoft.com/search/favicon.ico"),
    153             template_url_->favicon_url());
    154   EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
    155   EXPECT_EQ("http://search.msdn.microsoft.com/search/default.aspx?"
    156             "Query={searchTerms}&brand=msdn&locale=en-US",
    157             template_url_->url());
    158 }
    159 
    160 TEST_F(TemplateURLParserTest, TestWikipedia) {
    161   if (is_disabled())
    162     return;
    163   ASSERT_NO_FATAL_FAILURE(ParseFile("wikipedia.xml", NULL));
    164   ASSERT_TRUE(template_url_.get());
    165   EXPECT_EQ(ASCIIToUTF16("Wikipedia (English)"), template_url_->short_name());
    166   EXPECT_EQ(GURL("http://en.wikipedia.org/favicon.ico"),
    167             template_url_->favicon_url());
    168   EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
    169   EXPECT_EQ("http://en.wikipedia.org/w/index.php?"
    170             "title=Special:Search&search={searchTerms}",
    171             template_url_->url());
    172   EXPECT_TRUE(template_url_->suggestions_url_ref().SupportsReplacement(
    173       SearchTermsData()));
    174   EXPECT_EQ("http://en.wikipedia.org/w/api.php?"
    175             "action=opensearch&search={searchTerms}",
    176             template_url_->suggestions_url());
    177   ASSERT_EQ(2U, template_url_->input_encodings().size());
    178   EXPECT_EQ("UTF-8", template_url_->input_encodings()[0]);
    179   EXPECT_EQ("Shift_JIS", template_url_->input_encodings()[1]);
    180 }
    181 
    182 TEST_F(TemplateURLParserTest, NoCrashOnEmptyAttributes) {
    183   if (is_disabled())
    184     return;
    185   ASSERT_NO_FATAL_FAILURE(ParseFile("url_with_no_attributes.xml", NULL));
    186 }
    187 
    188 TEST_F(TemplateURLParserTest, TestFirefoxEbay) {
    189   if (is_disabled())
    190     return;
    191   // This file uses the Parameter extension
    192   // (see http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0)
    193   ParamFilterImpl filter("ebay", "ebay");
    194   ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_ebay.xml", &filter));
    195   ASSERT_TRUE(template_url_.get());
    196   EXPECT_EQ(ASCIIToUTF16("eBay"), template_url_->short_name());
    197   EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
    198   EXPECT_EQ("http://search.ebay.com/search/search.dll?query={searchTerms}&"
    199             "MfcISAPICommand=GetResult&ht=1&srchdesc=n&maxRecordsReturned=300&"
    200             "maxRecordsPerPage=50&SortProperty=MetaEndSort",
    201             template_url_->url());
    202   ASSERT_EQ(1U, template_url_->input_encodings().size());
    203   EXPECT_EQ("ISO-8859-1", template_url_->input_encodings()[0]);
    204   EXPECT_EQ(GURL("http://search.ebay.com/favicon.ico"),
    205             template_url_->favicon_url());
    206 }
    207 
    208 TEST_F(TemplateURLParserTest, TestFirefoxWebster) {
    209   if (is_disabled())
    210     return;
    211   // This XML file uses a namespace.
    212   ParamFilterImpl filter(std::string(), "Mozilla");
    213   ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_webster.xml", &filter));
    214   ASSERT_TRUE(template_url_.get());
    215   EXPECT_EQ(ASCIIToUTF16("Webster"), template_url_->short_name());
    216   EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
    217   EXPECT_EQ("http://www.webster.com/cgi-bin/dictionary?va={searchTerms}",
    218             template_url_->url());
    219   ASSERT_EQ(1U, template_url_->input_encodings().size());
    220   EXPECT_EQ("ISO-8859-1", template_url_->input_encodings()[0]);
    221   EXPECT_EQ(GURL("http://www.webster.com/favicon.ico"),
    222             template_url_->favicon_url());
    223 }
    224 
    225 TEST_F(TemplateURLParserTest, TestFirefoxYahoo) {
    226   if (is_disabled())
    227     return;
    228   // This XML file uses a namespace.
    229   ParamFilterImpl filter(std::string(), "Mozilla");
    230   ASSERT_NO_FATAL_FAILURE(ParseFile("firefox_yahoo.xml", &filter));
    231   ASSERT_TRUE(template_url_.get());
    232   EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_->short_name());
    233   EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
    234   EXPECT_EQ("http://ff.search.yahoo.com/gossip?"
    235             "output=fxjson&command={searchTerms}",
    236             template_url_->suggestions_url());
    237   EXPECT_EQ("http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8",
    238             template_url_->url());
    239   ASSERT_EQ(1U, template_url_->input_encodings().size());
    240   EXPECT_EQ("UTF-8", template_url_->input_encodings()[0]);
    241   EXPECT_EQ(GURL("http://search.yahoo.com/favicon.ico"),
    242             template_url_->favicon_url());
    243 }
    244 
    245 // Make sure we ignore POST suggestions (this is the same XML file as
    246 // firefox_yahoo.xml, the suggestion method was just changed to POST).
    247 TEST_F(TemplateURLParserTest, TestPostSuggestion) {
    248   if (is_disabled())
    249     return;
    250   // This XML file uses a namespace.
    251   ParamFilterImpl filter(std::string(), "Mozilla");
    252   ASSERT_NO_FATAL_FAILURE(ParseFile("post_suggestion.xml", &filter));
    253   ASSERT_TRUE(template_url_.get());
    254   EXPECT_EQ(ASCIIToUTF16("Yahoo"), template_url_->short_name());
    255   EXPECT_TRUE(template_url_->url_ref().SupportsReplacement(SearchTermsData()));
    256   EXPECT_TRUE(template_url_->suggestions_url().empty());
    257   EXPECT_EQ("http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8",
    258             template_url_->url());
    259   ASSERT_EQ(1U, template_url_->input_encodings().size());
    260   EXPECT_EQ("UTF-8", template_url_->input_encodings()[0]);
    261   EXPECT_EQ(GURL("http://search.yahoo.com/favicon.ico"),
    262             template_url_->favicon_url());
    263 }
    264