Home | History | Annotate | Download | only in autocomplete
      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/basictypes.h"
      6 #include "base/message_loop/message_loop.h"
      7 #include "base/strings/utf_string_conversions.h"
      8 #include "chrome/browser/autocomplete/autocomplete_match.h"
      9 #include "chrome/browser/autocomplete/extension_app_provider.h"
     10 #include "chrome/browser/history/history_service.h"
     11 #include "chrome/browser/history/history_service_factory.h"
     12 #include "chrome/browser/history/url_database.h"
     13 #include "chrome/test/base/testing_profile.h"
     14 #include "content/public/test/test_browser_thread.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 class ExtensionAppProviderTest : public testing::Test {
     18  protected:
     19   struct test_data {
     20     const base::string16 input;
     21     const size_t num_results;
     22     const GURL output[3];
     23   };
     24 
     25   ExtensionAppProviderTest()
     26       : ui_thread_(content::BrowserThread::UI, &message_loop_),
     27         history_service_(NULL) { }
     28   virtual ~ExtensionAppProviderTest() { }
     29 
     30   virtual void SetUp() OVERRIDE;
     31 
     32   void RunTest(test_data* keyword_cases,
     33                int num_cases);
     34 
     35  protected:
     36   base::MessageLoopForUI message_loop_;
     37   content::TestBrowserThread ui_thread_;
     38   scoped_refptr<ExtensionAppProvider> app_provider_;
     39   scoped_ptr<TestingProfile> profile_;
     40   HistoryService* history_service_;
     41 };
     42 
     43 void ExtensionAppProviderTest::SetUp() {
     44   profile_.reset(new TestingProfile());
     45   ASSERT_TRUE(profile_->CreateHistoryService(true, false));
     46   profile_->BlockUntilHistoryProcessesPendingRequests();
     47   history_service_ =
     48       HistoryServiceFactory::GetForProfile(profile_.get(),
     49                                            Profile::EXPLICIT_ACCESS);
     50 
     51   app_provider_ = new ExtensionAppProvider(NULL, profile_.get());
     52 
     53   struct TestExtensionApp {
     54     const char* app_name;
     55     const char* launch_url;
     56     bool should_match_against_launch_url;
     57     const char* title;
     58     int typed_count;
     59   } kExtensionApps[] = {
     60     {"COYB", "http://asdf/",            true,  "COYB", 7},
     61     {"NSNO", "http://fdsa/",            true,  "NSNO", 2},
     62     {"APPP", "chrome-extension://xyz/", false, "APPP", 2},
     63   };
     64 
     65   history::URLDatabase* url_db = history_service_->InMemoryDatabase();
     66 
     67   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExtensionApps); ++i) {
     68     // Populate the Extension Apps list.
     69     ExtensionAppProvider::ExtensionApp extension_app = {
     70       ASCIIToUTF16(kExtensionApps[i].app_name),
     71       ASCIIToUTF16(kExtensionApps[i].launch_url),
     72       kExtensionApps[i].should_match_against_launch_url
     73     };
     74     app_provider_->AddExtensionAppForTesting(extension_app);
     75 
     76     // Populate the InMemoryDatabase.
     77     history::URLRow info(GURL(kExtensionApps[i].launch_url));
     78     info.set_title(UTF8ToUTF16(kExtensionApps[i].title));
     79     info.set_typed_count(kExtensionApps[i].typed_count);
     80     url_db->AddURL(info);
     81   }
     82 }
     83 
     84 void ExtensionAppProviderTest::RunTest(
     85     test_data* keyword_cases,
     86     int num_cases) {
     87   ACMatches matches;
     88   for (int i = 0; i < num_cases; ++i) {
     89     AutocompleteInput input(keyword_cases[i].input, base::string16::npos,
     90                             base::string16(), GURL(),
     91                             AutocompleteInput::INVALID_SPEC, true,
     92                             false, true, AutocompleteInput::ALL_MATCHES);
     93     app_provider_->Start(input, false);
     94     EXPECT_TRUE(app_provider_->done());
     95     matches = app_provider_->matches();
     96     EXPECT_EQ(keyword_cases[i].num_results, matches.size())
     97         << ASCIIToUTF16("Input was: ") + keyword_cases[i].input;
     98     if (matches.size() == keyword_cases[i].num_results) {
     99       for (size_t j = 0; j < keyword_cases[i].num_results; ++j)
    100         EXPECT_EQ(keyword_cases[i].output[j], matches[j].destination_url);
    101     }
    102   }
    103 }
    104 
    105 TEST_F(ExtensionAppProviderTest, BasicMatching) {
    106   test_data edit_cases[] = {
    107     // Searching for a nonexistent value should give nothing.
    108     {ASCIIToUTF16("Not Found"),       0, { GURL() }},
    109 
    110     // The letter 'o' appears in both extension apps.
    111     {ASCIIToUTF16("o"),               2, { GURL("http://asdf/"),
    112                                            GURL("http://fdsa/") }},
    113     // The string 'co' appears in one extension app.
    114     {ASCIIToUTF16("co"),              1, { GURL("http://asdf/") }},
    115     // Try with URL matching.
    116     {ASCIIToUTF16("http://asdf/"),    1, { GURL("http://asdf/") }},
    117     {ASCIIToUTF16("http://fdsa/"),    1, { GURL("http://fdsa/") }},
    118 
    119     // "xyz" appears in a launch URL, but we're not matching against it.
    120     {ASCIIToUTF16("xyz"),             0, { GURL() }},
    121 
    122     // But it should be matcheable by title.
    123     {ASCIIToUTF16("APPP"),            1, { GURL("chrome-extension://xyz/") }},
    124 
    125   };
    126 
    127   RunTest(edit_cases, ARRAYSIZE_UNSAFE(edit_cases));
    128 }
    129 
    130 TEST_F(ExtensionAppProviderTest, CreateMatchSanitize) {
    131   struct TestData {
    132     const char* name;
    133     const char* match_contents;
    134   } cases[] = {
    135     { "Test", "Test" },
    136     { "Test \n Test", "Test  Test" },
    137     { "Test\r\t\nTest", "TestTest" },
    138   };
    139 
    140   AutocompleteInput input(ASCIIToUTF16("Test"), base::string16::npos,
    141                           base::string16(), GURL(),
    142                           AutocompleteInput::INVALID_SPEC, true, true,
    143                           true, AutocompleteInput::BEST_MATCH);
    144   base::string16 url(ASCIIToUTF16("http://example.com"));
    145   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    146     ExtensionAppProvider::ExtensionApp extension_app =
    147         {ASCIIToUTF16(cases[i].name), url, true};
    148     AutocompleteMatch match =
    149         app_provider_->CreateAutocompleteMatch(input,
    150                                                extension_app,
    151                                                0,
    152                                                base::string16::npos);
    153     EXPECT_EQ(ASCIIToUTF16(cases[i].match_contents), match.contents);
    154   }
    155 }
    156