- add sources.
[platform/framework/web/crosswalk.git] / src / components / autofill / core / browser / autofill_download_unittest.cc
1 // Copyright 2013 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 <list>
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/test_timeouts.h"
11 #include "chrome/test/base/testing_profile.h"
12 #include "components/autofill/core/browser/autofill_download.h"
13 #include "components/autofill/core/browser/autofill_field.h"
14 #include "components/autofill/core/browser/autofill_metrics.h"
15 #include "components/autofill/core/browser/autofill_type.h"
16 #include "components/autofill/core/browser/form_structure.h"
17 #include "components/autofill/core/common/form_data.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "net/url_request/test_url_fetcher_factory.h"
20 #include "net/url_request/url_request_status.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/WebKit/public/web/WebInputElement.h"
24
25 using WebKit::WebInputElement;
26
27 namespace autofill {
28
29 namespace {
30
31 class MockAutofillMetrics : public AutofillMetrics {
32  public:
33   MockAutofillMetrics() {}
34   MOCK_CONST_METHOD1(LogServerQueryMetric, void(ServerQueryMetric metric));
35
36  private:
37   DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
38 };
39
40 // Call |fetcher->OnURLFetchComplete()| as the URLFetcher would when
41 // a response is received.  Params allow caller to set fake status.
42 void FakeOnURLFetchComplete(net::TestURLFetcher* fetcher,
43                             int response_code,
44                             const std::string& response_body) {
45   fetcher->set_url(GURL());
46   fetcher->set_status(net::URLRequestStatus());
47   fetcher->set_response_code(response_code);
48   fetcher->SetResponseString(response_body);
49
50   fetcher->delegate()->OnURLFetchComplete(fetcher);
51 }
52
53 }  // namespace
54
55 // This tests AutofillDownloadManager. AutofillDownloadTest implements
56 // AutofillDownloadManager::Observer and creates an instance of
57 // AutofillDownloadManager. Then it records responses to different initiated
58 // requests, which are verified later. To mock network requests
59 // TestURLFetcherFactory is used, which creates URLFetchers that do not
60 // go over the wire, but allow calling back HTTP responses directly.
61 // The responses in test are out of order and verify: successful query request,
62 // successful upload request, failed upload request.
63 class AutofillDownloadTest : public AutofillDownloadManager::Observer,
64                              public testing::Test {
65  public:
66   AutofillDownloadTest()
67       : download_manager_(&profile_, this) {
68   }
69
70   void LimitCache(size_t cache_size) {
71     download_manager_.set_max_form_cache_size(cache_size);
72   }
73
74   // AutofillDownloadManager::Observer implementation.
75   virtual void OnLoadedServerPredictions(
76       const std::string& response_xml) OVERRIDE {
77     ResponseData response;
78     response.response = response_xml;
79     response.type_of_response = QUERY_SUCCESSFULL;
80     responses_.push_back(response);
81   }
82
83   virtual void OnUploadedPossibleFieldTypes() OVERRIDE {
84     ResponseData response;
85     response.type_of_response = UPLOAD_SUCCESSFULL;
86     responses_.push_back(response);
87   }
88
89   virtual void OnServerRequestError(
90       const std::string& form_signature,
91       AutofillDownloadManager::AutofillRequestType request_type,
92       int http_error) OVERRIDE {
93     ResponseData response;
94     response.signature = form_signature;
95     response.error = http_error;
96     response.type_of_response =
97         request_type == AutofillDownloadManager::REQUEST_QUERY ?
98             REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED;
99     responses_.push_back(response);
100   }
101
102   enum ResponseType {
103     QUERY_SUCCESSFULL,
104     UPLOAD_SUCCESSFULL,
105     REQUEST_QUERY_FAILED,
106     REQUEST_UPLOAD_FAILED,
107   };
108
109   struct ResponseData {
110     ResponseType type_of_response;
111     int error;
112     std::string signature;
113     std::string response;
114
115     ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {}
116   };
117   std::list<ResponseData> responses_;
118
119   content::TestBrowserThreadBundle thread_bundle_;
120   TestingProfile profile_;
121   AutofillDownloadManager download_manager_;
122 };
123
124 TEST_F(AutofillDownloadTest, QueryAndUploadTest) {
125   // Create and register factory.
126   net::TestURLFetcherFactory factory;
127
128   FormData form;
129   form.method = ASCIIToUTF16("post");
130
131   FormFieldData field;
132   field.label = ASCIIToUTF16("username");
133   field.name = ASCIIToUTF16("username");
134   field.form_control_type = "text";
135   form.fields.push_back(field);
136
137   field.label = ASCIIToUTF16("First Name");
138   field.name = ASCIIToUTF16("firstname");
139   field.form_control_type = "text";
140   form.fields.push_back(field);
141
142   field.label = ASCIIToUTF16("Last Name");
143   field.name = ASCIIToUTF16("lastname");
144   field.form_control_type = "text";
145   form.fields.push_back(field);
146
147   field.label = ASCIIToUTF16("email");
148   field.name = ASCIIToUTF16("email");
149   field.form_control_type = "text";
150   form.fields.push_back(field);
151
152   field.label = ASCIIToUTF16("email2");
153   field.name = ASCIIToUTF16("email2");
154   field.form_control_type = "text";
155   form.fields.push_back(field);
156
157   field.label = ASCIIToUTF16("password");
158   field.name = ASCIIToUTF16("password");
159   field.form_control_type = "password";
160   form.fields.push_back(field);
161
162   field.label = base::string16();
163   field.name = ASCIIToUTF16("Submit");
164   field.form_control_type = "submit";
165   form.fields.push_back(field);
166
167   FormStructure *form_structure = new FormStructure(form);
168   ScopedVector<FormStructure> form_structures;
169   form_structures.push_back(form_structure);
170
171   form.fields.clear();
172
173   field.label = ASCIIToUTF16("address");
174   field.name = ASCIIToUTF16("address");
175   field.form_control_type = "text";
176   form.fields.push_back(field);
177
178   field.label = ASCIIToUTF16("address2");
179   field.name = ASCIIToUTF16("address2");
180   field.form_control_type = "text";
181   form.fields.push_back(field);
182
183   field.label = ASCIIToUTF16("city");
184   field.name = ASCIIToUTF16("city");
185   field.form_control_type = "text";
186   form.fields.push_back(field);
187
188   field.label = base::string16();
189   field.name = ASCIIToUTF16("Submit");
190   field.form_control_type = "submit";
191   form.fields.push_back(field);
192
193   form_structure = new FormStructure(form);
194   form_structures.push_back(form_structure);
195
196   // Request with id 0.
197   MockAutofillMetrics mock_metric_logger;
198   EXPECT_CALL(mock_metric_logger,
199               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
200   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
201                                                   mock_metric_logger));
202   // Set upload to 100% so requests happen.
203   download_manager_.SetPositiveUploadRate(1.0);
204   download_manager_.SetNegativeUploadRate(1.0);
205   // Request with id 1.
206   EXPECT_TRUE(download_manager_.StartUploadRequest(
207       *(form_structures[0]), true, ServerFieldTypeSet()));
208   // Request with id 2.
209   EXPECT_TRUE(download_manager_.StartUploadRequest(
210       *(form_structures[1]), false, ServerFieldTypeSet()));
211
212   const char *responses[] = {
213     "<autofillqueryresponse>"
214       "<field autofilltype=\"0\" />"
215       "<field autofilltype=\"3\" />"
216       "<field autofilltype=\"5\" />"
217       "<field autofilltype=\"9\" />"
218       "<field autofilltype=\"0\" />"
219       "<field autofilltype=\"30\" />"
220       "<field autofilltype=\"31\" />"
221       "<field autofilltype=\"33\" />"
222     "</autofillqueryresponse>",
223     "<autofilluploadresponse positiveuploadrate=\"0.5\" "
224     "negativeuploadrate=\"0.3\"/>",
225     "<html></html>",
226   };
227
228   // Return them out of sequence.
229   net::TestURLFetcher* fetcher = factory.GetFetcherByID(1);
230   ASSERT_TRUE(fetcher);
231   FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
232
233   // After that upload rates would be adjusted to 0.5/0.3
234   EXPECT_DOUBLE_EQ(0.5, download_manager_.GetPositiveUploadRate());
235   EXPECT_DOUBLE_EQ(0.3, download_manager_.GetNegativeUploadRate());
236
237   fetcher = factory.GetFetcherByID(2);
238   ASSERT_TRUE(fetcher);
239   FakeOnURLFetchComplete(fetcher, 404, std::string(responses[2]));
240
241   fetcher = factory.GetFetcherByID(0);
242   ASSERT_TRUE(fetcher);
243   FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
244   EXPECT_EQ(static_cast<size_t>(3), responses_.size());
245
246   EXPECT_EQ(AutofillDownloadTest::UPLOAD_SUCCESSFULL,
247             responses_.front().type_of_response);
248   EXPECT_EQ(0, responses_.front().error);
249   EXPECT_EQ(std::string(), responses_.front().signature);
250   // Expected response on non-query request is an empty string.
251   EXPECT_EQ(std::string(), responses_.front().response);
252   responses_.pop_front();
253
254   EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
255             responses_.front().type_of_response);
256   EXPECT_EQ(404, responses_.front().error);
257   EXPECT_EQ(form_structures[1]->FormSignature(),
258             responses_.front().signature);
259   // Expected response on non-query request is an empty string.
260   EXPECT_EQ(std::string(), responses_.front().response);
261   responses_.pop_front();
262
263   EXPECT_EQ(responses_.front().type_of_response,
264             AutofillDownloadTest::QUERY_SUCCESSFULL);
265   EXPECT_EQ(0, responses_.front().error);
266   EXPECT_EQ(std::string(), responses_.front().signature);
267   EXPECT_EQ(responses[0], responses_.front().response);
268   responses_.pop_front();
269
270   // Set upload to 0% so no new requests happen.
271   download_manager_.SetPositiveUploadRate(0.0);
272   download_manager_.SetNegativeUploadRate(0.0);
273   // No actual requests for the next two calls, as we set upload rate to 0%.
274   EXPECT_FALSE(download_manager_.StartUploadRequest(
275       *(form_structures[0]), true, ServerFieldTypeSet()));
276   EXPECT_FALSE(download_manager_.StartUploadRequest(
277       *(form_structures[1]), false, ServerFieldTypeSet()));
278   fetcher = factory.GetFetcherByID(3);
279   EXPECT_EQ(NULL, fetcher);
280
281   // Modify form structures to miss the cache.
282   field.label = ASCIIToUTF16("Address line 2");
283   field.name = ASCIIToUTF16("address2");
284   field.form_control_type = "text";
285   form.fields.push_back(field);
286   form_structure = new FormStructure(form);
287   form_structures.push_back(form_structure);
288
289   // Request with id 3.
290   EXPECT_CALL(mock_metric_logger,
291               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
292   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
293                                                   mock_metric_logger));
294   fetcher = factory.GetFetcherByID(3);
295   ASSERT_TRUE(fetcher);
296   fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
297   FakeOnURLFetchComplete(fetcher, 500, std::string(responses[0]));
298
299   EXPECT_EQ(AutofillDownloadTest::REQUEST_QUERY_FAILED,
300             responses_.front().type_of_response);
301   EXPECT_EQ(500, responses_.front().error);
302   // Expected response on non-query request is an empty string.
303   EXPECT_EQ(std::string(), responses_.front().response);
304   responses_.pop_front();
305
306   // Query requests should be ignored for the next 10 seconds.
307   EXPECT_CALL(mock_metric_logger,
308               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(0);
309   EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get(),
310                                                    mock_metric_logger));
311   fetcher = factory.GetFetcherByID(4);
312   EXPECT_EQ(NULL, fetcher);
313
314   // Set upload required to true so requests happen.
315   form_structures[0]->upload_required_ = UPLOAD_REQUIRED;
316   // Request with id 4.
317   EXPECT_TRUE(download_manager_.StartUploadRequest(
318       *(form_structures[0]), true, ServerFieldTypeSet()));
319   fetcher = factory.GetFetcherByID(4);
320   ASSERT_TRUE(fetcher);
321   fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
322   FakeOnURLFetchComplete(fetcher, 503, std::string(responses[2]));
323   EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
324             responses_.front().type_of_response);
325   EXPECT_EQ(503, responses_.front().error);
326   responses_.pop_front();
327
328   // Upload requests should be ignored for the next 10 seconds.
329   EXPECT_FALSE(download_manager_.StartUploadRequest(
330       *(form_structures[0]), true, ServerFieldTypeSet()));
331   fetcher = factory.GetFetcherByID(5);
332   EXPECT_EQ(NULL, fetcher);
333 }
334
335 TEST_F(AutofillDownloadTest, CacheQueryTest) {
336   // Create and register factory.
337   net::TestURLFetcherFactory factory;
338
339   FormData form;
340   form.method = ASCIIToUTF16("post");
341
342   FormFieldData field;
343   field.form_control_type = "text";
344
345   field.label = ASCIIToUTF16("username");
346   field.name = ASCIIToUTF16("username");
347   form.fields.push_back(field);
348
349   field.label = ASCIIToUTF16("First Name");
350   field.name = ASCIIToUTF16("firstname");
351   form.fields.push_back(field);
352
353   field.label = ASCIIToUTF16("Last Name");
354   field.name = ASCIIToUTF16("lastname");
355   form.fields.push_back(field);
356
357   FormStructure *form_structure = new FormStructure(form);
358   ScopedVector<FormStructure> form_structures0;
359   form_structures0.push_back(form_structure);
360
361   // Add a slightly different form, which should result in a different request.
362   field.label = ASCIIToUTF16("email");
363   field.name = ASCIIToUTF16("email");
364   form.fields.push_back(field);
365   form_structure = new FormStructure(form);
366   ScopedVector<FormStructure> form_structures1;
367   form_structures1.push_back(form_structure);
368
369   // Add another slightly different form, which should also result in a
370   // different request.
371   field.label = ASCIIToUTF16("email2");
372   field.name = ASCIIToUTF16("email2");
373   form.fields.push_back(field);
374   form_structure = new FormStructure(form);
375   ScopedVector<FormStructure> form_structures2;
376   form_structures2.push_back(form_structure);
377
378   // Limit cache to two forms.
379   LimitCache(2);
380
381   const char *responses[] = {
382     "<autofillqueryresponse>"
383       "<field autofilltype=\"0\" />"
384       "<field autofilltype=\"3\" />"
385       "<field autofilltype=\"5\" />"
386     "</autofillqueryresponse>",
387     "<autofillqueryresponse>"
388       "<field autofilltype=\"0\" />"
389       "<field autofilltype=\"3\" />"
390       "<field autofilltype=\"5\" />"
391       "<field autofilltype=\"9\" />"
392     "</autofillqueryresponse>",
393     "<autofillqueryresponse>"
394       "<field autofilltype=\"0\" />"
395       "<field autofilltype=\"3\" />"
396       "<field autofilltype=\"5\" />"
397       "<field autofilltype=\"9\" />"
398       "<field autofilltype=\"0\" />"
399     "</autofillqueryresponse>",
400   };
401
402   // Request with id 0.
403   MockAutofillMetrics mock_metric_logger;
404   EXPECT_CALL(mock_metric_logger,
405               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
406   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
407                                                   mock_metric_logger));
408   // No responses yet
409   EXPECT_EQ(static_cast<size_t>(0), responses_.size());
410
411   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
412   ASSERT_TRUE(fetcher);
413   FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
414   ASSERT_EQ(static_cast<size_t>(1), responses_.size());
415   EXPECT_EQ(responses[0], responses_.front().response);
416
417   responses_.clear();
418
419   // No actual request - should be a cache hit.
420   EXPECT_CALL(mock_metric_logger,
421               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
422   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
423                                                   mock_metric_logger));
424   // Data is available immediately from cache - no over-the-wire trip.
425   ASSERT_EQ(static_cast<size_t>(1), responses_.size());
426   EXPECT_EQ(responses[0], responses_.front().response);
427   responses_.clear();
428
429   // Request with id 1.
430   EXPECT_CALL(mock_metric_logger,
431               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
432   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
433                                                   mock_metric_logger));
434   // No responses yet
435   EXPECT_EQ(static_cast<size_t>(0), responses_.size());
436
437   fetcher = factory.GetFetcherByID(1);
438   ASSERT_TRUE(fetcher);
439   FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
440   ASSERT_EQ(static_cast<size_t>(1), responses_.size());
441   EXPECT_EQ(responses[1], responses_.front().response);
442
443   responses_.clear();
444
445   // Request with id 2.
446   EXPECT_CALL(mock_metric_logger,
447               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
448   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
449                                                   mock_metric_logger));
450
451   fetcher = factory.GetFetcherByID(2);
452   ASSERT_TRUE(fetcher);
453   FakeOnURLFetchComplete(fetcher, 200, std::string(responses[2]));
454   ASSERT_EQ(static_cast<size_t>(1), responses_.size());
455   EXPECT_EQ(responses[2], responses_.front().response);
456
457   responses_.clear();
458
459   // No actual requests - should be a cache hit.
460   EXPECT_CALL(mock_metric_logger,
461               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
462   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
463                                                   mock_metric_logger));
464
465   EXPECT_CALL(mock_metric_logger,
466               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
467   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
468                                                   mock_metric_logger));
469
470   ASSERT_EQ(static_cast<size_t>(2), responses_.size());
471   EXPECT_EQ(responses[1], responses_.front().response);
472   EXPECT_EQ(responses[2], responses_.back().response);
473   responses_.clear();
474
475   // The first structure should've expired.
476   // Request with id 3.
477   EXPECT_CALL(mock_metric_logger,
478               LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
479   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
480                                                   mock_metric_logger));
481   // No responses yet
482   EXPECT_EQ(static_cast<size_t>(0), responses_.size());
483
484   fetcher = factory.GetFetcherByID(3);
485   ASSERT_TRUE(fetcher);
486   FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
487   ASSERT_EQ(static_cast<size_t>(1), responses_.size());
488   EXPECT_EQ(responses[0], responses_.front().response);
489 }
490
491 }  // namespace autofill