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
14using ::testing::_;
15using ::testing::Return;
16using ::testing::DoDefault;
17using ::testing::ReturnRef;
18using ::testing::Pointee;
19using ::testing::Ref;
20using ::testing::Invoke;
21class AutofillProfile;
22
23using 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.
28class 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
84class 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
95TEST_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      &current_profiles,
132      NULL,
133      NULL,
134      NULL);
135
136  EXPECT_EQ((unsigned int)1, current_profiles.size());
137}
138
139TEST_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                                             &current_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      &current_profiles,
169      NULL,
170      NULL,
171      NULL);
172}
173
174TEST_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
215TEST_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
234TEST_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