- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / autocomplete / contact_provider_chromeos_unittest.cc
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 "chrome/browser/autocomplete/contact_provider_chromeos.h"
6
7 #include <cmath>
8 #include <map>
9 #include <string>
10 #include <vector>
11
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/autocomplete/autocomplete_input.h"
18 #include "chrome/browser/autocomplete/autocomplete_match.h"
19 #include "chrome/browser/autocomplete/autocomplete_provider.h"
20 #include "chrome/browser/chromeos/contacts/contact.pb.h"
21 #include "chrome/browser/chromeos/contacts/contact_manager_stub.h"
22 #include "chrome/browser/chromeos/contacts/contact_test_util.h"
23 #include "chrome/test/base/testing_browser_process.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chrome/test/base/testing_profile_manager.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/test/test_browser_thread.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29
30 using content::BrowserThread;
31
32 namespace {
33
34 // Initializes |contact| with the passed-in data.
35 void InitContact(const std::string& contact_id,
36                  const std::string& full_name,
37                  const std::string& given_name,
38                  const std::string& family_name,
39                  contacts::Contact* contact) {
40   contact->set_contact_id(contact_id);
41   contact->set_full_name(full_name);
42   contact->set_given_name(given_name);
43   contact->set_family_name(family_name);
44 }
45
46 }  // namespace
47
48 class ContactProviderTest : public testing::Test {
49  public:
50   ContactProviderTest() : ui_thread_(BrowserThread::UI, &message_loop_) {}
51   virtual ~ContactProviderTest() {}
52
53  protected:
54   // testing::Test implementation.
55   virtual void SetUp() OVERRIDE {
56     profile_manager_.reset(
57         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
58     ASSERT_TRUE(profile_manager_->SetUp());
59     profile_ = profile_manager_->CreateTestingProfile("test_profile");
60     contact_manager_.reset(new contacts::ContactManagerStub(profile_));
61     contact_provider_ =
62         new ContactProvider(NULL, profile_, contact_manager_->GetWeakPtr());
63   }
64
65   // Starts a (synchronous) query for |utf8_text| in |contact_provider_|.
66   void StartQuery(const std::string& utf8_text) {
67     contact_provider_->Start(
68         AutocompleteInput(UTF8ToUTF16(utf8_text),
69                           string16::npos,
70                           string16(),
71                           GURL(),
72                           AutocompleteInput::INVALID_SPEC,
73                           false,
74                           false,
75                           false,
76                           AutocompleteInput::ALL_MATCHES),
77         false);  // minimal_changes
78   }
79
80   // Returns the contact ID in |match|'s additional info, or an empty string if
81   // no ID is present.
82   std::string GetContactIdFromMatch(const AutocompleteMatch& match) {
83     AutocompleteMatch::AdditionalInfo::const_iterator it =
84         match.additional_info.find(ContactProvider::kMatchContactIdKey);
85     return it != match.additional_info.end() ? it->second : std::string();
86   }
87
88   // Returns pointers to all of the Contact objects referenced in
89   // |contact_provider_|'s current results.
90   contacts::ContactPointers GetMatchedContacts() {
91     contacts::ContactPointers contacts;
92     const ACMatches& matches = contact_provider_->matches();
93     for (size_t i = 0; i < matches.size(); ++i) {
94       const contacts::Contact* contact = contact_manager_->GetContactById(
95           profile_, GetContactIdFromMatch(matches[i]));
96       DCHECK(contact) << "Unable to find contact for match " << i;
97       contacts.push_back(contact);
98     }
99     return contacts;
100   }
101
102   // Returns a semicolon-separated string containing string representations (as
103   // provided by AutocompleteMatch::ClassificationsToString()) of the
104   // |contents_class| fields of all current matches.  Results are sorted by
105   // contact ID.
106   std::string GetMatchClassifications() {
107     typedef std::map<std::string, std::string> StringMap;
108     StringMap contact_id_classifications;
109     const ACMatches& matches = contact_provider_->matches();
110     for (size_t i = 0; i < matches.size(); ++i) {
111       std::string id = GetContactIdFromMatch(matches[i]);
112       DCHECK(!id.empty()) << "Match " << i << " lacks contact ID";
113       contact_id_classifications[id] = AutocompleteMatch::
114           ClassificationsToString(matches[i].contents_class);
115     }
116
117     std::string result;
118     for (StringMap::const_iterator it = contact_id_classifications.begin();
119          it != contact_id_classifications.end(); ++it) {
120       if (!result.empty())
121         result += ";";
122       result += it->second;
123     }
124     return result;
125   }
126
127   base::MessageLoopForUI message_loop_;
128   content::TestBrowserThread ui_thread_;
129
130   scoped_ptr<TestingProfileManager> profile_manager_;
131   TestingProfile* profile_;
132
133   scoped_ptr<contacts::ContactManagerStub> contact_manager_;
134   scoped_refptr<ContactProvider> contact_provider_;
135 };
136
137 TEST_F(ContactProviderTest, BasicMatching) {
138   const std::string kContactId1 = "contact_1";
139   scoped_ptr<contacts::Contact> contact1(new contacts::Contact);
140   InitContact(kContactId1, "Bob Smith", "Bob", "Smith", contact1.get());
141
142   const std::string kContactId2 = "contact_2";
143   scoped_ptr<contacts::Contact> contact2(new contacts::Contact);
144   InitContact(kContactId2, "Dr. Jane Smith", "Jane", "Smith", contact2.get());
145
146   contacts::ContactPointers contacts;
147   contacts.push_back(contact1.get());
148   contacts.push_back(contact2.get());
149   contact_manager_->SetContacts(contacts);
150   contact_manager_->NotifyObserversAboutUpdatedContacts();
151
152   StartQuery("b");
153   EXPECT_EQ(
154       contacts::test::VarContactsToString(1, contact1.get()),
155       contacts::test::ContactsToString(GetMatchedContacts()));
156   EXPECT_EQ("0,2,1,0", GetMatchClassifications());
157
158   StartQuery("bob");
159   EXPECT_EQ(
160       contacts::test::VarContactsToString(1, contact1.get()),
161       contacts::test::ContactsToString(GetMatchedContacts()));
162   EXPECT_EQ("0,2,3,0", GetMatchClassifications());
163
164   StartQuery("bob smith");
165   EXPECT_EQ(
166       contacts::test::VarContactsToString(1, contact1.get()),
167       contacts::test::ContactsToString(GetMatchedContacts()));
168   EXPECT_EQ("0,2", GetMatchClassifications());
169
170   StartQuery("sm");
171   EXPECT_EQ(
172       contacts::test::VarContactsToString(2, contact1.get(), contact2.get()),
173       contacts::test::ContactsToString(GetMatchedContacts()));
174   EXPECT_EQ("0,0,4,2,6,0;" "0,0,9,2,11,0", GetMatchClassifications());
175
176   StartQuery("smith");
177   EXPECT_EQ(
178       contacts::test::VarContactsToString(2, contact1.get(), contact2.get()),
179       contacts::test::ContactsToString(GetMatchedContacts()));
180   EXPECT_EQ("0,0,4,2;" "0,0,9,2", GetMatchClassifications());
181
182   StartQuery("smIth BOb");
183   EXPECT_EQ(
184       contacts::test::VarContactsToString(1, contact1.get()),
185       contacts::test::ContactsToString(GetMatchedContacts()));
186   EXPECT_EQ("0,2,3,0,4,2", GetMatchClassifications());
187
188   StartQuery("bobo");
189   EXPECT_EQ("", contacts::test::ContactsToString(GetMatchedContacts()));
190   EXPECT_EQ("", GetMatchClassifications());
191
192   StartQuery("mith");
193   EXPECT_EQ("", contacts::test::ContactsToString(GetMatchedContacts()));
194   EXPECT_EQ("", GetMatchClassifications());
195
196   StartQuery("dr");
197   EXPECT_EQ(
198       contacts::test::VarContactsToString(1, contact2.get()),
199       contacts::test::ContactsToString(GetMatchedContacts()));
200   EXPECT_EQ("0,2,2,0", GetMatchClassifications());
201
202   StartQuery("dr. j");
203   EXPECT_EQ(
204       contacts::test::VarContactsToString(1, contact2.get()),
205       contacts::test::ContactsToString(GetMatchedContacts()));
206   EXPECT_EQ("0,2,5,0", GetMatchClassifications());
207
208   StartQuery("jane");
209   EXPECT_EQ(
210       contacts::test::VarContactsToString(1, contact2.get()),
211       contacts::test::ContactsToString(GetMatchedContacts()));
212   EXPECT_EQ("0,0,4,2,8,0", GetMatchClassifications());
213 }
214
215 TEST_F(ContactProviderTest, Collation) {
216   scoped_ptr<contacts::Contact> contact(new contacts::Contact);
217   InitContact("1", "Bj\xC3\xB6rn Adelsv\xC3\xA4rd",
218               "Bj\xC3\xB6rn", "Adelsv\xC3\xA4rd",
219               contact.get());
220
221   contacts::ContactPointers contacts;
222   contacts.push_back(contact.get());
223   contact_manager_->SetContacts(contacts);
224   contact_manager_->NotifyObserversAboutUpdatedContacts();
225
226   StartQuery("bjorn");
227   EXPECT_EQ(
228       contacts::test::VarContactsToString(1, contact.get()),
229       contacts::test::ContactsToString(GetMatchedContacts()));
230   EXPECT_EQ("0,2,5,0", GetMatchClassifications());
231
232   StartQuery("adelsvard");
233   EXPECT_EQ(
234       contacts::test::VarContactsToString(1, contact.get()),
235       contacts::test::ContactsToString(GetMatchedContacts()));
236   EXPECT_EQ("0,0,6,2", GetMatchClassifications());
237 }
238
239 TEST_F(ContactProviderTest, Relevance) {
240   // Create more contacts than the maximum number of results that an
241   // AutocompleteProvider should return.  Give them all the same family name and
242   // ascending affinities from 0.0 to 1.0.
243   const size_t kNumContacts = AutocompleteProvider::kMaxMatches + 1;
244   const std::string kFamilyName = "Jones";
245
246   ScopedVector<contacts::Contact> contacts;
247   contacts::ContactPointers contact_pointers;
248   for (size_t i = 0; i < kNumContacts; ++i) {
249     contacts::Contact* contact = new contacts::Contact;
250     std::string id_string = base::IntToString(static_cast<int>(i));
251     InitContact(id_string, id_string, kFamilyName,
252                 id_string + " " + kFamilyName, contact);
253     contact->set_affinity(static_cast<float>(i) / kNumContacts);
254     contacts.push_back(contact);
255     contact_pointers.push_back(contact);
256   }
257
258   contact_manager_->SetContacts(contact_pointers);
259   contact_manager_->NotifyObserversAboutUpdatedContacts();
260
261   // Do a search for the family name and check that the total number of results
262   // is limited as expected and that the results are ordered by descending
263   // affinity.
264   StartQuery(kFamilyName);
265   const ACMatches& matches = contact_provider_->matches();
266   ASSERT_EQ(AutocompleteProvider::kMaxMatches, matches.size());
267
268   int previous_relevance = 0;
269   for (size_t i = 0; i < matches.size(); ++i) {
270     const contacts::Contact& exp_contact =
271         *(contacts[kNumContacts - 1 - i]);
272     std::string match_id = GetContactIdFromMatch(matches[i]);
273     EXPECT_EQ(exp_contact.contact_id(), match_id)
274         << "Expected contact ID " << exp_contact.contact_id()
275         << " for match " << i << " but got " << match_id << " instead";
276     if (i > 0) {
277       EXPECT_LE(matches[i].relevance, previous_relevance)
278           << "Match " << i << " has greater relevance than previous match";
279     }
280     EXPECT_FALSE(matches[i].allowed_to_be_default_match);
281     previous_relevance = matches[i].relevance;
282   }
283 }