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