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

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: merge and switch an EXPECT_TRUE(... == NULL) to EXPECT_FALSE(...) 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 MessageLoopForUI message_loop_;
74 content::TestBrowserThread ui_thread_;
75
76 TestContactStoreObserver observer_;
77 scoped_ptr<TestingProfile> profile_;
78 scoped_ptr<GoogleContactStore> store_;
79 scoped_ptr<GoogleContactStore::TestAPI> test_api_;
80
81 FakeContactDatabase* db_; // not owned
82 gdata::GDataContactsServiceStub* gdata_service_; // not owned
83
84 private:
85 DISALLOW_COPY_AND_ASSIGN(GoogleContactStoreTest);
86 };
87
88 TEST_F(GoogleContactStoreTest, LoadFromDatabase) {
89 // Store two contacts in the database.
90 const std::string kProviderId1 = "provider1";
91 const std::string kProviderId2 = "provider2";
92 scoped_ptr<Contact> contact1(new Contact);
93 InitContact(kProviderId1, "1", false, contact1.get());
94 scoped_ptr<Contact> contact2(new Contact);
95 InitContact(kProviderId2, "2", false, contact2.get());
96 ContactPointers db_contacts;
97 db_contacts.push_back(contact1.get());
98 db_contacts.push_back(contact2.get());
99 UpdateMetadata db_metadata;
100 db_->SetContacts(db_contacts, db_metadata);
101
102 // Tell the GData service to report failure, initialize the store, and check
103 // that the contacts from the database are loaded.
104 gdata_service_->set_download_should_succeed(false);
105 store_->Init();
106 ContactPointers loaded_contacts;
107 store_->AppendContacts(&loaded_contacts);
108 EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()),
109 ContactsToString(loaded_contacts));
110 EXPECT_TRUE(test_api_->update_scheduled());
111 EXPECT_EQ(1, observer_.num_updates());
112
113 // Check that we can also grab the contact via its ID.
114 const Contact* loaded_contact1 = store_->GetContactByProviderId(kProviderId1);
115 ASSERT_TRUE(loaded_contact1);
116 EXPECT_EQ(ContactToString(*contact1), ContactToString(*loaded_contact1));
117
118 // We should get NULL if we request a nonexistent contact.
119 EXPECT_FALSE(store_->GetContactByProviderId("bogus_id"));
120 }
121
122 TEST_F(GoogleContactStoreTest, LoadFromGData) {
123 // Store two contacts in the GData service.
124 scoped_ptr<Contact> contact1(new Contact);
125 InitContact("provider1", "1", false, contact1.get());
126 scoped_ptr<Contact> contact2(new Contact);
127 InitContact("provider2", "2", false, contact2.get());
128 ContactPointers gdata_contacts;
129 gdata_contacts.push_back(contact1.get());
130 gdata_contacts.push_back(contact2.get());
131 gdata_service_->SetContacts(gdata_contacts, base::Time());
132
133 // Initialize the store and check that the contacts are loaded from GData.
134 store_->Init();
135 ContactPointers loaded_contacts;
136 store_->AppendContacts(&loaded_contacts);
137 EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()),
138 ContactsToString(loaded_contacts));
139 EXPECT_TRUE(test_api_->update_scheduled());
140 EXPECT_EQ(1, observer_.num_updates());
141
142 // The contacts should've been saved to the database, too.
143 EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()),
144 ContactsToString(db_->contacts()));
145 }
146
147 TEST_F(GoogleContactStoreTest, UpdateFromGData) {
148 scoped_ptr<Contact> contact1(new Contact);
149 InitContact("provider1", "1", false, contact1.get());
150 scoped_ptr<Contact> contact2(new Contact);
151 InitContact("provider2", "2", false, contact2.get());
152 scoped_ptr<Contact> contact3(new Contact);
153 InitContact("provider3", "3", false, contact3.get());
154
155 // Store the first two contacts in the database.
156 ContactPointers db_contacts;
157 db_contacts.push_back(contact1.get());
158 db_contacts.push_back(contact2.get());
159 UpdateMetadata db_metadata;
160 db_->SetContacts(db_contacts, db_metadata);
161
162 // Store all three in the GData service. We expect the update request to ask
163 // for all contacts updated one millisecond after the newest contact in the
164 // database.
165 ContactPointers gdata_contacts;
166 gdata_contacts.push_back(contact1.get());
167 gdata_contacts.push_back(contact2.get());
168 gdata_contacts.push_back(contact3.get());
169 gdata_service_->SetContacts(
170 gdata_contacts,
171 base::Time::FromInternalValue(contact2->update_time()) +
172 base::TimeDelta::FromMilliseconds(1));
173
174 // Check that the store ends up with all three contacts.
175 store_->Init();
176 ContactPointers loaded_contacts;
177 store_->AppendContacts(&loaded_contacts);
178 EXPECT_EQ(VarContactsToString(
179 3, contact1.get(), contact2.get(), contact3.get()),
180 ContactsToString(loaded_contacts));
181 EXPECT_EQ(2, observer_.num_updates());
182
183 // All three contacts should've been saved to the database.
184 EXPECT_EQ(VarContactsToString(
185 3, contact1.get(), contact2.get(), contact3.get()),
186 ContactsToString(db_->contacts()));
187 EXPECT_TRUE(test_api_->update_scheduled());
188 }
189
190 TEST_F(GoogleContactStoreTest, FetchUpdatedContacts) {
191 scoped_ptr<Contact> contact1(new Contact);
192 InitContact("provider1", "1", false, contact1.get());
193 scoped_ptr<Contact> contact2(new Contact);
194 InitContact("provider2", "2", false, contact2.get());
195 scoped_ptr<Contact> contact3(new Contact);
196 InitContact("provider3", "3", false, contact3.get());
197
198 // Tell the GData service to return all three contacts in response to a full
199 // update.
200 ContactPointers gdata_contacts;
201 gdata_contacts.push_back(contact1.get());
202 gdata_contacts.push_back(contact2.get());
203 gdata_contacts.push_back(contact3.get());
204 gdata_service_->SetContacts(gdata_contacts, base::Time());
205
206 store_->Init();
207 ContactPointers loaded_contacts;
208 store_->AppendContacts(&loaded_contacts);
209 EXPECT_EQ(ContactsToString(gdata_contacts),
210 ContactsToString(loaded_contacts));
211 EXPECT_EQ(ContactsToString(gdata_contacts),
212 ContactsToString(db_->contacts()));
213 EXPECT_TRUE(test_api_->update_scheduled());
214 EXPECT_EQ(1, observer_.num_updates());
215 observer_.reset_stats();
216
217 // Update the third contact.
218 contact3->set_full_name("new full name");
219 base::Time old_contact3_update_time =
220 base::Time::FromInternalValue(contact3->update_time());
221 contact3->set_update_time(
222 (old_contact3_update_time +
223 base::TimeDelta::FromSeconds(10)).ToInternalValue());
224 gdata_service_->SetContacts(
225 gdata_contacts,
226 old_contact3_update_time + base::TimeDelta::FromMilliseconds(1));
227
228 // Check that the updated contact is loaded (i.e. the store passed the
229 // correct minimum update time to the service).
230 test_api_->DoUpdate();
231 loaded_contacts.clear();
232 store_->AppendContacts(&loaded_contacts);
233 EXPECT_EQ(ContactsToString(gdata_contacts),
234 ContactsToString(loaded_contacts));
235 EXPECT_EQ(ContactsToString(gdata_contacts),
236 ContactsToString(db_->contacts()));
237 EXPECT_TRUE(test_api_->update_scheduled());
238 EXPECT_EQ(1, observer_.num_updates());
239 observer_.reset_stats();
240
241 // The next update should be based on the third contact's new update time.
242 contact3->set_full_name("yet another full name");
243 gdata_service_->SetContacts(
244 gdata_contacts,
245 base::Time::FromInternalValue(contact3->update_time()) +
246 base::TimeDelta::FromMilliseconds(1));
247 test_api_->DoUpdate();
248 loaded_contacts.clear();
249 store_->AppendContacts(&loaded_contacts);
250 EXPECT_EQ(ContactsToString(gdata_contacts),
251 ContactsToString(loaded_contacts));
252 EXPECT_EQ(ContactsToString(gdata_contacts),
253 ContactsToString(db_->contacts()));
254 EXPECT_TRUE(test_api_->update_scheduled());
255 EXPECT_EQ(1, observer_.num_updates());
256 }
257
258 TEST_F(GoogleContactStoreTest, DontReturnDeletedContacts) {
259 // Tell GData to return a single deleted contact.
260 const std::string kProviderId = "provider";
261 scoped_ptr<Contact> contact(new Contact);
262 InitContact(kProviderId, "1", true, contact.get());
263 ContactPointers gdata_contacts;
264 gdata_contacts.push_back(contact.get());
265 gdata_service_->SetContacts(gdata_contacts, base::Time());
266
267 // The contact shouldn't be returned by AppendContacts() or
268 // GetContactByProviderId().
269 store_->Init();
270 ContactPointers loaded_contacts;
271 store_->AppendContacts(&loaded_contacts);
272 EXPECT_TRUE(loaded_contacts.empty());
273 EXPECT_FALSE(store_->GetContactByProviderId(kProviderId));
274 }
275
276 // Test that we do a full refresh from GData if enough time has passed since the
277 // last refresh that we might've missed some contact deletions (see
278 // |kForceFullUpdateDays| in google_contact_store.cc).
279 TEST_F(GoogleContactStoreTest, FullRefreshAfterThirtyDays) {
280 base::Time::Exploded kInitTimeExploded = { 2012, 3, 0, 1, 16, 34, 56, 123 };
281 base::Time kInitTime = base::Time::FromUTCExploded(kInitTimeExploded);
282
283 base::Time kOldUpdateTime = kInitTime - base::TimeDelta::FromDays(31);
284 scoped_ptr<Contact> contact1(new Contact);
285 InitContact("provider1", "1", false, contact1.get());
286 contact1->set_update_time(kOldUpdateTime.ToInternalValue());
287 scoped_ptr<Contact> contact2(new Contact);
288 InitContact("provider2", "2", false, contact2.get());
289 contact2->set_update_time(kOldUpdateTime.ToInternalValue());
290
291 // Put both contacts in the database, along with metadata saying that the last
292 // successful update was 31 days in the past.
293 ContactPointers db_contacts;
294 db_contacts.push_back(contact1.get());
295 db_contacts.push_back(contact2.get());
296 UpdateMetadata db_metadata;
297 db_metadata.set_last_update_start_time(kOldUpdateTime.ToInternalValue());
298 db_->SetContacts(db_contacts, db_metadata);
299
300 // Tell the GData service to return only the first contact and to expect a
301 // full refresh (since it's been a long time since the last update).
302 ContactPointers gdata_contacts;
303 gdata_contacts.push_back(contact1.get());
304 gdata_service_->SetContacts(gdata_contacts, base::Time());
305
306 test_api_->set_current_time(kInitTime);
307 store_->Init();
308 ContactPointers loaded_contacts;
309 store_->AppendContacts(&loaded_contacts);
310 EXPECT_EQ(ContactsToString(gdata_contacts),
311 ContactsToString(loaded_contacts));
312 EXPECT_TRUE(test_api_->update_scheduled());
313
314 // Make GData return both contacts now in response to an incremental update.
315 gdata_contacts.clear();
316 contact2->set_update_time(kInitTime.ToInternalValue());
317 gdata_contacts.push_back(contact1.get());
318 gdata_contacts.push_back(contact2.get());
319 gdata_service_->SetContacts(
320 gdata_contacts, kOldUpdateTime + base::TimeDelta::FromMilliseconds(1));
321
322 // Advance the time by twenty days and check that the update is successful.
323 base::Time kFirstUpdateTime = kInitTime + base::TimeDelta::FromDays(20);
324 test_api_->set_current_time(kFirstUpdateTime);
325 test_api_->DoUpdate();
326 loaded_contacts.clear();
327 store_->AppendContacts(&loaded_contacts);
328 EXPECT_EQ(ContactsToString(gdata_contacts),
329 ContactsToString(loaded_contacts));
330
331 // After we advance the time by 31 days, we should do a full refresh again.
332 gdata_contacts.clear();
333 gdata_contacts.push_back(contact1.get());
334 gdata_service_->SetContacts(gdata_contacts, base::Time());
335 base::Time kSecondUpdateTime =
336 kFirstUpdateTime + base::TimeDelta::FromDays(31);
337 test_api_->set_current_time(kSecondUpdateTime);
338 test_api_->DoUpdate();
339 loaded_contacts.clear();
340 store_->AppendContacts(&loaded_contacts);
341 EXPECT_EQ(ContactsToString(gdata_contacts),
342 ContactsToString(loaded_contacts));
343 }
344
345 TEST_F(GoogleContactStoreTest, HandleDatabaseInitFailure) {
346 scoped_ptr<Contact> contact1(new Contact);
347 InitContact("provider1", "1", false, contact1.get());
348
349 // Store a contact in the database but make initialization fail.
350 ContactPointers db_contacts;
351 db_contacts.push_back(contact1.get());
352 UpdateMetadata db_metadata;
353 db_->SetContacts(db_contacts, db_metadata);
354 db_->set_init_success(false);
355
356 // Create a second contact and tell the GData service to return it.
357 scoped_ptr<Contact> contact2(new Contact);
358 InitContact("provider2", "2", false, contact2.get());
359 ContactPointers gdata_contacts;
360 gdata_contacts.push_back(contact2.get());
361 gdata_service_->SetContacts(gdata_contacts, base::Time());
362
363 // Initialize the store. We shouldn't get the first contact (since DB
364 // initialization failed) but we should still fetch the second one from GData
365 // and schedule an update.
366 store_->Init();
367 ContactPointers loaded_contacts;
368 store_->AppendContacts(&loaded_contacts);
369 EXPECT_EQ(ContactsToString(gdata_contacts),
370 ContactsToString(loaded_contacts));
371 EXPECT_TRUE(test_api_->update_scheduled());
372 }
373
374 } // namespace test
375 } // namespace contacts
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698