Index: chrome/browser/chromeos/contacts/google_contact_source_unittest.cc |
diff --git a/chrome/browser/chromeos/contacts/google_contact_source_unittest.cc b/chrome/browser/chromeos/contacts/google_contact_source_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6525934ec195f8c666a205639b045a31f134d9e9 |
--- /dev/null |
+++ b/chrome/browser/chromeos/contacts/google_contact_source_unittest.cc |
@@ -0,0 +1,247 @@ |
+// 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/chromeos/contacts/google_contact_source.h" |
+ |
+#include "base/bind.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
+#include "base/time.h" |
+#include "chrome/test/base/testing_profile.h" |
+#include "chrome/browser/chromeos/contacts/contact.h" |
+#include "chrome/browser/chromeos/contacts/contact_source_observer.h" |
+#include "chrome/browser/chromeos/contacts/contact_test_lib.h" |
+#include "chrome/browser/chromeos/contacts/fake_contact_database.h" |
+#include "chrome/browser/chromeos/gdata/fake_gdata_contacts_service.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 contacts { |
+namespace test { |
+ |
+// ContactSourceObserver implementation that just counts the number of times |
+// that it's been told that a source has been updated. |
+class TestContactSourceObserver : public ContactSourceObserver { |
+ public: |
+ TestContactSourceObserver() : num_updates_(0) {} |
+ ~TestContactSourceObserver() {} |
+ |
+ int num_updates() const { return num_updates_; } |
+ void reset_stats() { num_updates_ = 0; } |
+ |
+ // ContactSourceObserver overrides: |
+ void OnContactsUpdated(ContactSource* source) OVERRIDE { |
+ DCHECK(source); |
+ num_updates_++; |
+ } |
+ |
+ private: |
+ // Number of times that OnContactsUpdated() has been called. |
+ int num_updates_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestContactSourceObserver); |
+}; |
+ |
+class GoogleContactSourceTest : public testing::Test { |
+ public: |
+ GoogleContactSourceTest() : ui_thread_(BrowserThread::UI, &message_loop_) {} |
+ virtual ~GoogleContactSourceTest() {} |
+ |
+ protected: |
+ // testing::Test implementation. |
+ virtual void SetUp() OVERRIDE { |
+ testing::Test::SetUp(); |
+ profile_.reset(new TestingProfile); |
+ |
+ source_.reset(new GoogleContactSource(profile_.get())); |
+ source_->AddObserver(&observer_); |
+ |
+ test_api_.reset(new GoogleContactSource::TestAPI(source_.get())); |
+ |
+ db_ = new FakeContactDatabase; |
+ test_api_->SetDatabase(db_); |
+ |
+ gdata_service_ = new gdata::FakeGDataContactsService; |
+ test_api_->SetGDataService(gdata_service_); |
+ } |
+ |
+ TestContactSourceObserver* observer() { return &observer_; } |
+ GoogleContactSource* source() { return source_.get(); } |
+ GoogleContactSource::TestAPI* test_api() { return test_api_.get(); } |
+ FakeContactDatabase* db() { return db_; } |
+ gdata::FakeGDataContactsService* gdata_service() { return gdata_service_; } |
+ |
+ private: |
+ MessageLoopForUI message_loop_; |
+ content::TestBrowserThread ui_thread_; |
+ |
+ TestContactSourceObserver observer_; |
+ scoped_ptr<TestingProfile> profile_; |
+ scoped_ptr<GoogleContactSource> source_; |
+ scoped_ptr<GoogleContactSource::TestAPI> test_api_; |
+ |
+ FakeContactDatabase* db_; // not owned |
+ gdata::FakeGDataContactsService* gdata_service_; // not owned |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GoogleContactSourceTest); |
+}; |
+ |
+TEST_F(GoogleContactSourceTest, LoadFromDatabase) { |
+ // Store two contacts in the database. |
+ scoped_ptr<Contact> contact1(new Contact); |
+ InitContact("provider1", "1", false, contact1.get()); |
+ scoped_ptr<Contact> contact2(new Contact); |
+ InitContact("provider2", "2", false, contact2.get()); |
+ ContactPointers db_contacts; |
+ db_contacts.push_back(contact1.get()); |
+ db_contacts.push_back(contact2.get()); |
+ db()->SetContacts(db_contacts); |
+ |
+ // Tell the GData service to report failure, initialize the source, and check |
+ // that the contacts from the database are loaded. |
+ gdata_service()->set_download_should_succeed(false); |
+ source()->Init(); |
+ ContactPointers loaded_contacts; |
+ source()->AppendContacts(&loaded_contacts); |
+ EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()), |
+ ContactsToString(loaded_contacts)); |
+ EXPECT_TRUE(test_api()->update_scheduled()); |
+ EXPECT_EQ(1, observer()->num_updates()); |
+} |
+ |
+TEST_F(GoogleContactSourceTest, LoadFromGData) { |
+ // Store two contacts in the GData service. |
+ scoped_ptr<Contact> contact1(new Contact); |
+ InitContact("provider1", "1", false, contact1.get()); |
+ scoped_ptr<Contact> contact2(new Contact); |
+ InitContact("provider2", "2", false, contact2.get()); |
+ ContactPointers gdata_contacts; |
+ gdata_contacts.push_back(contact1.get()); |
+ gdata_contacts.push_back(contact2.get()); |
+ gdata_service()->SetContacts(gdata_contacts, base::Time()); |
+ |
+ // Initialize the source and check that the contacts are loaded from GData. |
+ source()->Init(); |
+ ContactPointers loaded_contacts; |
+ source()->AppendContacts(&loaded_contacts); |
+ EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()), |
+ ContactsToString(loaded_contacts)); |
+ EXPECT_TRUE(test_api()->update_scheduled()); |
+ EXPECT_EQ(1, observer()->num_updates()); |
+ |
+ // The contacts should've been saved to the database, too. |
+ EXPECT_EQ(VarContactsToString(2, contact1.get(), contact2.get()), |
+ ContactsToString(db()->contacts())); |
+} |
+ |
+TEST_F(GoogleContactSourceTest, UpdateFromGData) { |
+ scoped_ptr<Contact> contact1(new Contact); |
+ InitContact("provider1", "1", false, contact1.get()); |
+ scoped_ptr<Contact> contact2(new Contact); |
+ InitContact("provider2", "2", false, contact2.get()); |
+ scoped_ptr<Contact> contact3(new Contact); |
+ InitContact("provider3", "3", false, contact3.get()); |
+ |
+ // Store the first two contacts in the database. |
+ ContactPointers db_contacts; |
+ db_contacts.push_back(contact1.get()); |
+ db_contacts.push_back(contact2.get()); |
+ db()->SetContacts(db_contacts); |
+ |
+ // Store all three in the GData service. We expect the update request to ask |
+ // for all contacts updated one millisecond after the newest contact in the |
+ // database. |
+ ContactPointers gdata_contacts; |
+ gdata_contacts.push_back(contact1.get()); |
+ gdata_contacts.push_back(contact2.get()); |
+ gdata_contacts.push_back(contact3.get()); |
+ gdata_service()->SetContacts( |
+ gdata_contacts, |
+ contact2->update_time + base::TimeDelta::FromMilliseconds(1)); |
+ |
+ // Check that the source ends up with all three contacts. |
+ source()->Init(); |
+ ContactPointers loaded_contacts; |
+ source()->AppendContacts(&loaded_contacts); |
+ EXPECT_EQ(VarContactsToString( |
+ 3, contact1.get(), contact2.get(), contact3.get()), |
+ ContactsToString(loaded_contacts)); |
+ EXPECT_EQ(2, observer()->num_updates()); |
+ |
+ // All three contacts should've been saved to the database. |
+ EXPECT_EQ(VarContactsToString( |
+ 3, contact1.get(), contact2.get(), contact3.get()), |
+ ContactsToString(db()->contacts())); |
+ EXPECT_TRUE(test_api()->update_scheduled()); |
+} |
+ |
+TEST_F(GoogleContactSourceTest, FetchUpdatedContacts) { |
+ scoped_ptr<Contact> contact1(new Contact); |
+ InitContact("provider1", "1", false, contact1.get()); |
+ scoped_ptr<Contact> contact2(new Contact); |
+ InitContact("provider2", "2", false, contact2.get()); |
+ scoped_ptr<Contact> contact3(new Contact); |
+ InitContact("provider3", "3", false, contact3.get()); |
+ |
+ // Tell the GData service to return all three contacts in response to a full |
+ // update. |
+ ContactPointers gdata_contacts; |
+ gdata_contacts.push_back(contact1.get()); |
+ gdata_contacts.push_back(contact2.get()); |
+ gdata_contacts.push_back(contact3.get()); |
+ gdata_service()->SetContacts(gdata_contacts, base::Time()); |
+ |
+ source()->Init(); |
+ ContactPointers loaded_contacts; |
+ source()->AppendContacts(&loaded_contacts); |
+ EXPECT_EQ(ContactsToString(gdata_contacts), |
+ ContactsToString(loaded_contacts)); |
+ EXPECT_EQ(ContactsToString(gdata_contacts), |
+ ContactsToString(db()->contacts())); |
+ EXPECT_TRUE(test_api()->update_scheduled()); |
+ EXPECT_EQ(1, observer()->num_updates()); |
+ observer()->reset_stats(); |
+ |
+ // Update the third contact. |
+ contact3->full_name = "new full name"; |
+ base::Time old_contact3_update_time = contact3->update_time; |
+ contact3->update_time += base::TimeDelta::FromSeconds(10); |
+ gdata_service()->SetContacts( |
+ gdata_contacts, |
+ old_contact3_update_time + base::TimeDelta::FromMilliseconds(1)); |
+ |
+ // Check that the updated contact is loaded (i.e. the source passed the |
+ // correct minimum update time to the service). |
+ test_api()->DoUpdate(); |
+ loaded_contacts.clear(); |
+ source()->AppendContacts(&loaded_contacts); |
+ EXPECT_EQ(ContactsToString(gdata_contacts), |
+ ContactsToString(loaded_contacts)); |
+ EXPECT_EQ(ContactsToString(gdata_contacts), |
+ ContactsToString(db()->contacts())); |
+ EXPECT_TRUE(test_api()->update_scheduled()); |
+ EXPECT_EQ(1, observer()->num_updates()); |
+ observer()->reset_stats(); |
+ |
+ // The next update should be based on the third contact's new update time. |
+ contact3->full_name = "yet another full name"; |
+ gdata_service()->SetContacts( |
+ gdata_contacts, |
+ contact3->update_time + base::TimeDelta::FromMilliseconds(1)); |
+ test_api()->DoUpdate(); |
+ loaded_contacts.clear(); |
+ source()->AppendContacts(&loaded_contacts); |
+ EXPECT_EQ(ContactsToString(gdata_contacts), |
+ ContactsToString(loaded_contacts)); |
+ EXPECT_EQ(ContactsToString(gdata_contacts), |
+ ContactsToString(db()->contacts())); |
+ EXPECT_TRUE(test_api()->update_scheduled()); |
+ EXPECT_EQ(1, observer()->num_updates()); |
+} |
+ |
+} // namespace test |
+} // namespace contacts |