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 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, string16::npos, string16(),
     90                             GURL(), AutocompleteInput::INVALID_SPEC, true,
     91                             false, true, AutocompleteInput::ALL_MATCHES);
     92     app_provider_->Start(input, false);
     93     EXPECT_TRUE(app_provider_->done());
     94     matches = app_provider_->matches();
     95     EXPECT_EQ(keyword_cases[i].num_results, matches.size())
     96         << ASCIIToUTF16("Input was: ") + keyword_cases[i].input;
     97     if (matches.size() == keyword_cases[i].num_results) {
     98       for (size_t j = 0; j < keyword_cases[i].num_results; ++j)
     99         EXPECT_EQ(keyword_cases[i].output[j], matches[j].destination_url);
    100     }
    101   }
    102 }
    103 
    104 TEST_F(ExtensionAppProviderTest, BasicMatching) {
    105   test_data edit_cases[] = {
    106     // Searching for a nonexistent value should give nothing.
    107     {ASCIIToUTF16("Not Found"),       0, { GURL() }},
    108 
    109     // The letter 'o' appears in both extension apps.
    110     {ASCIIToUTF16("o"),               2, { GURL("http://asdf/"),
    111                                            GURL("http://fdsa/") }},
    112     // The string 'co' appears in one extension app.
    113     {ASCIIToUTF16("co"),              1, { GURL("http://asdf/") }},
    114     // Try with URL matching.
    115     {ASCIIToUTF16("http://asdf/"),    1, { GURL("http://asdf/") }},
    116     {ASCIIToUTF16("http://fdsa/"),    1, { GURL("http://fdsa/") }},
    117 
    118     // "xyz" appears in a launch URL, but we're not matching against it.
    119     {ASCIIToUTF16("xyz"),             0, { GURL() }},
    120 
    121     // But it should be matcheable by title.
    122     {ASCIIToUTF16("APPP"),            1, { GURL("chrome-extension://xyz/") }},
    123 
    124   };
    125 
    126   RunTest(edit_cases, ARRAYSIZE_UNSAFE(edit_cases));
    127 }
    128 
    129 TEST_F(ExtensionAppProviderTest, CreateMatchSanitize) {
    130   struct TestData {
    131     const char* name;
    132     const char* match_contents;
    133   } cases[] = {
    134     { "Test", "Test" },
    135     { "Test \n Test", "Test  Test" },
    136     { "Test\r\t\nTest", "TestTest" },
    137   };
    138 
    139   AutocompleteInput input(ASCIIToUTF16("Test"), string16::npos, string16(),
    140                           GURL(), AutocompleteInput::INVALID_SPEC, true, true,
    141                           true, AutocompleteInput::BEST_MATCH);
    142   string16 url(ASCIIToUTF16("http://example.com"));
    143   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    144     ExtensionAppProvider::ExtensionApp extension_app =
    145         {ASCIIToUTF16(cases[i].name), url, true};
    146     AutocompleteMatch match =
    147         app_provider_->CreateAutocompleteMatch(input,
    148                                                extension_app,
    149                                                0,
    150                                                string16::npos);
    151     EXPECT_EQ(ASCIIToUTF16(cases[i].match_contents), match.contents);
    152   }
    153 }
    154