summaryrefslogtreecommitdiffstats
path: root/chrome/browser/template_url_model_unittest.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/template_url_model_unittest.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/template_url_model_unittest.cc')
-rw-r--r--chrome/browser/template_url_model_unittest.cc641
1 files changed, 641 insertions, 0 deletions
diff --git a/chrome/browser/template_url_model_unittest.cc b/chrome/browser/template_url_model_unittest.cc
new file mode 100644
index 0000000..3af0c5c
--- /dev/null
+++ b/chrome/browser/template_url_model_unittest.cc
@@ -0,0 +1,641 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <windows.h>
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "chrome/browser/template_url.h"
+#include "chrome/browser/template_url_model.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/test/testing_profile.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// A Task used to coordinate when the database has finished processing
+// requests. See note in BlockTillServiceProcessesRequests for details.
+//
+// When Run() schedules a QuitTask on the message loop it was created with.
+class QuitTask2 : public Task {
+ public:
+ QuitTask2() : main_loop_(MessageLoop::current()) {}
+
+ virtual void Run() {
+ main_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+
+ private:
+ MessageLoop* main_loop_;
+};
+
+// Subclass the TestingProfile so that it can return a WebDataService.
+class TemplateURLModelTestingProfile : public TestingProfile {
+ public:
+ TemplateURLModelTestingProfile() : TestingProfile() { }
+
+ void SetUp() {
+ // Name a subdirectory of the temp directory.
+ ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
+ file_util::AppendToPath(&test_dir_, L"TemplateURLModelTest");
+
+ // Create a fresh, empty copy of this directory.
+ file_util::Delete(test_dir_, true);
+ CreateDirectory(test_dir_.c_str(), NULL);
+
+ std::wstring path = test_dir_;
+ file_util::AppendToPath(&path, L"TestDataService.db");
+ service_ = new WebDataService;
+ EXPECT_TRUE(service_->InitWithPath(path));
+ }
+
+ void TearDown() {
+ // Clean up the test directory.
+ service_->Shutdown();
+ ASSERT_TRUE(file_util::Delete(test_dir_, true));
+ ASSERT_FALSE(file_util::PathExists(test_dir_));
+ }
+
+ virtual WebDataService* GetWebDataService(ServiceAccessType access) {
+ return service_.get();
+ }
+
+ private:
+ scoped_refptr<WebDataService> service_;
+ std::wstring test_dir_;
+};
+
+// Trivial subclass of TemplateURLModel that records the last invocation of
+// SetKeywordSearchTermsForURL.
+class TestingTemplateURLModel : public TemplateURLModel {
+ public:
+ explicit TestingTemplateURLModel(Profile* profile)
+ : TemplateURLModel(profile) {
+ }
+
+ std::wstring GetAndClearSearchTerm() {
+ std::wstring search_term;
+ search_term.swap(search_term_);
+ return search_term;
+ }
+
+ protected:
+ virtual void SetKeywordSearchTermsForURL(const TemplateURL* t_url,
+ const GURL& url,
+ const std::wstring& term) {
+ search_term_ = term;
+ }
+
+ private:
+ std::wstring search_term_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(TestingTemplateURLModel);
+};
+
+class TemplateURLModelTest : public testing::Test,
+ public TemplateURLModelObserver {
+ public:
+ TemplateURLModelTest() : changed_count_(0) {
+ }
+
+ virtual void SetUp() {
+ profile_.reset(new TemplateURLModelTestingProfile());
+ profile_->SetUp();
+ model_.reset(new TestingTemplateURLModel(profile_.get()));
+ model_->AddObserver(this);
+ }
+
+ virtual void TearDown() {
+ profile_->TearDown();
+ delete TemplateURLRef::google_base_url_;
+ TemplateURLRef::google_base_url_ = NULL;
+ }
+
+ TemplateURL* AddKeywordWithDate(const std::wstring & keyword,
+ const std::wstring & url,
+ const std::wstring & short_name,
+ bool safe_for_autoreplace,
+ Time created_date) {
+ TemplateURL* template_url = new TemplateURL();
+ template_url->SetURL(url, 0, 0);
+ template_url->set_keyword(keyword);
+ template_url->set_short_name(short_name);
+ template_url->set_date_created(created_date);
+ template_url->set_safe_for_autoreplace(safe_for_autoreplace);
+ model_->Add(template_url);
+ EXPECT_NE(0, template_url->id());
+ return template_url;
+ }
+
+ virtual void OnTemplateURLModelChanged() {
+ changed_count_++;
+ }
+
+ void VerifyObserverCount(int expected_changed_count) {
+ ASSERT_EQ(expected_changed_count, changed_count_);
+ changed_count_ = 0;
+ }
+
+ // Blocks the caller until the service has finished servicing all pending
+ // requests.
+ void BlockTillServiceProcessesRequests() {
+ // Schedule a task on the background thread that is processed after all
+ // pending requests on the background thread.
+ profile_->GetWebDataService(Profile::EXPLICIT_ACCESS)->thread()->
+ message_loop()->PostTask(FROM_HERE, new QuitTask2());
+ // Run the current message loop. QuitTask2, when run, invokes Quit,
+ // which unblocks this.
+ MessageLoop::current()->Run();
+ }
+
+ // Makes sure the load was successful and sent the correct notification.
+ void VerifyLoad() {
+ ASSERT_FALSE(model_->loaded());
+ model_->Load();
+ BlockTillServiceProcessesRequests();
+ VerifyObserverCount(1);
+ changed_count_ = 0;
+ }
+
+ // Creates a new TemplateURLModel.
+ void ResetModel(bool verify_load) {
+ model_.reset(new TestingTemplateURLModel(profile_.get()));
+ model_->AddObserver(this);
+ changed_count_ = 0;
+ if (verify_load)
+ VerifyLoad();
+ }
+
+ // Verifies the two TemplateURLs are equal.
+ void AssertEquals(const TemplateURL& expected, const TemplateURL& actual) {
+ ASSERT_EQ(expected.url()->url(), actual.url()->url());
+ ASSERT_EQ(expected.keyword(), actual.keyword());
+ ASSERT_EQ(expected.short_name(), actual.short_name());
+ ASSERT_TRUE(expected.GetFavIconURL() == actual.GetFavIconURL());
+ ASSERT_EQ(expected.id(), actual.id());
+ ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
+ ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
+ ASSERT_TRUE(expected.date_created() == actual.date_created());
+ }
+
+ std::wstring GetAndClearSearchTerm() {
+ return model_->GetAndClearSearchTerm();
+ }
+
+ void SetGoogleBaseURL(const std::wstring& base_url) const {
+ delete TemplateURLRef::google_base_url_;
+ TemplateURLRef::google_base_url_ = new std::wstring(base_url);
+ }
+
+ scoped_ptr<TemplateURLModelTestingProfile> profile_;
+ scoped_ptr<TestingTemplateURLModel> model_;
+ int changed_count_;
+};
+
+TEST_F(TemplateURLModelTest, Load) {
+ VerifyLoad();
+}
+
+TEST_F(TemplateURLModelTest, AddUpdateRemove) {
+ // Add a new TemplateURL.
+ VerifyLoad();
+ const size_t initial_count = model_->GetTemplateURLs().size();
+
+ TemplateURL* t_url = new TemplateURL();
+ t_url->SetURL(L"http://www.google.com/foo/bar", 0, 0);
+ t_url->set_keyword(L"keyword");
+ t_url->set_short_name(L"google");
+ GURL favicon_url("http://favicon.url");
+ t_url->SetFavIconURL(favicon_url);
+ t_url->set_date_created(Time::FromTimeT(100));
+ t_url->set_safe_for_autoreplace(true);
+ model_->Add(t_url);
+ ASSERT_TRUE(model_->CanReplaceKeyword(L"keyword", std::wstring(), NULL));
+ VerifyObserverCount(1);
+ BlockTillServiceProcessesRequests();
+ // We need to clone as model takes ownership of TemplateURL and will
+ // delete it.
+ TemplateURL cloned_url(*t_url);
+ ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size());
+ ASSERT_TRUE(model_->GetTemplateURLForKeyword(t_url->keyword()) == t_url);
+ ASSERT_TRUE(t_url->date_created() == cloned_url.date_created());
+
+ // Reload the model to verify it was actually saved to the database.
+ ResetModel(true);
+ ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size());
+ const TemplateURL* loaded_url = model_->GetTemplateURLForKeyword(L"keyword");
+ ASSERT_TRUE(loaded_url != NULL);
+ AssertEquals(cloned_url, *loaded_url);
+ ASSERT_TRUE(model_->CanReplaceKeyword(L"keyword", std::wstring(), NULL));
+
+ // Mutate an element and verify it succeeded.
+ model_->ResetTemplateURL(loaded_url, L"a", L"b", L"c");
+ ASSERT_EQ(L"a", loaded_url->short_name());
+ ASSERT_EQ(L"b", loaded_url->keyword());
+ ASSERT_EQ(L"c", loaded_url->url()->url());
+ ASSERT_FALSE(loaded_url->safe_for_autoreplace());
+ ASSERT_TRUE(model_->CanReplaceKeyword(L"keyword", std::wstring(), NULL));
+ ASSERT_FALSE(model_->CanReplaceKeyword(L"b", std::wstring(), NULL));
+ cloned_url = *loaded_url;
+ BlockTillServiceProcessesRequests();
+ ResetModel(true);
+ ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size());
+ loaded_url = model_->GetTemplateURLForKeyword(L"b");
+ ASSERT_TRUE(loaded_url != NULL);
+ AssertEquals(cloned_url, *loaded_url);
+
+ // Remove an element and verify it succeeded.
+ model_->Remove(loaded_url);
+ VerifyObserverCount(1);
+ ResetModel(true);
+ ASSERT_EQ(initial_count, model_->GetTemplateURLs().size());
+ EXPECT_TRUE(model_->GetTemplateURLForKeyword(L"b") == NULL);
+}
+
+TEST_F(TemplateURLModelTest, GenerateKeyword) {
+ ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL(), true));
+ // Shouldn't generate keywords for https.
+ ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("https://blah"), true));
+ ASSERT_EQ(L"foo", TemplateURLModel::GenerateKeyword(GURL("http://foo"),
+ true));
+ // www. should be stripped.
+ ASSERT_EQ(L"foo", TemplateURLModel::GenerateKeyword(GURL("http://www.foo"),
+ true));
+ // Shouldn't generate keywords with paths, if autodetected.
+ ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"),
+ true));
+ ASSERT_EQ(L"blah", TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"),
+ false));
+ // FTP shouldn't generate a keyword.
+ ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("ftp://blah/"), true));
+ // Make sure we don't get a trailing /
+ ASSERT_EQ(L"blah", TemplateURLModel::GenerateKeyword(GURL("http://blah/"),
+ true));
+}
+
+TEST_F(TemplateURLModelTest, ClearBrowsingData_Keywords) {
+ Time now = Time::Now();
+ TimeDelta one_day = TimeDelta::FromDays(1);
+ Time month_ago = now - TimeDelta::FromDays(30);
+
+ // Nothing has been added.
+ EXPECT_EQ(0, model_->GetTemplateURLs().size());
+
+ // Create one with a 0 time.
+ AddKeywordWithDate(L"key1", L"http://foo1", L"name1", true, Time());
+ // Create one for now and +/- 1 day.
+ AddKeywordWithDate(L"key2", L"http://foo2", L"name2", true, now - one_day);
+ AddKeywordWithDate(L"key3", L"http://foo3", L"name3", true, now);
+ AddKeywordWithDate(L"key4", L"http://foo4", L"name4", true, now + one_day);
+ // Try the other three states.
+ AddKeywordWithDate(L"key5", L"http://foo5", L"name5", false, now);
+ AddKeywordWithDate(L"key6", L"http://foo6", L"name6", false, month_ago);
+
+ // We just added a few items, validate them.
+ EXPECT_EQ(6, model_->GetTemplateURLs().size());
+
+ // Try removing from current timestamp. This should delete the one in the
+ // future and one very recent one.
+ model_->RemoveAutoGeneratedSince(now);
+ EXPECT_EQ(4, model_->GetTemplateURLs().size());
+
+ // Try removing from two months ago. This should only delete items that are
+ // auto-generated.
+ model_->RemoveAutoGeneratedSince(now - TimeDelta::FromDays(60));
+ EXPECT_EQ(3, model_->GetTemplateURLs().size());
+
+ // Make sure the right values remain.
+ EXPECT_EQ(L"key1", model_->GetTemplateURLs()[0]->keyword());
+ EXPECT_TRUE(model_->GetTemplateURLs()[0]->safe_for_autoreplace());
+ EXPECT_EQ(0, model_->GetTemplateURLs()[0]->date_created().ToInternalValue());
+
+ EXPECT_EQ(L"key5", model_->GetTemplateURLs()[1]->keyword());
+ EXPECT_FALSE(model_->GetTemplateURLs()[1]->safe_for_autoreplace());
+ EXPECT_EQ(now.ToInternalValue(),
+ model_->GetTemplateURLs()[1]->date_created().ToInternalValue());
+
+ EXPECT_EQ(L"key6", model_->GetTemplateURLs()[2]->keyword());
+ EXPECT_FALSE(model_->GetTemplateURLs()[2]->safe_for_autoreplace());
+ EXPECT_EQ(month_ago.ToInternalValue(),
+ model_->GetTemplateURLs()[2]->date_created().ToInternalValue());
+
+ // Try removing from Time=0. This should delete one more.
+ model_->RemoveAutoGeneratedSince(Time());
+ EXPECT_EQ(2, model_->GetTemplateURLs().size());
+}
+
+TEST_F(TemplateURLModelTest, Reset) {
+ // Add a new TemplateURL.
+ VerifyLoad();
+ const size_t initial_count = model_->GetTemplateURLs().size();
+ TemplateURL* t_url = new TemplateURL();
+ t_url->SetURL(L"http://www.google.com/foo/bar", 0, 0);
+ t_url->set_keyword(L"keyword");
+ t_url->set_short_name(L"google");
+ GURL favicon_url("http://favicon.url");
+ t_url->SetFavIconURL(favicon_url);
+ t_url->set_date_created(Time::FromTimeT(100));
+ model_->Add(t_url);
+
+ VerifyObserverCount(1);
+ BlockTillServiceProcessesRequests();
+
+ // Reset the short name, keyword, url and make sure it takes.
+ const std::wstring new_short_name(L"a");
+ const std::wstring new_keyword(L"b");
+ const std::wstring new_url(L"c");
+ model_->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url);
+ ASSERT_EQ(new_short_name, t_url->short_name());
+ ASSERT_EQ(new_keyword, t_url->keyword());
+ ASSERT_EQ(new_url, t_url->url()->url());
+
+ // Make sure the mappings in the model were updated.
+ ASSERT_TRUE(model_->GetTemplateURLForKeyword(new_keyword) == t_url);
+ ASSERT_TRUE(model_->GetTemplateURLForKeyword(L"keyword") == NULL);
+
+ TemplateURL last_url = *t_url;
+
+ // Reload the model from the database and make sure the change took.
+ ResetModel(true);
+ t_url = NULL;
+ EXPECT_EQ(initial_count + 1, model_->GetTemplateURLs().size());
+ const TemplateURL* read_url = model_->GetTemplateURLForKeyword(new_keyword);
+ ASSERT_TRUE(read_url);
+ AssertEquals(last_url, *read_url);
+}
+
+TEST_F(TemplateURLModelTest, DefaultSearchProvider) {
+ // Add a new TemplateURL.
+ VerifyLoad();
+ const size_t initial_count = model_->GetTemplateURLs().size();
+ TemplateURL* t_url =
+ AddKeywordWithDate(L"key1", L"http://foo1", L"name1", true, Time());
+
+ changed_count_ = 0;
+ model_->SetDefaultSearchProvider(t_url);
+
+ ASSERT_EQ(t_url, model_->GetDefaultSearchProvider());
+
+ ASSERT_TRUE(t_url->safe_for_autoreplace());
+ ASSERT_TRUE(t_url->show_in_default_list());
+
+ // Setting the default search provider should have caused notification.
+ VerifyObserverCount(1);
+
+ BlockTillServiceProcessesRequests();
+
+ TemplateURL cloned_url = *t_url;
+
+ ResetModel(true);
+ t_url = NULL;
+
+ // Make sure when we reload we get a default search provider.
+ EXPECT_EQ(1 + initial_count, model_->GetTemplateURLs().size());
+ ASSERT_TRUE(model_->GetDefaultSearchProvider());
+ AssertEquals(cloned_url, *model_->GetDefaultSearchProvider());
+}
+
+TEST_F(TemplateURLModelTest, TemplateURLWithNoKeyword) {
+ VerifyLoad();
+
+ const size_t initial_count = model_->GetTemplateURLs().size();
+
+ AddKeywordWithDate(std::wstring(), L"http://foo1", L"name1", true, Time());
+
+ // We just added a few items, validate them.
+ ASSERT_EQ(initial_count + 1, model_->GetTemplateURLs().size());
+
+ // Reload the model from the database and make sure we get the url back.
+ ResetModel(true);
+
+ ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size());
+
+ bool found_keyword = false;
+ for (size_t i = 0; i < initial_count + 1; ++i) {
+ if (model_->GetTemplateURLs()[i]->keyword().empty()) {
+ found_keyword = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(found_keyword);
+}
+
+TEST_F(TemplateURLModelTest, CantReplaceWithSameKeyword) {
+ ASSERT_TRUE(model_->CanReplaceKeyword(L"foo", std::wstring(), NULL));
+ TemplateURL* t_url =
+ AddKeywordWithDate(L"foo", L"http://foo1", L"name1", true, Time());
+
+ // Can still replace, newly added template url is marked safe to replace.
+ ASSERT_TRUE(model_->CanReplaceKeyword(L"foo", L"http://foo2", NULL));
+
+ // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
+ // no longer be replaceable.
+ model_->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
+ t_url->url()->url());
+
+ ASSERT_FALSE(model_->CanReplaceKeyword(L"foo", L"http://foo2", NULL));
+}
+
+TEST_F(TemplateURLModelTest, CantReplaceWithSameHosts) {
+ ASSERT_TRUE(model_->CanReplaceKeyword(L"foo", L"http://foo.com", NULL));
+ TemplateURL* t_url =
+ AddKeywordWithDate(L"foo", L"http://foo.com", L"name1", true, Time());
+
+ // Can still replace, newly added template url is marked safe to replace.
+ ASSERT_TRUE(model_->CanReplaceKeyword(L"bar", L"http://foo.com", NULL));
+
+ // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
+ // no longer be replaceable.
+ model_->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
+ t_url->url()->url());
+
+ ASSERT_FALSE(model_->CanReplaceKeyword(L"bar", L"http://foo.com", NULL));
+}
+
+TEST_F(TemplateURLModelTest, HasDefaultSearchProvider) {
+ // We should have a default search provider even if we haven't loaded.
+ ASSERT_TRUE(model_->GetDefaultSearchProvider());
+
+ // Now force the model to load and make sure we still have a default.
+ VerifyLoad();
+
+ ASSERT_TRUE(model_->GetDefaultSearchProvider());
+}
+
+TEST_F(TemplateURLModelTest, DefaultSearchProviderLoadedFromPrefs) {
+ VerifyLoad();
+
+ TemplateURL* template_url = new TemplateURL();
+ template_url->SetURL(L"http://url", 0, 0);
+ template_url->SetSuggestionsURL(L"http://url2", 0, 0);
+ template_url->set_short_name(L"a");
+ template_url->set_safe_for_autoreplace(true);
+ template_url->set_date_created(Time::FromTimeT(100));
+
+ model_->Add(template_url);
+
+ const TemplateURL::IDType id = template_url->id();
+
+ model_->SetDefaultSearchProvider(template_url);
+
+ BlockTillServiceProcessesRequests();
+
+ TemplateURL first_default_search_provider = *template_url;
+
+ template_url = NULL;
+
+ // Reset the model and don't load it. The template url we set as the default
+ // should be pulled from prefs now.
+ ResetModel(false);
+
+ // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs
+ // value are persisted to prefs.
+ const TemplateURL* default_turl = model_->GetDefaultSearchProvider();
+ ASSERT_TRUE(default_turl);
+ ASSERT_TRUE(default_turl->url());
+ ASSERT_EQ(L"http://url", default_turl->url()->url());
+ ASSERT_TRUE(default_turl->suggestions_url());
+ ASSERT_EQ(L"http://url2", default_turl->suggestions_url()->url());
+ ASSERT_EQ(L"a", default_turl->short_name());
+ ASSERT_EQ(id, default_turl->id());
+
+ // Now do a load and make sure the default search provider really takes.
+ VerifyLoad();
+
+ ASSERT_TRUE(model_->GetDefaultSearchProvider());
+ AssertEquals(first_default_search_provider,
+ *model_->GetDefaultSearchProvider());
+}
+
+TEST_F(TemplateURLModelTest, BuildQueryTerms) {
+ struct TestData {
+ const std::string url;
+ const bool result;
+ // Keys and values are a semicolon separated list of expected values in the
+ // map.
+ const std::string keys;
+ const std::string values;
+ } data[] = {
+ // No query should return false.
+ { "http://blah/", false, "", "" },
+
+ // Query with empty key should return false.
+ { "http://blah/foo?=y", false, "", "" },
+
+ // Query with key occurring multiple times should return false.
+ { "http://blah/foo?x=y&x=z", false, "", "" },
+
+ { "http://blah/foo?x=y", true, "x", "y" },
+ { "http://blah/foo?x=y&y=z", true, "x;y", "y;z" },
+
+ // Key occurring multiple times should get an empty string.
+ { "http://blah/foo?x=y&x=z&y=z", true, "x;y", ";z" },
+ };
+
+ for (size_t i = 0; i < arraysize(data); ++i) {
+ TemplateURLModel::QueryTerms terms;
+ ASSERT_EQ(data[i].result,
+ TemplateURLModel::BuildQueryTerms(GURL(data[i].url), &terms));
+ if (data[i].result) {
+ std::vector<std::string> keys;
+ std::vector<std::string> values;
+ SplitString(data[i].keys, ';', &keys);
+ SplitString(data[i].values, ';', &values);
+ ASSERT_TRUE(keys.size() == values.size());
+ ASSERT_EQ(keys.size(), terms.size());
+ for (size_t j = 0; j < keys.size(); ++j) {
+ TemplateURLModel::QueryTerms::iterator term_iterator =
+ terms.find(keys[j]);
+ ASSERT_TRUE(term_iterator != terms.end());
+ ASSERT_EQ(values[j], term_iterator->second);
+ }
+ }
+ }
+}
+
+TEST_F(TemplateURLModelTest, UpdateKeywordSearchTermsForURL) {
+ struct TestData {
+ const std::string url;
+ const std::wstring term;
+ } data[] = {
+ { "http://foo/", L"" },
+ { "http://foo/foo?q=xx", L"" },
+ { "http://x/bar?q=xx", L"" },
+ { "http://x/foo?y=xx", L"" },
+ { "http://x/foo?q=xx", L"xx" },
+ { "http://x/foo?a=b&q=xx", L"xx" },
+ { "http://x/foo?q=b&q=xx", L"" },
+ };
+
+ AddKeywordWithDate(L"x", L"http://x/foo?q={searchTerms}", L"name", false,
+ Time());
+
+ for (size_t i = 0; i < arraysize(data); ++i) {
+ model_->UpdateKeywordSearchTermsForURL(history::URLRow(GURL(data[i].url)));
+ EXPECT_EQ(data[i].term, GetAndClearSearchTerm());
+ }
+}
+
+TEST_F(TemplateURLModelTest, DontUpdateKeywordSearchForNonReplaceable) {
+ struct TestData {
+ const std::string url;
+ } data[] = {
+ { "http://foo/" },
+ { "http://x/bar?q=xx" },
+ { "http://x/foo?y=xx" },
+ };
+
+ AddKeywordWithDate(L"x", L"http://x/foo", L"name", false, Time());
+
+ for (size_t i = 0; i < arraysize(data); ++i) {
+ model_->UpdateKeywordSearchTermsForURL(history::URLRow(GURL(data[i].url)));
+ ASSERT_EQ(std::wstring(), GetAndClearSearchTerm());
+ }
+}
+
+TEST_F(TemplateURLModelTest, ChangeGoogleBaseValue) {
+ SetGoogleBaseURL(L"http://google.com/");
+ const TemplateURL* t_url =
+ AddKeywordWithDate(L"x", L"{google:baseURL}?q={searchTerms}",
+ L"name", false, Time());
+ ASSERT_EQ(t_url, model_->GetTemplateURLForHost("google.com"));
+ ASSERT_EQ("google.com", t_url->url()->GetHost());
+
+ // Change the Google base url.
+ SetGoogleBaseURL(L"http://foo.com/");
+ model_->GoogleBaseURLChanged();
+
+ // Make sure the host->TemplateURL map was updated appropriately.
+ ASSERT_EQ(t_url, model_->GetTemplateURLForHost("foo.com"));
+ ASSERT_TRUE(model_->GetTemplateURLForHost("google.com") == NULL);
+ ASSERT_EQ("foo.com", t_url->url()->GetHost());
+ ASSERT_EQ(L"http://foo.com/?q=x", t_url->url()->ReplaceSearchTerms(*t_url,
+ L"x", TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()));
+}