1 // Copyright (c) 2011 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 "base/utf_string_conversions.h" 6 #include "chrome/browser/sync/engine/read_node_mock.h" 7 #include "chrome/browser/sync/engine/syncapi_mock.h" 8 #include "chrome/browser/sync/glue/autofill_profile_model_associator.h" 9 #include "chrome/browser/sync/syncable/syncable.h" 10 #include "chrome/browser/sync/syncable/syncable_mock.h" 11 #include "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 using ::testing::_; 15 using ::testing::Return; 16 using ::testing::DoDefault; 17 using ::testing::ReturnRef; 18 using ::testing::Pointee; 19 using ::testing::Ref; 20 using ::testing::Invoke; 21 class AutofillProfile; 22 23 using browser_sync::AutofillProfileModelAssociator; 24 25 // Note this is not a generic mock. This is a mock used to 26 // test AutofillProfileModelAssociator class itself by mocking 27 // other functions that are called by the functions we need to test. 28 class MockAutofillProfileModelAssociator 29 : public AutofillProfileModelAssociator { 30 public: 31 MockAutofillProfileModelAssociator() { 32 } 33 virtual ~MockAutofillProfileModelAssociator() {} 34 bool TraverseAndAssociateChromeAutofillProfilesWrapper( 35 sync_api::WriteTransaction* write_trans, 36 const sync_api::ReadNode& autofill_root, 37 const std::vector<AutofillProfile*>& all_profiles_from_db, 38 std::set<std::string>* current_profiles, 39 std::vector<AutofillProfile*>* updated_profiles, 40 std::vector<AutofillProfile*>* new_profiles, 41 std::vector<std::string>* profiles_to_delete) { 42 return TraverseAndAssociateChromeAutofillProfiles(write_trans, 43 autofill_root, 44 all_profiles_from_db, 45 current_profiles, 46 updated_profiles, 47 new_profiles, 48 profiles_to_delete); 49 } 50 MOCK_METHOD3(AddNativeProfileIfNeeded, 51 void(const sync_pb::AutofillProfileSpecifics&, 52 DataBundle*, 53 const sync_api::ReadNode&)); 54 MOCK_METHOD2(OverwriteProfileWithServerData, 55 bool(AutofillProfile*, 56 const sync_pb::AutofillProfileSpecifics&)); 57 MOCK_METHOD6(MakeNewAutofillProfileSyncNodeIfNeeded, 58 bool(sync_api::WriteTransaction*, 59 const sync_api::BaseNode&, 60 const AutofillProfile&, 61 std::vector<AutofillProfile*>*, 62 std::set<std::string>*, 63 std::vector<std::string>*)); 64 MOCK_METHOD2(Associate, void(const std::string*, int64)); 65 66 bool TraverseAndAssociateAllSyncNodesWrapper( 67 sync_api::WriteTransaction *trans, 68 const sync_api::ReadNode &autofill_root, 69 browser_sync::AutofillProfileModelAssociator::DataBundle *bundle) { 70 return TraverseAndAssociateAllSyncNodes(trans, autofill_root, bundle); 71 } 72 73 void AddNativeProfileIfNeededWrapper( 74 const sync_pb::AutofillProfileSpecifics& profile, 75 DataBundle* bundle, 76 const sync_api::ReadNode& node) { 77 AutofillProfileModelAssociator::AddNativeProfileIfNeeded( 78 profile, 79 bundle, 80 node); 81 } 82 }; 83 84 class AutofillProfileModelAssociatorTest : public testing::Test { 85 public: 86 AutofillProfileModelAssociatorTest() 87 : db_thread_(BrowserThread::DB, &message_loop_) {} 88 89 protected: 90 MessageLoop message_loop_; 91 BrowserThread db_thread_; 92 MockAutofillProfileModelAssociator associator_; 93 }; 94 95 TEST_F(AutofillProfileModelAssociatorTest, 96 TestAssociateProfileInWebDBWithSyncDB) { 97 ScopedVector<AutofillProfile> profiles_from_web_db; 98 std::string guid = "EDC609ED-7EEE-4F27-B00C-423242A9C44B"; 99 100 sync_pb::EntitySpecifics specifics; 101 MockDirectory mock_directory; 102 sync_pb::AutofillProfileSpecifics *profile_specifics = 103 specifics.MutableExtension(sync_pb::autofill_profile); 104 105 profile_specifics->set_guid(guid); 106 107 std::set<std::string> current_profiles; 108 109 // This will be released inside the function 110 // TraverseAndAssociateChromeAutofillProfiles 111 AutofillProfile *profile = new AutofillProfile(guid); 112 113 // Set up the entry kernel with what we want. 114 EntryKernel kernel; 115 kernel.put(syncable::SPECIFICS, specifics); 116 kernel.put(syncable::META_HANDLE, 1); 117 118 MockWriteTransaction write_trans(&mock_directory); 119 EXPECT_CALL(mock_directory, GetEntryByClientTag(_)) 120 .WillOnce(Return(&kernel)); 121 122 sync_api::ReadNode read_node(&write_trans); 123 124 EXPECT_CALL(associator_, Associate(Pointee(guid), 1)); 125 126 profiles_from_web_db.push_back(profile); 127 128 associator_.TraverseAndAssociateChromeAutofillProfilesWrapper(&write_trans, 129 read_node, 130 profiles_from_web_db.get(), 131 ¤t_profiles, 132 NULL, 133 NULL, 134 NULL); 135 136 EXPECT_EQ((unsigned int)1, current_profiles.size()); 137 } 138 139 TEST_F(AutofillProfileModelAssociatorTest, TestAssociatingMissingWebDBProfile) { 140 ScopedVector<AutofillProfile> profiles_from_web_db; 141 MockDirectory mock_directory; 142 143 MockWriteTransaction write_trans(&mock_directory); 144 EXPECT_CALL(mock_directory, 145 GetEntryByClientTag(_)) 146 .WillOnce(Return(reinterpret_cast<EntryKernel*>(NULL))); 147 148 sync_api::ReadNode autofill_root(&write_trans); 149 150 std::string guid = "EDC609ED-7EEE-4F27-B00C-423242A9C44A"; 151 std::set<std::string> current_profiles; 152 AutofillProfile *profile = new AutofillProfile(guid); 153 154 EXPECT_CALL(associator_, 155 MakeNewAutofillProfileSyncNodeIfNeeded(&write_trans, 156 Ref(autofill_root), 157 Ref(*profile), 158 _, 159 ¤t_profiles, 160 NULL)) 161 .WillOnce(Return(true)); 162 163 profiles_from_web_db.push_back(profile); 164 165 associator_.TraverseAndAssociateChromeAutofillProfilesWrapper(&write_trans, 166 autofill_root, 167 profiles_from_web_db.get(), 168 ¤t_profiles, 169 NULL, 170 NULL, 171 NULL); 172 } 173 174 TEST_F(AutofillProfileModelAssociatorTest, 175 TestAssociateProfileInSyncDBWithWebDB) { 176 ReadNodeMock autofill_root; 177 178 // The constrcutor itself will initialize the id to root. 179 syncable::Id root_id; 180 181 sync_pb::EntitySpecifics specifics; 182 MockDirectory mock_directory; 183 sync_pb::AutofillProfileSpecifics *profile_specifics = 184 specifics.MutableExtension(sync_pb::autofill_profile); 185 186 profile_specifics->set_guid("abc"); 187 188 // Set up the entry kernel with what we want. 189 EntryKernel kernel; 190 kernel.put(syncable::SPECIFICS, specifics); 191 kernel.put(syncable::META_HANDLE, 1); 192 kernel.put(syncable::ID, root_id); 193 194 MockWriteTransaction write_trans(&mock_directory); 195 196 browser_sync::AutofillProfileModelAssociator::DataBundle bundle; 197 198 EXPECT_CALL(autofill_root, GetFirstChildId()) 199 .WillOnce(Return(1)); 200 201 EXPECT_CALL(mock_directory, 202 GetEntryByHandle(_)) 203 .WillOnce(Return(&kernel)); 204 205 EXPECT_CALL(associator_, 206 AddNativeProfileIfNeeded(_, 207 &bundle, 208 _)); 209 210 associator_.TraverseAndAssociateAllSyncNodesWrapper(&write_trans, 211 autofill_root, 212 &bundle); 213 } 214 215 TEST_F(AutofillProfileModelAssociatorTest, TestDontNeedToAddNativeProfile) { 216 ::testing::StrictMock<MockAutofillProfileModelAssociator> associator; 217 sync_pb::AutofillProfileSpecifics profile_specifics; 218 ReadNodeMock read_node; 219 std::string guid = "EDC609ED-7EEE-4F27-B00C-423242A9C44C"; 220 std::set<std::string> current_profiles; 221 browser_sync::AutofillProfileModelAssociator::DataBundle bundle; 222 223 profile_specifics.set_guid(guid); 224 225 bundle.current_profiles.insert(guid); 226 227 // We have no expectations to set. We have used a strict mock. 228 // If the profile is already present no other function 229 // should be called. 230 associator.AddNativeProfileIfNeededWrapper(profile_specifics, &bundle, 231 read_node); 232 } 233 234 TEST_F(AutofillProfileModelAssociatorTest, TestNeedToAddNativeProfile) { 235 sync_pb::AutofillProfileSpecifics profile_specifics; 236 ReadNodeMock read_node; 237 std::string guid = "EDC609ED-7EEE-4F27-B00C-423242A9C44D"; 238 std::set<std::string> current_profiles; 239 browser_sync::AutofillProfileModelAssociator::DataBundle bundle; 240 std::string first_name = "lingesh"; 241 242 profile_specifics.set_guid(guid); 243 profile_specifics.set_name_first(first_name); 244 245 EXPECT_CALL(read_node, GetId()) 246 .WillOnce(Return(1)); 247 248 EXPECT_CALL(associator_, 249 Associate(Pointee(guid), 1)); 250 251 associator_.AddNativeProfileIfNeededWrapper( 252 profile_specifics, 253 &bundle, 254 read_node); 255 256 EXPECT_EQ(bundle.new_profiles.size(), (unsigned int)1); 257 EXPECT_EQ(bundle.new_profiles.front()->GetInfo(NAME_FIRST), 258 UTF8ToUTF16(first_name)); 259 } 260 261