Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: chrome/browser/chromeos/contacts/google_contact_store_unittest.cc

Issue 10829144: contacts: Add GoogleContactStore. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: minor updates Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/chromeos/contacts/google_contact_store.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h"
10 #include "base/time.h"
11 #include "chrome/test/base/testing_profile.h"
12 #include "chrome/browser/chromeos/contacts/contact.pb.h"
13 #include "chrome/browser/chromeos/contacts/contact_store_observer.h"
14 #include "chrome/browser/chromeos/contacts/contact_test_util.h"
15 #include "chrome/browser/chromeos/contacts/fake_contact_database.h"
16 #include "chrome/browser/chromeos/gdata/gdata_contacts_service_stub.h"
17 #include "chrome/browser/chromeos/gdata/gdata_util.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/test/test_browser_thread.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using content::BrowserThread;
23
24 namespace contacts {
25 namespace test {
26
27 // ContactStoreObserver implementation that just counts the number of times
28 // that it's been told that a store has been updated.
29 class TestContactStoreObserver : public ContactStoreObserver {
30 public:
31 TestContactStoreObserver() : num_updates_(0) {}
32 ~TestContactStoreObserver() {}
33
34 int num_updates() const { return num_updates_; }
35 void reset_stats() { num_updates_ = 0; }
36
37 // ContactStoreObserver overrides:
38 void OnContactsUpdated(ContactStore* store) OVERRIDE {
39 DCHECK(store);
40 num_updates_++;
41 }
42
43 private:
44 // Number of times that OnContactsUpdated() has been called.
45 int num_updates_;
46
47 DISALLOW_COPY_AND_ASSIGN(TestContactStoreObserver);
48 };
49
50 class GoogleContactStoreTest : public testing::Test {
51 public:
52 GoogleContactStoreTest() : ui_thread_(BrowserThread::UI, &message_loop_) {}
53 virtual ~GoogleContactStoreTest() {}
54
55 protected:
56 // testing::Test implementation.
57 virtual void SetUp() OVERRIDE {
58 testing::Test::SetUp();
59 profile_.reset(new TestingProfile);
60
61 store_.reset(new GoogleContactStore(profile_.get()));
62 store_->AddObserver(&observer_);
63
64 test_api_.reset(new GoogleContactStore::TestAPI(store_.get()));
65
66 db_ = new FakeContactDatabase;
67 test_api_->SetDatabase(db_);
68
69 gdata_service_ = new gdata::GDataContactsServiceStub;
70 test_api_->SetGDataService(gdata_service_);
71 }
72
73 TestContactStoreObserver* observer() { return &observer_; }
74 GoogleContactStore* store() { return store_.get(); }
75 GoogleContactStore::TestAPI* test_api() { return test_api_.get(); }
76 FakeContactDatabase* db() { return db_; }
77 gdata::GDataContactsServiceStub* gdata_service() { return gdata_service_; }
satorux1 2012/08/02 22:21:25 In tests, you might want to make all members prote
Daniel Erat 2012/08/02 23:23:18 Done. Thinking back, I believe that I just did it
78
79 private:
80 MessageLoopForUI message_loop_;
81 content::TestBrowserThread ui_thread_;
82
83 TestContactStoreObserver observer_;
84 scoped_ptr<TestingProfile> profile_;
85 scoped_ptr<GoogleContactStore> store_;
86 scoped_ptr<GoogleContactStore::TestAPI> test_api_;
87
88 FakeContactDatabase* db_; // not owned
89 gdata::GDataContactsServiceStub* gdata_service_; // not owned
90
91 DISALLOW_COPY_AND_ASSIGN(GoogleContactStoreTest);
92 };
93
94 TEST_F(GoogleContactStoreTest, LoadFromDatabase) {
95 // Store two contacts in the database.
96 const std::string kProviderId1 = "provider1";
97 const std::string kProviderId2 = "provider2";
98 scoped_ptr<Contact> contact1(new Contact);
99 InitContact(kProviderId1, "1", false, contact1.get());
100 scoped_ptr<Contact> contact2(new Contact);
101 InitContact(kProviderId2, "2", false, contact2.get());
102 ContactPointers db_contacts;
103 db_contacts.push_back(contact1.get());
104 db_contacts.push_back(contact2.get());
105 UpdateMetadata db_metadata;
106 db()->SetContacts(db_contacts, db_metadata);
107
108 // Tell the GData service to report failure, initialize the store, and check
109 // that the contacts from the database are loaded.
110 gdata_service()->set_download_should_succeed(false);
111 store()->Init();
112 ContactPointers loaded_contacts;
113 store()->AppendContacts(&loaded_contacts);
114 EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()),
115 ContactsToString(loaded_contacts));
116 EXPECT_TRUE(test_api()->update_scheduled());
117 EXPECT_EQ(1, observer()->num_updates());
118
119 // Check that we can also grab the contact via its ID.
120 const Contact* loaded_contact1 =
121 store()->GetContactByProviderId(kProviderId1);
122 ASSERT_TRUE(loaded_contact1 != NULL);
satorux1 2012/08/02 22:21:25 you could do ASSERT_TRUE(loaded_contact1);
Daniel Erat 2012/08/02 23:23:18 Done.
123 EXPECT_EQ(ContactToString(*contact1), ContactToString(*loaded_contact1));
124
125 // We should get NULL if we request a nonexistent contact.
126 EXPECT_TRUE(store()->GetContactByProviderId("bogus_id") == NULL);
satorux1 2012/08/02 22:21:25 you could do EXPECT_FALSE(store()->GetContactByPro
Daniel Erat 2012/08/02 23:23:18 Done.
127 }
128
129 TEST_F(GoogleContactStoreTest, LoadFromGData) {
130 // Store two contacts in the GData service.
131 scoped_ptr<Contact> contact1(new Contact);
132 InitContact("provider1", "1", false, contact1.get());
133 scoped_ptr<Contact> contact2(new Contact);
134 InitContact("provider2", "2", false, contact2.get());
135 ContactPointers gdata_contacts;
136 gdata_contacts.push_back(contact1.get());
137 gdata_contacts.push_back(contact2.get());
138 gdata_service()->SetContacts(gdata_contacts, base::Time());
139
140 // Initialize the store and check that the contacts are loaded from GData.
141 store()->Init();
142 ContactPointers loaded_contacts;
143 store()->AppendContacts(&loaded_contacts);
144 EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()),
145 ContactsToString(loaded_contacts));
146 EXPECT_TRUE(test_api()->update_scheduled());
147 EXPECT_EQ(1, observer()->num_updates());
148
149 // The contacts should've been saved to the database, too.
150 EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()),
151 ContactsToString(db()->contacts()));
152 }
153
154 TEST_F(GoogleContactStoreTest, UpdateFromGData) {
155 scoped_ptr<Contact> contact1(new Contact);
156 InitContact("provider1", "1", false, contact1.get());
157 scoped_ptr<Contact> contact2(new Contact);
158 InitContact("provider2", "2", false, contact2.get());
159 scoped_ptr<Contact> contact3(new Contact);
160 InitContact("provider3", "3", false, contact3.get());
161
162 // Store the first two contacts in the database.
163 ContactPointers db_contacts;
164 db_contacts.push_back(contact1.get());
165 db_contacts.push_back(contact2.get());
166 UpdateMetadata db_metadata;
167 db()->SetContacts(db_contacts, db_metadata);
168
169 // Store all three in the GData service. We expect the update request to ask
170 // for all contacts updated one millisecond after the newest contact in the
171 // database.
172 ContactPointers gdata_contacts;
173 gdata_contacts.push_back(contact1.get());
174 gdata_contacts.push_back(contact2.get());
175 gdata_contacts.push_back(contact3.get());
176 gdata_service()->SetContacts(
177 gdata_contacts,
178 base::Time::FromInternalValue(contact2->update_time()) +
179 base::TimeDelta::FromMilliseconds(1));
180
181 // Check that the store ends up with all three contacts.
182 store()->Init();
183 ContactPointers loaded_contacts;
184 store()->AppendContacts(&loaded_contacts);
185 EXPECT_EQ(VarContactsToString(
186 3, contact1.get(), contact2.get(), contact3.get()),
187 ContactsToString(loaded_contacts));
188 EXPECT_EQ(2, observer()->num_updates());
189
190 // All three contacts should've been saved to the database.
191 EXPECT_EQ(VarContactsToString(
192 3, contact1.get(), contact2.get(), contact3.get()),
193 ContactsToString(db()->contacts()));
194 EXPECT_TRUE(test_api()->update_scheduled());
195 }
196
197 TEST_F(GoogleContactStoreTest, FetchUpdatedContacts) {
198 scoped_ptr<Contact> contact1(new Contact);
199 InitContact("provider1", "1", false, contact1.get());
200 scoped_ptr<Contact> contact2(new Contact);
201 InitContact("provider2", "2", false, contact2.get());
202 scoped_ptr<Contact> contact3(new Contact);
203 InitContact("provider3", "3", false, contact3.get());
204
205 // Tell the GData service to return all three contacts in response to a full
206 // update.
207 ContactPointers gdata_contacts;
208 gdata_contacts.push_back(contact1.get());
209 gdata_contacts.push_back(contact2.get());
210 gdata_contacts.push_back(contact3.get());
211 gdata_service()->SetContacts(gdata_contacts, base::Time());
212
213 store()->Init();
214 ContactPointers loaded_contacts;
215 store()->AppendContacts(&loaded_contacts);
216 EXPECT_EQ(ContactsToString(gdata_contacts),
217 ContactsToString(loaded_contacts));
218 EXPECT_EQ(ContactsToString(gdata_contacts),
219 ContactsToString(db()->contacts()));
220 EXPECT_TRUE(test_api()->update_scheduled());
221 EXPECT_EQ(1, observer()->num_updates());
222 observer()->reset_stats();
223
224 // Update the third contact.
225 contact3->set_full_name("new full name");
226 base::Time old_contact3_update_time =
227 base::Time::FromInternalValue(contact3->update_time());
228 contact3->set_update_time(
229 (old_contact3_update_time +
230 base::TimeDelta::FromSeconds(10)).ToInternalValue());
231 gdata_service()->SetContacts(
232 gdata_contacts,
233 old_contact3_update_time + base::TimeDelta::FromMilliseconds(1));
234
235 // Check that the updated contact is loaded (i.e. the store passed the
236 // correct minimum update time to the service).
237 test_api()->DoUpdate();
238 loaded_contacts.clear();
239 store()->AppendContacts(&loaded_contacts);
240 EXPECT_EQ(ContactsToString(gdata_contacts),
241 ContactsToString(loaded_contacts));
242 EXPECT_EQ(ContactsToString(gdata_contacts),
243 ContactsToString(db()->contacts()));
244 EXPECT_TRUE(test_api()->update_scheduled());
245 EXPECT_EQ(1, observer()->num_updates());
246 observer()->reset_stats();
247
248 // The next update should be based on the third contact's new update time.
249 contact3->set_full_name("yet another full name");
250 gdata_service()->SetContacts(
251 gdata_contacts,
252 base::Time::FromInternalValue(contact3->update_time()) +
253 base::TimeDelta::FromMilliseconds(1));
254 test_api()->DoUpdate();
255 loaded_contacts.clear();
256 store()->AppendContacts(&loaded_contacts);
257 EXPECT_EQ(ContactsToString(gdata_contacts),
258 ContactsToString(loaded_contacts));
259 EXPECT_EQ(ContactsToString(gdata_contacts),
260 ContactsToString(db()->contacts()));
261 EXPECT_TRUE(test_api()->update_scheduled());
262 EXPECT_EQ(1, observer()->num_updates());
263 }
264
265 TEST_F(GoogleContactStoreTest, DontReturnDeletedContacts) {
266 // Tell GData to return a single deleted contact.
267 const std::string kProviderId = "provider";
268 scoped_ptr<Contact> contact(new Contact);
269 InitContact(kProviderId, "1", true, contact.get());
270 ContactPointers gdata_contacts;
271 gdata_contacts.push_back(contact.get());
272 gdata_service()->SetContacts(gdata_contacts, base::Time());
273
274 // The contact shouldn't be returned by AppendContacts() or
275 // GetContactByProviderId().
276 store()->Init();
277 ContactPointers loaded_contacts;
278 store()->AppendContacts(&loaded_contacts);
279 EXPECT_TRUE(loaded_contacts.empty());
280 EXPECT_TRUE(store()->GetContactByProviderId(kProviderId) == NULL);
281 }
282
283 // Test that we do a full refresh from GData if enough time has passed since the
284 // last refresh that we might've missed some contact deletions (see
285 // |kForceFullUpdateDays| in google_contact_store.cc).
286 TEST_F(GoogleContactStoreTest, FullRefreshAfterThirtyDays) {
287 base::Time::Exploded kInitTimeExploded = { 2012, 3, 0, 1, 16, 34, 56, 123 };
288 base::Time kInitTime = base::Time::FromUTCExploded(kInitTimeExploded);
289
290 base::Time kOldUpdateTime = kInitTime - base::TimeDelta::FromDays(31);
291 scoped_ptr<Contact> contact1(new Contact);
292 InitContact("provider1", "1", false, contact1.get());
293 contact1->set_update_time(kOldUpdateTime.ToInternalValue());
294 scoped_ptr<Contact> contact2(new Contact);
295 InitContact("provider2", "2", false, contact2.get());
296 contact2->set_update_time(kOldUpdateTime.ToInternalValue());
297
298 // Put both contacts in the database, along with metadata saying that the last
299 // successful update was 31 days in the past.
300 ContactPointers db_contacts;
301 db_contacts.push_back(contact1.get());
302 db_contacts.push_back(contact2.get());
303 UpdateMetadata db_metadata;
304 db_metadata.set_last_update_start_time(kOldUpdateTime.ToInternalValue());
305 db()->SetContacts(db_contacts, db_metadata);
306
307 // Tell the GData service to return only the first contact and to expect a
308 // full refresh (since it's been a long time since the last update).
309 ContactPointers gdata_contacts;
310 gdata_contacts.push_back(contact1.get());
311 gdata_service()->SetContacts(gdata_contacts, base::Time());
312
313 test_api()->set_current_time(kInitTime);
314 store()->Init();
315 ContactPointers loaded_contacts;
316 store()->AppendContacts(&loaded_contacts);
317 EXPECT_EQ(ContactsToString(gdata_contacts),
318 ContactsToString(loaded_contacts));
319 EXPECT_TRUE(test_api()->update_scheduled());
320
321 // Make GData return both contacts now in response to an incremental update.
322 gdata_contacts.clear();
323 contact2->set_update_time(kInitTime.ToInternalValue());
324 gdata_contacts.push_back(contact1.get());
325 gdata_contacts.push_back(contact2.get());
326 gdata_service()->SetContacts(
327 gdata_contacts, kOldUpdateTime + base::TimeDelta::FromMilliseconds(1));
328
329 // Advance the time by twenty days and check that the update is successful.
330 base::Time kFirstUpdateTime = kInitTime + base::TimeDelta::FromDays(20);
331 test_api()->set_current_time(kFirstUpdateTime);
332 test_api()->DoUpdate();
333 loaded_contacts.clear();
334 store()->AppendContacts(&loaded_contacts);
335 EXPECT_EQ(ContactsToString(gdata_contacts),
336 ContactsToString(loaded_contacts));
337
338 // After we advance the time by 31 days, we should do a full refresh again.
339 gdata_contacts.clear();
340 gdata_contacts.push_back(contact1.get());
341 gdata_service()->SetContacts(gdata_contacts, base::Time());
342 base::Time kSecondUpdateTime =
343 kFirstUpdateTime + base::TimeDelta::FromDays(31);
344 test_api()->set_current_time(kSecondUpdateTime);
345 test_api()->DoUpdate();
346 loaded_contacts.clear();
347 store()->AppendContacts(&loaded_contacts);
348 EXPECT_EQ(ContactsToString(gdata_contacts),
349 ContactsToString(loaded_contacts));
350 }
351
352 TEST_F(GoogleContactStoreTest, HandleDatabaseInitFailure) {
353 scoped_ptr<Contact> contact1(new Contact);
354 InitContact("provider1", "1", false, contact1.get());
355
356 // Store a contact in the database but make initialization fail.
357 ContactPointers db_contacts;
358 db_contacts.push_back(contact1.get());
359 UpdateMetadata db_metadata;
360 db()->SetContacts(db_contacts, db_metadata);
361 db()->set_init_success(false);
362
363 // Create a second contact and tell the GData service to return it.
364 scoped_ptr<Contact> contact2(new Contact);
365 InitContact("provider2", "2", false, contact2.get());
366 ContactPointers gdata_contacts;
367 gdata_contacts.push_back(contact2.get());
368 gdata_service()->SetContacts(gdata_contacts, base::Time());
369
370 // Initialize the store. We shouldn't get the first contact (since DB
371 // initialization failed) but we should still fetch the second one from GData
372 // and schedule an update.
373 store()->Init();
374 ContactPointers loaded_contacts;
375 store()->AppendContacts(&loaded_contacts);
376 EXPECT_EQ(ContactsToString(gdata_contacts),
377 ContactsToString(loaded_contacts));
378 EXPECT_TRUE(test_api()->update_scheduled());
379 }
380
381 } // namespace test
382 } // namespace contacts
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698