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