blob: 61d984f75496f96e9c543851e0d146a8e5e4b113 [file] [log] [blame]
// Copyright (c) 2012 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 "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/string16.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/keyword_provider.h"
#include "chrome/browser/autocomplete/search_provider.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "testing/gtest/include/gtest/gtest.h"
static std::ostream& operator<<(std::ostream& os,
const AutocompleteResult::const_iterator& it) {
return os << static_cast<const AutocompleteMatch*>(&(*it));
}
namespace {
const size_t kResultsPerProvider = 3;
}
// Autocomplete provider that provides known results. Note that this is
// refcounted so that it can also be a task on the message loop.
class TestProvider : public AutocompleteProvider {
public:
TestProvider(int relevance, const string16& prefix)
: AutocompleteProvider(NULL, NULL, ""),
relevance_(relevance),
prefix_(prefix) {
}
virtual void Start(const AutocompleteInput& input,
bool minimal_changes);
void set_listener(ACProviderListener* listener) {
listener_ = listener;
}
private:
~TestProvider() {}
void Run();
void AddResults(int start_at, int num);
int relevance_;
const string16 prefix_;
};
void TestProvider::Start(const AutocompleteInput& input,
bool minimal_changes) {
if (minimal_changes)
return;
matches_.clear();
// Generate one result synchronously, the rest later.
AddResults(0, 1);
if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) {
done_ = false;
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&TestProvider::Run,
this));
}
}
void TestProvider::Run() {
DCHECK_GT(kResultsPerProvider, 0U);
AddResults(1, kResultsPerProvider);
done_ = true;
DCHECK(listener_);
listener_->OnProviderUpdate(true);
}
void TestProvider::AddResults(int start_at, int num) {
for (int i = start_at; i < num; i++) {
AutocompleteMatch match(this, relevance_ - i, false,
AutocompleteMatch::URL_WHAT_YOU_TYPED);
match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i));
match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit));
match.contents = match.fill_into_edit;
match.contents_class.push_back(
ACMatchClassification(0, ACMatchClassification::NONE));
match.description = match.fill_into_edit;
match.description_class.push_back(
ACMatchClassification(0, ACMatchClassification::NONE));
matches_.push_back(match);
}
}
class AutocompleteProviderTest : public testing::Test,
public content::NotificationObserver {
protected:
struct KeywordTestData {
const string16 fill_into_edit;
const string16 keyword;
const bool expected_keyword_result;
};
protected:
void ResetControllerWithTestProviders(bool same_destinations);
// Runs a query on the input "a", and makes sure both providers' input is
// properly collected.
void RunTest();
void RunRedundantKeywordTest(const KeywordTestData* match_data, size_t size);
void RunQuery(const string16 query);
void ResetControllerWithTestProvidersWithKeywordAndSearchProviders();
void ResetControllerWithKeywordProvider();
void RunExactKeymatchTest(bool allow_exact_keyword_match);
// These providers are owned by the controller once it's created.
ACProviders providers_;
AutocompleteResult result_;
scoped_ptr<AutocompleteController> controller_;
private:
// content::NotificationObserver
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details);
MessageLoopForUI message_loop_;
content::NotificationRegistrar registrar_;
TestingProfile profile_;
};
void AutocompleteProviderTest::ResetControllerWithTestProviders(
bool same_destinations) {
// Forget about any existing providers. The controller owns them and will
// Release() them below, when we delete it during the call to reset().
providers_.clear();
// Construct two new providers, with either the same or different prefixes.
TestProvider* providerA = new TestProvider(kResultsPerProvider,
ASCIIToUTF16("http://a"));
providerA->AddRef();
providers_.push_back(providerA);
TestProvider* providerB = new TestProvider(kResultsPerProvider * 2,
same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b"));
providerB->AddRef();
providers_.push_back(providerB);
// Reset the controller to contain our new providers.
AutocompleteController* controller =
new AutocompleteController(providers_, &profile_);
controller_.reset(controller);
providerA->set_listener(controller);
providerB->set_listener(controller);
// The providers don't complete synchronously, so listen for "result updated"
// notifications.
registrar_.Add(this,
chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
content::Source<AutocompleteController>(controller));
}
void AutocompleteProviderTest::
ResetControllerWithTestProvidersWithKeywordAndSearchProviders() {
TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile_, &TemplateURLServiceFactory::BuildInstanceFor);
// Reset the default TemplateURL.
TemplateURLData data;
data.SetURL("http://defaultturl/{searchTerms}");
TemplateURL* default_t_url = new TemplateURL(&profile_, data);
TemplateURLService* turl_model =
TemplateURLServiceFactory::GetForProfile(&profile_);
turl_model->Add(default_t_url);
turl_model->SetDefaultSearchProvider(default_t_url);
TemplateURLID default_provider_id = default_t_url->id();
ASSERT_NE(0, default_provider_id);
// Create another TemplateURL for KeywordProvider.
data.short_name = ASCIIToUTF16("k");
data.SetKeyword(ASCIIToUTF16("k"));
data.SetURL("http://keyword/{searchTerms}");
TemplateURL* keyword_t_url = new TemplateURL(&profile_, data);
turl_model->Add(keyword_t_url);
ASSERT_NE(0, keyword_t_url->id());
// Forget about any existing providers. The controller owns them and will
// Release() them below, when we delete it during the call to reset().
providers_.clear();
// Create both a keyword and search provider, and add them in that order.
// (Order is important; see comments in RunExactKeymatchTest().)
AutocompleteProvider* keyword_provider = new KeywordProvider(NULL, &profile_);
keyword_provider->AddRef();
providers_.push_back(keyword_provider);
AutocompleteProvider* search_provider = new SearchProvider(NULL, &profile_);
search_provider->AddRef();
providers_.push_back(search_provider);
controller_.reset(new AutocompleteController(providers_, &profile_));
}
void AutocompleteProviderTest::
ResetControllerWithKeywordProvider() {
TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile_, &TemplateURLServiceFactory::BuildInstanceFor);
TemplateURLService* turl_model =
TemplateURLServiceFactory::GetForProfile(&profile_);
// Create a TemplateURL for KeywordProvider.
TemplateURLData data;
data.short_name = ASCIIToUTF16("foo.com");
data.SetKeyword(ASCIIToUTF16("foo.com"));
data.SetURL("http://foo.com/{searchTerms}");
TemplateURL* keyword_t_url = new TemplateURL(&profile_, data);
turl_model->Add(keyword_t_url);
ASSERT_NE(0, keyword_t_url->id());
// Create another TemplateURL for KeywordProvider.
data.short_name = ASCIIToUTF16("bar.com");
data.SetKeyword(ASCIIToUTF16("bar.com"));
data.SetURL("http://bar.com/{searchTerms}");
keyword_t_url = new TemplateURL(&profile_, data);
turl_model->Add(keyword_t_url);
ASSERT_NE(0, keyword_t_url->id());
// Forget about any existing providers. The controller owns them and will
// Release() them below, when we delete it during the call to reset().
providers_.clear();
// Create both a keyword and search provider, and add them in that order.
// (Order is important; see comments in RunExactKeymatchTest().)
KeywordProvider* keyword_provider = new KeywordProvider(NULL, &profile_);
keyword_provider->AddRef();
providers_.push_back(keyword_provider);
AutocompleteController* controller =
new AutocompleteController(providers_, &profile_);
controller->set_keyword_provider(keyword_provider);
controller_.reset(controller);
}
void AutocompleteProviderTest::RunTest() {
RunQuery(ASCIIToUTF16("a"));
}
void AutocompleteProviderTest::RunRedundantKeywordTest(
const KeywordTestData* match_data,
size_t size) {
ACMatches matches;
for (size_t i = 0; i < size; ++i) {
AutocompleteMatch match;
match.fill_into_edit = match_data[i].fill_into_edit;
match.transition = content::PAGE_TRANSITION_KEYWORD;
match.keyword = match_data[i].keyword;
matches.push_back(match);
}
AutocompleteResult result;
result.AppendMatches(matches);
controller_->UpdateAssociatedKeywords(&result);
for (size_t j = 0; j < result.size(); ++j) {
EXPECT_EQ(match_data[j].expected_keyword_result,
result.match_at(j).associated_keyword.get() != NULL);
}
}
void AutocompleteProviderTest::RunQuery(const string16 query) {
result_.Reset();
controller_->Start(query, string16(), true, false, true,
AutocompleteInput::ALL_MATCHES);
if (!controller_->done())
// The message loop will terminate when all autocomplete input has been
// collected.
MessageLoop::current()->Run();
}
void AutocompleteProviderTest::RunExactKeymatchTest(
bool allow_exact_keyword_match) {
// Send the controller input which exactly matches the keyword provider we
// created in ResetControllerWithKeywordAndSearchProviders(). The default
// match should thus be a keyword match iff |allow_exact_keyword_match| is
// true.
controller_->Start(ASCIIToUTF16("k test"), string16(), true, false,
allow_exact_keyword_match,
AutocompleteInput::SYNCHRONOUS_MATCHES);
EXPECT_TRUE(controller_->done());
// ResetControllerWithKeywordAndSearchProviders() adds the keyword provider
// first, then the search provider. So if the default match is a keyword
// match, it will come from provider 0, otherwise from provider 1.
EXPECT_EQ(providers_[allow_exact_keyword_match ? 0 : 1],
controller_->result().default_match()->provider);
}
void AutocompleteProviderTest::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (controller_->done()) {
result_.CopyFrom(controller_->result());
MessageLoop::current()->Quit();
}
}
// Tests that the default selection is set properly when updating results.
TEST_F(AutocompleteProviderTest, Query) {
ResetControllerWithTestProviders(false);
RunTest();
// Make sure the default match gets set to the highest relevance match. The
// highest relevance matches should come from the second provider.
EXPECT_EQ(kResultsPerProvider * 2, result_.size()); // two providers
ASSERT_NE(result_.end(), result_.default_match());
EXPECT_EQ(providers_[1], result_.default_match()->provider);
}
TEST_F(AutocompleteProviderTest, RemoveDuplicates) {
ResetControllerWithTestProviders(true);
RunTest();
// Make sure all the first provider's results were eliminated by the second
// provider's.
EXPECT_EQ(kResultsPerProvider, result_.size());
for (AutocompleteResult::const_iterator i(result_.begin());
i != result_.end(); ++i)
EXPECT_EQ(providers_[1], i->provider);
}
TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) {
ResetControllerWithTestProvidersWithKeywordAndSearchProviders();
RunExactKeymatchTest(true);
RunExactKeymatchTest(false);
}
// Test that redundant associated keywords are removed.
TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) {
ResetControllerWithKeywordProvider();
// Get the controller's internal members in the correct state.
RunQuery(ASCIIToUTF16("fo"));
{
KeywordTestData duplicate_url[] = {
{ ASCIIToUTF16("fo"), string16(), false },
{ ASCIIToUTF16("foo.com"), string16(), true },
{ ASCIIToUTF16("foo.com"), string16(), false }
};
SCOPED_TRACE("Duplicate url");
RunRedundantKeywordTest(duplicate_url, ARRAYSIZE_UNSAFE(duplicate_url));
}
{
KeywordTestData keyword_match[] = {
{ ASCIIToUTF16("foo.com"), ASCIIToUTF16("foo.com"), false },
{ ASCIIToUTF16("foo.com"), string16(), false }
};
SCOPED_TRACE("Duplicate url with keyword match");
RunRedundantKeywordTest(keyword_match, ARRAYSIZE_UNSAFE(keyword_match));
}
{
KeywordTestData multiple_keyword[] = {
{ ASCIIToUTF16("fo"), string16(), false },
{ ASCIIToUTF16("foo.com"), string16(), true },
{ ASCIIToUTF16("foo.com"), string16(), false },
{ ASCIIToUTF16("bar.com"), string16(), true },
};
SCOPED_TRACE("Duplicate url with multiple keywords");
RunRedundantKeywordTest(multiple_keyword,
ARRAYSIZE_UNSAFE(multiple_keyword));
}
}
typedef testing::Test AutocompleteTest;
TEST_F(AutocompleteTest, InputType) {
struct test_data {
const string16 input;
const AutocompleteInput::Type type;
} input_cases[] = {
{ string16(), AutocompleteInput::INVALID },
{ ASCIIToUTF16("?"), AutocompleteInput::FORCED_QUERY },
{ ASCIIToUTF16("?foo"), AutocompleteInput::FORCED_QUERY },
{ ASCIIToUTF16("?foo bar"), AutocompleteInput::FORCED_QUERY },
{ ASCIIToUTF16("?http://foo.com/bar"), AutocompleteInput::FORCED_QUERY },
{ ASCIIToUTF16("foo"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("localhost"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo.c"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("-foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo-.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo_.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo.-com"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo/"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo/bar"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo/bar/"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo/bar baz\\"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo.com/bar"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo;bar"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo/bar baz"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo bar.com"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo bar"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo+bar"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo+bar.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("\"foo:bar\""), AutocompleteInput::QUERY },
{ ASCIIToUTF16("link:foo.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo:81"), AutocompleteInput::URL },
{ ASCIIToUTF16("localhost:8080"), AutocompleteInput::URL },
{ ASCIIToUTF16("www.foo.com:81"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo.com:123456"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo.com:abc"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("1.2.3.4:abc"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("user@foo.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user@foo/z"), AutocompleteInput::URL },
{ ASCIIToUTF16("user@foo/z z"), AutocompleteInput::URL },
{ ASCIIToUTF16("user@foo.com/z"), AutocompleteInput::URL },
{ ASCIIToUTF16("user:pass@"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user:pass@!foo.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user:pass@foo"), AutocompleteInput::URL },
{ ASCIIToUTF16("user:pass@foo.c"), AutocompleteInput::URL },
{ ASCIIToUTF16("user:pass@foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("user:pass@foo.com:81"), AutocompleteInput::URL },
{ ASCIIToUTF16("user:pass@foo:81"), AutocompleteInput::URL },
{ ASCIIToUTF16("1.2"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("1.2/45"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("1.2:45"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user@1.2:45"), AutocompleteInput::URL },
{ ASCIIToUTF16("user@foo:45"), AutocompleteInput::URL },
{ ASCIIToUTF16("user:pass@1.2:45"), AutocompleteInput::URL },
{ ASCIIToUTF16("host?query"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("host#ref"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("host/path?query"), AutocompleteInput::URL },
{ ASCIIToUTF16("host/path#ref"), AutocompleteInput::URL },
{ ASCIIToUTF16("en.wikipedia.org/wiki/Jim Beam"), AutocompleteInput::URL },
// In Chrome itself, mailto: will get handled by ShellExecute, but in
// unittest mode, we don't have the data loaded in the external protocol
// handler to know this.
// { ASCIIToUTF16("mailto:abuse@foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("view-source:http://www.foo.com/"), AutocompleteInput::URL },
{ ASCIIToUTF16("javascript:alert(\"Hi there\");"), AutocompleteInput::URL },
#if defined(OS_WIN)
{ ASCIIToUTF16("C:\\Program Files"), AutocompleteInput::URL },
{ ASCIIToUTF16("\\\\Server\\Folder\\File"), AutocompleteInput::URL },
#endif // defined(OS_WIN)
{ ASCIIToUTF16("http:foo"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://foo"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://foo.c"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://foo_bar.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://foo/bar baz"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://-foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://foo-.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://foo_.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("http://foo.-com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("http://_foo_.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("http://foo.com:abc"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("http://foo.com:123456"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("http://1.2.3.4:abc"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("http:user@foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://user@foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http:user:pass@foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://user:pass@foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://1.2"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://1.2/45"), AutocompleteInput::URL },
{ ASCIIToUTF16("http:ps/2 games"), AutocompleteInput::URL },
{ ASCIIToUTF16("https://foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("127.0.0.1"), AutocompleteInput::URL },
{ ASCIIToUTF16("127.0.1"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("127.0.1/"), AutocompleteInput::URL },
{ ASCIIToUTF16("browser.tabs.closeButtons"), AutocompleteInput::UNKNOWN },
{ WideToUTF16(L"\u6d4b\u8bd5"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("[2001:]"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("[2001:dB8::1]"), AutocompleteInput::URL },
{ ASCIIToUTF16("192.168.0.256"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("[foo.com]"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("filesystem:http://a.com/t/bar"), AutocompleteInput::URL },
{ ASCIIToUTF16("filesystem:http:foo"), AutocompleteInput::URL },
{ ASCIIToUTF16("filesystem:file://"), AutocompleteInput::URL },
{ ASCIIToUTF16("filesystem:http"), AutocompleteInput::URL },
{ ASCIIToUTF16("filesystem:"), AutocompleteInput::URL },
{ ASCIIToUTF16("ftp:"), AutocompleteInput::URL },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) {
SCOPED_TRACE(input_cases[i].input);
AutocompleteInput input(input_cases[i].input, string16(), true, false,
true, AutocompleteInput::ALL_MATCHES);
EXPECT_EQ(input_cases[i].type, input.type());
}
}
TEST_F(AutocompleteTest, InputTypeWithDesiredTLD) {
struct test_data {
const string16 input;
const AutocompleteInput::Type type;
} input_cases[] = {
{ ASCIIToUTF16("401k"), AutocompleteInput::REQUESTED_URL },
{ ASCIIToUTF16("999999999999999"), AutocompleteInput::REQUESTED_URL },
{ ASCIIToUTF16("x@y"), AutocompleteInput::REQUESTED_URL },
{ ASCIIToUTF16("y/z z"), AutocompleteInput::REQUESTED_URL },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) {
SCOPED_TRACE(input_cases[i].input);
AutocompleteInput input(input_cases[i].input, ASCIIToUTF16("com"), true,
false, true, AutocompleteInput::ALL_MATCHES);
EXPECT_EQ(input_cases[i].type, input.type());
}
}
// This tests for a regression where certain input in the omnibox caused us to
// crash. As long as the test completes without crashing, we're fine.
TEST_F(AutocompleteTest, InputCrash) {
AutocompleteInput input(WideToUTF16(L"\uff65@s"), string16(), true, false,
true, AutocompleteInput::ALL_MATCHES);
}
// Test comparing matches relevance.
TEST(AutocompleteMatch, MoreRelevant) {
struct RelevantCases {
int r1;
int r2;
bool expected_result;
} cases[] = {
{ 10, 0, true },
{ 10, -5, true },
{ -5, 10, false },
{ 0, 10, false },
{ -10, -5, false },
{ -5, -10, true },
};
AutocompleteMatch m1(NULL, 0, false,
AutocompleteMatch::URL_WHAT_YOU_TYPED);
AutocompleteMatch m2(NULL, 0, false,
AutocompleteMatch::URL_WHAT_YOU_TYPED);
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
m1.relevance = cases[i].r1;
m2.relevance = cases[i].r2;
EXPECT_EQ(cases[i].expected_result,
AutocompleteMatch::MoreRelevant(m1, m2));
}
}
TEST(AutocompleteInput, ParseForEmphasizeComponent) {
using url_parse::Component;
Component kInvalidComponent(0, -1);
struct test_data {
const string16 input;
const Component scheme;
const Component host;
} input_cases[] = {
{ string16(), kInvalidComponent, kInvalidComponent },
{ ASCIIToUTF16("?"), kInvalidComponent, kInvalidComponent },
{ ASCIIToUTF16("?http://foo.com/bar"), kInvalidComponent,
kInvalidComponent },
{ ASCIIToUTF16("foo/bar baz"), kInvalidComponent, Component(0, 3) },
{ ASCIIToUTF16("http://foo/bar baz"), Component(0, 4), Component(7, 3) },
{ ASCIIToUTF16("link:foo.com"), Component(0, 4), kInvalidComponent },
{ ASCIIToUTF16("www.foo.com:81"), kInvalidComponent, Component(0, 11) },
{ WideToUTF16(L"\u6d4b\u8bd5"), kInvalidComponent, Component(0, 2) },
{ ASCIIToUTF16("view-source:http://www.foo.com/"), Component(12, 4),
Component(19, 11) },
{ ASCIIToUTF16("view-source:https://example.com/"),
Component(12, 5), Component(20, 11) },
{ ASCIIToUTF16("view-source:www.foo.com"), kInvalidComponent,
Component(12, 11) },
{ ASCIIToUTF16("view-source:"), Component(0, 11), kInvalidComponent },
{ ASCIIToUTF16("view-source:garbage"), kInvalidComponent,
Component(12, 7) },
{ ASCIIToUTF16("view-source:http://http://foo"), Component(12, 4),
Component(19, 4) },
{ ASCIIToUTF16("view-source:view-source:http://example.com/"),
Component(12, 11), kInvalidComponent }
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) {
SCOPED_TRACE(input_cases[i].input);
Component scheme, host;
AutocompleteInput::ParseForEmphasizeComponents(input_cases[i].input,
string16(),
&scheme,
&host);
AutocompleteInput input(input_cases[i].input, string16(), true, false,
true, AutocompleteInput::ALL_MATCHES);
EXPECT_EQ(input_cases[i].scheme.begin, scheme.begin);
EXPECT_EQ(input_cases[i].scheme.len, scheme.len);
EXPECT_EQ(input_cases[i].host.begin, host.begin);
EXPECT_EQ(input_cases[i].host.len, host.len);
}
}