Index: chrome/browser/autocomplete/contact_provider_chromeos_unittest.cc |
diff --git a/chrome/browser/autocomplete/contact_provider_chromeos_unittest.cc b/chrome/browser/autocomplete/contact_provider_chromeos_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..99cdb97972bb63eb6f5b06811afa1a971ccc01e9 |
--- /dev/null |
+++ b/chrome/browser/autocomplete/contact_provider_chromeos_unittest.cc |
@@ -0,0 +1,282 @@ |
+// 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 "chrome/browser/autocomplete/contact_provider_chromeos.h" |
+ |
+#include <string> |
+#include <utility> |
+#include <vector> |
+ |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
+#include "base/string16.h" |
+#include "base/string_number_conversions.h" |
+#include "base/string_split.h" |
+#include "base/utf_string_conversions.h" |
+#include "chrome/browser/autocomplete/autocomplete_input.h" |
+#include "chrome/browser/autocomplete/autocomplete_match.h" |
+#include "chrome/browser/autocomplete/autocomplete_provider.h" |
+#include "chrome/browser/chromeos/contacts/contact.pb.h" |
+#include "chrome/browser/chromeos/contacts/contact_manager_stub.h" |
+#include "chrome/browser/chromeos/contacts/contact_test_util.h" |
+#include "chrome/test/base/testing_browser_process.h" |
+#include "chrome/test/base/testing_profile.h" |
+#include "chrome/test/base/testing_profile_manager.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/test/test_browser_thread.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using content::BrowserThread; |
+ |
+namespace { |
+ |
+// Given a string of comma-separated "index:length" spans like "0:1,5:3", |
+// returns a vector of pairs containing the same information. |
+ContactProvider::MatchSpans MatchSpansFromString(const std::string& str) { |
+ ContactProvider::MatchSpans spans; |
+ std::vector<std::string> parts; |
+ base::SplitString(str, ',', &parts); |
+ for (size_t i = 0; i < parts.size(); ++i) { |
+ std::vector<std::string> index_and_length; |
+ base::SplitString(parts[i], ':', &index_and_length); |
+ CHECK(index_and_length.size() == 2); |
+ |
+ ContactProvider::MatchSpan span; |
+ CHECK(base::StringToUint64(index_and_length[0], &span.first)); |
+ CHECK(base::StringToUint64(index_and_length[1], &span.second)); |
+ spans.push_back(span); |
+ } |
+ return spans; |
+} |
+ |
+// Given a vector of classifications, returns a comma-separated string |
+// consisting of each classifications offset followed by a character describing |
+// its style ('n' for "none", 'u' for "URL", 'm' for "match", and 'd' for |
+// "dim"), e.g. "0n,5m,8n". |
+std::string ACMatchClassificationsToString( |
+ const AutocompleteMatch::ACMatchClassifications& classifications) { |
+ std::string result; |
+ for (size_t i = 0; i < classifications.size(); ++i) { |
+ if (!result.empty()) |
+ result += ","; |
+ |
+ result += base::Uint64ToString( |
+ static_cast<uint64>(classifications[i].offset)); |
+ |
+ switch (classifications[i].style) { |
+ case AutocompleteMatch::ACMatchClassification::NONE: |
+ result += "n"; |
+ break; |
+ case AutocompleteMatch::ACMatchClassification::URL: |
+ result += "u"; |
+ break; |
+ case AutocompleteMatch::ACMatchClassification::MATCH: |
+ result += "m"; |
+ break; |
+ case AutocompleteMatch::ACMatchClassification::DIM: |
+ result += "d"; |
+ break; |
+ default: |
+ NOTREACHED() << "Unknown style " << classifications[i].style; |
+ } |
+ } |
+ |
+ return result; |
+} |
+ |
+// Initializes |contact| with the passed-in data. |
+void InitContact(const std::string& contact_id, |
+ const std::string& full_name, |
+ const std::string& given_name, |
+ const std::string& family_name, |
+ contacts::Contact* contact) { |
+ contact->set_contact_id(contact_id); |
+ contact->set_full_name(full_name); |
+ contact->set_given_name(given_name); |
+ contact->set_family_name(family_name); |
+} |
+ |
+} // namespace |
+ |
+class ContactProviderTest : public testing::Test { |
+ public: |
+ ContactProviderTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} |
+ virtual ~ContactProviderTest() {} |
+ |
+ protected: |
+ // testing::Test implementation. |
+ virtual void SetUp() OVERRIDE { |
+ profile_manager_.reset( |
+ new TestingProfileManager( |
+ static_cast<TestingBrowserProcess*>(g_browser_process))); |
+ ASSERT_TRUE(profile_manager_->SetUp()); |
+ profile_ = profile_manager_->CreateTestingProfile("test_profile"); |
+ contact_manager_.reset(new contacts::ContactManagerStub(profile_)); |
+ contact_provider_ = |
+ new ContactProvider(NULL, profile_, contact_manager_->GetWeakPtr()); |
+ } |
+ |
+ // Starts a (synchronous) query for |utf8_text| in |contact_provider_|. |
+ void StartQuery(const std::string& utf8_text) { |
+ contact_provider_->Start( |
+ AutocompleteInput(UTF8ToUTF16(utf8_text), |
+ string16(), // desired_tld |
+ false, // prevent_inline_autocomplete |
+ false, // prefer_keyword |
+ false, // allow_exact_keyword_match |
+ AutocompleteInput::ALL_MATCHES), |
+ false); // minimal_changes |
+ } |
+ |
+ // Returns pointers to all of the Contact objects referenced in |
+ // |contact_provider_|'s current results. |
+ contacts::ContactPointers GetMatchedContacts() { |
+ contacts::ContactPointers contacts; |
+ const ACMatches& matches = contact_provider_->matches(); |
+ for (size_t i = 0; i < matches.size(); ++i) { |
+ const AutocompleteMatch& match = matches[i]; |
+ |
+ std::map<std::string, std::string>::const_iterator info_it = |
+ match.additional_info.find(ContactProvider::kMatchContactIdKey); |
+ if (info_it == match.additional_info.end()) { |
+ LOG(ERROR) << "Unable to find contact ID in match"; |
+ continue; |
+ } |
+ const std::string& contact_id = info_it->second; |
+ |
+ const contacts::Contact* contact = |
+ contact_manager_->GetContactById(profile_, contact_id); |
+ if (!contact) { |
+ LOG(ERROR) << "Unable to find contact with ID " << contact_id; |
+ continue; |
+ } |
+ |
+ contacts.push_back(contact); |
+ } |
+ return contacts; |
+ } |
+ |
+ MessageLoopForUI message_loop_; |
+ content::TestBrowserThread ui_thread_; |
+ |
+ scoped_ptr<TestingProfileManager> profile_manager_; |
+ TestingProfile* profile_; |
+ |
+ scoped_ptr<contacts::ContactManagerStub> contact_manager_; |
+ scoped_refptr<ContactProvider> contact_provider_; |
+}; |
+ |
+TEST_F(ContactProviderTest, FillACMatchClassifications) { |
+ // We should end up with a single unstyled classification if we pass in an |
+ // empty list of spans or a single 0-length span. |
+ EXPECT_EQ( |
+ "0n", |
+ ACMatchClassificationsToString( |
+ ContactProvider::TestAPI::RunFillACMatchClassifications( |
+ MatchSpansFromString(""), 10))); |
+ EXPECT_EQ( |
+ "0n", |
+ ACMatchClassificationsToString( |
+ ContactProvider::TestAPI::RunFillACMatchClassifications( |
+ MatchSpansFromString("5:0"), 10))); |
+ |
+ EXPECT_EQ( |
+ "0m,3n,5m,6n", |
+ ACMatchClassificationsToString( |
+ ContactProvider::TestAPI::RunFillACMatchClassifications( |
+ MatchSpansFromString("0:3,5:1"), 10))); |
+ |
+ // Overlapping and adjacent spans should be collapsed. |
+ EXPECT_EQ( |
+ "0n,2m,7n,8m", |
+ ACMatchClassificationsToString( |
+ ContactProvider::TestAPI::RunFillACMatchClassifications( |
+ MatchSpansFromString("2:1,2:5,3:1,8:1,9:1"), 10))); |
+ |
+ // Unsorted input should fail. |
+ EXPECT_EQ( |
+ "", |
+ ACMatchClassificationsToString( |
+ ContactProvider::TestAPI::RunFillACMatchClassifications( |
+ MatchSpansFromString("2:1,1:1"), 10))); |
+ |
+ // We should also report failure if a span exceeds the length of the string. |
+ EXPECT_EQ( |
+ "", |
+ ACMatchClassificationsToString( |
+ ContactProvider::TestAPI::RunFillACMatchClassifications( |
+ MatchSpansFromString("9:2"), 10))); |
+} |
+ |
+TEST_F(ContactProviderTest, Basic) { |
+ const std::string kContactId1 = "contact_1"; |
+ scoped_ptr<contacts::Contact> contact1(new contacts::Contact); |
+ InitContact(kContactId1, "Bob Smith", "Bob", "Smith", contact1.get()); |
+ |
+ const std::string kContactId2 = "contact_2"; |
+ scoped_ptr<contacts::Contact> contact2(new contacts::Contact); |
+ InitContact(kContactId2, "Dr. Jane Doe", "Jane", "Doe", contact2.get()); |
+ |
+ contacts::ContactPointers contacts; |
+ contacts.push_back(contact1.get()); |
+ contacts.push_back(contact2.get()); |
+ contact_manager_->SetContacts(contacts); |
+ contact_manager_->NotifyObserversAboutUpdatedContacts(); |
+ |
+ StartQuery("b"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact1.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("bob"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact1.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("bob smith"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact1.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("sm"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact1.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("smith"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact1.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("smIth BOb"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact1.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("bobo"); |
+ EXPECT_EQ("", contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("mith"); |
+ EXPECT_EQ("", contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("dr"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact2.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("dr. j"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact2.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("jane"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact2.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+ |
+ StartQuery("doe"); |
+ EXPECT_EQ( |
+ contacts::test::VarContactsToString(1, contact2.get()), |
+ contacts::test::ContactsToString(GetMatchedContacts())); |
+} |