web_data_service_unittest.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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 <string>
6#include <vector>
7
8#include "base/basictypes.h"
9#include "base/file_util.h"
10#include "base/message_loop.h"
11#include "base/path_service.h"
12#include "base/ref_counted.h"
13#include "base/scoped_ptr.h"
14#include "base/string16.h"
15#include "base/string_util.h"
16#include "base/time.h"
17#include "base/waitable_event.h"
18#include "chrome/browser/autofill/autofill_profile.h"
19#include "chrome/browser/autofill/credit_card.h"
20#include "chrome/browser/chrome_thread.h"
21#include "chrome/browser/webdata/autofill_change.h"
22#include "chrome/browser/webdata/autofill_entry.h"
23#include "chrome/browser/webdata/web_data_service.h"
24#include "chrome/browser/webdata/web_data_service_test_util.h"
25#include "chrome/common/chrome_paths.h"
26#include "chrome/common/notification_details.h"
27#include "chrome/common/notification_service.h"
28#include "chrome/common/notification_type.h"
29#include "chrome/test/thread_observer_helper.h"
30#include "testing/gmock/include/gmock/gmock.h"
31#include "testing/gtest/include/gtest/gtest.h"
32#include "webkit/glue/form_field.h"
33
34using base::Time;
35using base::TimeDelta;
36using base::WaitableEvent;
37using testing::_;
38using testing::DoDefault;
39using testing::ElementsAreArray;
40using testing::Pointee;
41using testing::Property;
42
43typedef std::vector<AutofillChange> AutofillChangeList;
44
45static const int kWebDataServiceTimeoutSeconds = 8;
46
47ACTION_P(SignalEvent, event) {
48  event->Signal();
49}
50
51class AutofillDBThreadObserverHelper : public DBThreadObserverHelper {
52 protected:
53  virtual void RegisterObservers() {
54    registrar_.Add(&observer_,
55                   NotificationType::AUTOFILL_ENTRIES_CHANGED,
56                   NotificationService::AllSources());
57    registrar_.Add(&observer_,
58                   NotificationType::AUTOFILL_PROFILE_CHANGED,
59                   NotificationService::AllSources());
60    registrar_.Add(&observer_,
61                   NotificationType::AUTOFILL_CREDIT_CARD_CHANGED,
62                   NotificationService::AllSources());
63  }
64};
65
66class WebDataServiceTest : public testing::Test {
67 public:
68  WebDataServiceTest()
69      : ui_thread_(ChromeThread::UI, &message_loop_),
70        db_thread_(ChromeThread::DB) {}
71
72 protected:
73  virtual void SetUp() {
74    db_thread_.Start();
75
76    PathService::Get(chrome::DIR_TEST_DATA, &profile_dir_);
77    const std::string test_profile = "WebDataServiceTest";
78    profile_dir_ = profile_dir_.AppendASCII(test_profile);
79    file_util::Delete(profile_dir_, true);
80    file_util::CreateDirectory(profile_dir_);
81    wds_ = new WebDataService();
82    wds_->Init(profile_dir_);
83  }
84
85  virtual void TearDown() {
86    if (wds_.get())
87      wds_->Shutdown();
88    file_util::Delete(profile_dir_, true);
89
90    db_thread_.Stop();
91    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
92    MessageLoop::current()->Run();
93  }
94
95  MessageLoopForUI message_loop_;
96  ChromeThread ui_thread_;
97  ChromeThread db_thread_;
98  FilePath profile_dir_;
99  scoped_refptr<WebDataService> wds_;
100};
101
102class WebDataServiceAutofillTest : public WebDataServiceTest {
103 public:
104  WebDataServiceAutofillTest()
105      : WebDataServiceTest(),
106        unique_id1_(1),
107        unique_id2_(2),
108        test_timeout_(TimeDelta::FromSeconds(kWebDataServiceTimeoutSeconds)),
109        done_event_(false, false) {}
110
111 protected:
112  virtual void SetUp() {
113    WebDataServiceTest::SetUp();
114    name1_ = ASCIIToUTF16("name1");
115    name2_ = ASCIIToUTF16("name2");
116    value1_ = ASCIIToUTF16("value1");
117    value2_ = ASCIIToUTF16("value2");
118    observer_helper_ = new AutofillDBThreadObserverHelper();
119    observer_helper_->Init();
120  }
121
122  virtual void TearDown() {
123    // Release this first so it can get destructed on the db thread.
124    observer_helper_ = NULL;
125    WebDataServiceTest::TearDown();
126  }
127
128  void AppendFormField(const string16& name,
129                       const string16& value,
130                       std::vector<webkit_glue::FormField>* form_fields) {
131    form_fields->push_back(
132        webkit_glue::FormField(string16(),
133                               name,
134                               value,
135                               string16(),
136                               0));
137  }
138
139  string16 name1_;
140  string16 name2_;
141  string16 value1_;
142  string16 value2_;
143  int unique_id1_, unique_id2_;
144  const TimeDelta test_timeout_;
145  scoped_refptr<AutofillDBThreadObserverHelper> observer_helper_;
146  WaitableEvent done_event_;
147};
148
149TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
150  const AutofillChange expected_changes[] = {
151    AutofillChange(AutofillChange::ADD, AutofillKey(name1_, value1_)),
152    AutofillChange(AutofillChange::ADD, AutofillKey(name2_, value2_))
153  };
154
155  // This will verify that the correct notification is triggered,
156  // passing the correct list of autofill keys in the details.
157  EXPECT_CALL(
158      *observer_helper_->observer(),
159      Observe(NotificationType(NotificationType::AUTOFILL_ENTRIES_CHANGED),
160              Source<WebDataService>(wds_.get()),
161              Property(&Details<const AutofillChangeList>::ptr,
162                       Pointee(ElementsAreArray(expected_changes))))).
163      WillOnce(SignalEvent(&done_event_));
164
165  std::vector<webkit_glue::FormField> form_fields;
166  AppendFormField(name1_, value1_, &form_fields);
167  AppendFormField(name2_, value2_, &form_fields);
168  wds_->AddFormFields(form_fields);
169
170  // The event will be signaled when the mock observer is notified.
171  done_event_.TimedWait(test_timeout_);
172
173  AutofillWebDataServiceConsumer<std::vector<string16> > consumer;
174  WebDataService::Handle handle;
175  static const int limit = 10;
176  handle = wds_->GetFormValuesForElementName(
177      name1_, string16(), limit, &consumer);
178
179  // The message loop will exit when the consumer is called.
180  MessageLoop::current()->Run();
181
182  EXPECT_EQ(handle, consumer.handle());
183  ASSERT_EQ(1U, consumer.result().size());
184  EXPECT_EQ(value1_, consumer.result()[0]);
185}
186
187TEST_F(WebDataServiceAutofillTest, FormFillRemoveOne) {
188  // First add some values to autofill.
189  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
190      WillOnce(SignalEvent(&done_event_));
191  std::vector<webkit_glue::FormField> form_fields;
192  AppendFormField(name1_, value1_, &form_fields);
193  wds_->AddFormFields(form_fields);
194
195  // The event will be signaled when the mock observer is notified.
196  done_event_.TimedWait(test_timeout_);
197
198  // This will verify that the correct notification is triggered,
199  // passing the correct list of autofill keys in the details.
200  const AutofillChange expected_changes[] = {
201    AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_))
202  };
203  EXPECT_CALL(
204      *observer_helper_->observer(),
205      Observe(NotificationType(NotificationType::AUTOFILL_ENTRIES_CHANGED),
206              Source<WebDataService>(wds_.get()),
207              Property(&Details<const AutofillChangeList>::ptr,
208                       Pointee(ElementsAreArray(expected_changes))))).
209      WillOnce(SignalEvent(&done_event_));
210  wds_->RemoveFormValueForElementName(name1_, value1_);
211
212  // The event will be signaled when the mock observer is notified.
213  done_event_.TimedWait(test_timeout_);
214}
215
216TEST_F(WebDataServiceAutofillTest, FormFillRemoveMany) {
217  TimeDelta one_day(TimeDelta::FromDays(1));
218  Time t = Time::Now();
219
220  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
221      WillOnce(SignalEvent(&done_event_));
222  std::vector<webkit_glue::FormField> form_fields;
223  AppendFormField(name1_, value1_, &form_fields);
224  AppendFormField(name2_, value2_, &form_fields);
225  wds_->AddFormFields(form_fields);
226
227  // The event will be signaled when the mock observer is notified.
228  done_event_.TimedWait(test_timeout_);
229
230  // This will verify that the correct notification is triggered,
231  // passing the correct list of autofill keys in the details.
232  const AutofillChange expected_changes[] = {
233    AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_)),
234    AutofillChange(AutofillChange::REMOVE, AutofillKey(name2_, value2_))
235  };
236  EXPECT_CALL(
237      *observer_helper_->observer(),
238      Observe(NotificationType(NotificationType::AUTOFILL_ENTRIES_CHANGED),
239              Source<WebDataService>(wds_.get()),
240              Property(&Details<const AutofillChangeList>::ptr,
241                       Pointee(ElementsAreArray(expected_changes))))).
242      WillOnce(SignalEvent(&done_event_));
243  wds_->RemoveFormElementsAddedBetween(t, t + one_day);
244
245  // The event will be signaled when the mock observer is notified.
246  done_event_.TimedWait(test_timeout_);
247}
248
249TEST_F(WebDataServiceAutofillTest, ProfileAdd) {
250  AutoFillProfile profile(name1_, unique_id1_);
251  const AutofillProfileChange expected_change(
252      AutofillProfileChange::ADD, name1_, &profile, string16());
253
254  EXPECT_CALL(
255      *observer_helper_->observer(),
256      Observe(NotificationType(NotificationType::AUTOFILL_PROFILE_CHANGED),
257              Source<WebDataService>(wds_.get()),
258              Property(&Details<const AutofillProfileChange>::ptr,
259                       Pointee(expected_change)))).
260      WillOnce(SignalEvent(&done_event_));
261
262  wds_->AddAutoFillProfile(profile);
263  done_event_.TimedWait(test_timeout_);
264}
265
266TEST_F(WebDataServiceAutofillTest, ProfileRemove) {
267  AutoFillProfile profile(name1_, unique_id1_);
268
269  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
270      WillOnce(SignalEvent(&done_event_));
271  wds_->AddAutoFillProfile(profile);
272  done_event_.TimedWait(test_timeout_);
273
274  const AutofillProfileChange expected_change(
275      AutofillProfileChange::REMOVE, name1_, NULL, string16());
276  EXPECT_CALL(
277      *observer_helper_->observer(),
278      Observe(NotificationType(NotificationType::AUTOFILL_PROFILE_CHANGED),
279              Source<WebDataService>(wds_.get()),
280              Property(&Details<const AutofillProfileChange>::ptr,
281                       Pointee(expected_change)))).
282      WillOnce(SignalEvent(&done_event_));
283
284  wds_->RemoveAutoFillProfile(profile.unique_id());
285  done_event_.TimedWait(test_timeout_);
286}
287
288TEST_F(WebDataServiceAutofillTest, ProfileUpdate) {
289  AutoFillProfile profile1(name1_, unique_id1_);
290  AutoFillProfile profile2(name2_, unique_id2_);
291
292  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
293      Times(2).
294      WillOnce(DoDefault()).
295      WillOnce(SignalEvent(&done_event_));
296  wds_->AddAutoFillProfile(profile1);
297  wds_->AddAutoFillProfile(profile2);
298
299  done_event_.TimedWait(test_timeout_);
300
301  AutoFillProfile profile1_delta(profile1);
302  string16 new_label(ASCIIToUTF16("new_label!"));
303  profile1_delta.set_label(new_label);
304  const AutofillProfileChange expected_change(
305      AutofillProfileChange::UPDATE, new_label, &profile1_delta, name1_);
306
307  EXPECT_CALL(
308      *observer_helper_->observer(),
309      Observe(NotificationType(NotificationType::AUTOFILL_PROFILE_CHANGED),
310              Source<WebDataService>(wds_.get()),
311              Property(&Details<const AutofillProfileChange>::ptr,
312                       Pointee(expected_change)))).
313      WillOnce(SignalEvent(&done_event_));
314
315  wds_->UpdateAutoFillProfile(profile1_delta);
316  done_event_.TimedWait(test_timeout_);
317}
318
319TEST_F(WebDataServiceAutofillTest, CreditAdd) {
320  CreditCard card(name1_, unique_id1_);
321  const AutofillCreditCardChange expected_change(
322      AutofillCreditCardChange::ADD, name1_, &card);
323
324  EXPECT_CALL(
325      *observer_helper_->observer(),
326      Observe(NotificationType(NotificationType::AUTOFILL_CREDIT_CARD_CHANGED),
327              Source<WebDataService>(wds_.get()),
328              Property(&Details<const AutofillCreditCardChange>::ptr,
329                       Pointee(expected_change)))).
330      WillOnce(SignalEvent(&done_event_));
331
332  wds_->AddCreditCard(card);
333  done_event_.TimedWait(test_timeout_);
334}
335
336TEST_F(WebDataServiceAutofillTest, CreditRemove) {
337  CreditCard card(name1_, unique_id1_);
338  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
339      WillOnce(SignalEvent(&done_event_));
340  wds_->AddCreditCard(card);
341  done_event_.TimedWait(test_timeout_);
342
343  const AutofillCreditCardChange expected_change(
344      AutofillCreditCardChange::REMOVE, name1_, NULL);
345
346  EXPECT_CALL(
347      *observer_helper_->observer(),
348      Observe(NotificationType(NotificationType::AUTOFILL_CREDIT_CARD_CHANGED),
349              Source<WebDataService>(wds_.get()),
350              Property(&Details<const AutofillCreditCardChange>::ptr,
351                       Pointee(expected_change)))).
352      WillOnce(SignalEvent(&done_event_));
353
354  wds_->RemoveCreditCard(card.unique_id());
355  done_event_.TimedWait(test_timeout_);
356}
357
358TEST_F(WebDataServiceAutofillTest, CreditUpdate) {
359  CreditCard card1(name1_, unique_id1_);
360  CreditCard card2(name2_, unique_id2_);
361
362  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
363      Times(2).
364      WillOnce(DoDefault()).
365      WillOnce(SignalEvent(&done_event_));
366  wds_->AddCreditCard(card1);
367  wds_->AddCreditCard(card2);
368  done_event_.TimedWait(test_timeout_);
369
370  CreditCard card1_delta(card1);
371  card1_delta.set_label(ASCIIToUTF16("new_label!"));
372  const AutofillCreditCardChange expected_change(
373      AutofillCreditCardChange::UPDATE, name1_, &card1_delta);
374
375  EXPECT_CALL(
376      *observer_helper_->observer(),
377      Observe(NotificationType(NotificationType::AUTOFILL_CREDIT_CARD_CHANGED),
378              Source<WebDataService>(wds_.get()),
379              Property(&Details<const AutofillCreditCardChange>::ptr,
380                       Pointee(expected_change)))).
381      WillOnce(SignalEvent(&done_event_));
382
383  wds_->UpdateCreditCard(card1_delta);
384  done_event_.TimedWait(test_timeout_);
385}
386