autofill_xml_parser_unittest.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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 <string>
6#include <vector>
7
8#include "base/memory/scoped_ptr.h"
9#include "base/strings/string_number_conversions.h"
10#include "components/autofill/content/browser/autocheckout_page_meta_data.h"
11#include "components/autofill/core/browser/autofill_xml_parser.h"
12#include "components/autofill/core/browser/field_types.h"
13#include "testing/gtest/include/gtest/gtest.h"
14#include "third_party/libjingle/source/talk/xmllite/xmlparser.h"
15
16namespace autofill {
17namespace {
18
19class AutofillQueryXmlParserTest : public testing::Test {
20 public:
21  AutofillQueryXmlParserTest(): upload_required_(USE_UPLOAD_RATES) {};
22  virtual ~AutofillQueryXmlParserTest() {};
23
24 protected:
25  void ParseQueryXML(const std::string& xml, bool should_succeed) {
26    // Create a parser.
27    AutofillQueryXmlParser parse_handler(&field_infos_,
28                                         &upload_required_,
29                                         &experiment_id_,
30                                         &page_meta_data_);
31    buzz::XmlParser parser(&parse_handler);
32    parser.Parse(xml.c_str(), xml.length(), true);
33    EXPECT_EQ(should_succeed, parse_handler.succeeded());
34  }
35
36  std::vector<AutofillServerFieldInfo> field_infos_;
37  UploadRequired upload_required_;
38  std::string experiment_id_;
39  autofill::AutocheckoutPageMetaData page_meta_data_;
40};
41
42class AutofillUploadXmlParserTest : public testing::Test {
43 public:
44  AutofillUploadXmlParserTest(): positive_(0), negative_(0) {};
45  virtual ~AutofillUploadXmlParserTest() {};
46
47 protected:
48  void ParseUploadXML(const std::string& xml, bool should_succeed) {
49    // Create a parser.
50    AutofillUploadXmlParser parse_handler(&positive_, &negative_);
51    buzz::XmlParser parser(&parse_handler);
52    parser.Parse(xml.c_str(), xml.length(), true);
53
54    EXPECT_EQ(should_succeed, parse_handler.succeeded());
55  }
56
57  double positive_;
58  double negative_;
59};
60
61TEST_F(AutofillQueryXmlParserTest, BasicQuery) {
62  // An XML string representing a basic query response.
63  std::string xml = "<autofillqueryresponse>"
64                    "<field autofilltype=\"0\" />"
65                    "<field autofilltype=\"1\" />"
66                    "<field autofilltype=\"3\" />"
67                    "<field autofilltype=\"2\" />"
68                    "<field autofilltype=\"61\" defaultvalue=\"default\"/>"
69                    "</autofillqueryresponse>";
70  ParseQueryXML(xml, true);
71
72  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
73  ASSERT_EQ(5U, field_infos_.size());
74  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
75  EXPECT_EQ(UNKNOWN_TYPE, field_infos_[1].field_type);
76  EXPECT_EQ(NAME_FIRST, field_infos_[2].field_type);
77  EXPECT_EQ(EMPTY_TYPE, field_infos_[3].field_type);
78  EXPECT_TRUE(field_infos_[3].default_value.empty());
79  EXPECT_EQ(FIELD_WITH_DEFAULT_VALUE, field_infos_[4].field_type);
80  EXPECT_EQ("default", field_infos_[4].default_value);
81  EXPECT_TRUE(experiment_id_.empty());
82}
83
84// Test parsing the upload required attribute.
85TEST_F(AutofillQueryXmlParserTest, TestUploadRequired) {
86  std::string xml = "<autofillqueryresponse uploadrequired=\"true\">"
87                    "<field autofilltype=\"0\" />"
88                    "</autofillqueryresponse>";
89
90  ParseQueryXML(xml, true);
91
92  EXPECT_EQ(upload_required_, upload_required_);
93  ASSERT_EQ(1U, field_infos_.size());
94  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
95  EXPECT_TRUE(experiment_id_.empty());
96
97  field_infos_.clear();
98  xml = "<autofillqueryresponse uploadrequired=\"false\">"
99        "<field autofilltype=\"0\" />"
100        "</autofillqueryresponse>";
101
102  ParseQueryXML(xml, true);
103
104  EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required_);
105  ASSERT_EQ(1U, field_infos_.size());
106  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
107  EXPECT_TRUE(experiment_id_.empty());
108
109  field_infos_.clear();
110  xml = "<autofillqueryresponse uploadrequired=\"bad_value\">"
111        "<field autofilltype=\"0\" />"
112        "</autofillqueryresponse>";
113
114  ParseQueryXML(xml, true);
115
116  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
117  ASSERT_EQ(1U, field_infos_.size());
118  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
119  EXPECT_TRUE(experiment_id_.empty());
120}
121
122// Test parsing the experiment id attribute
123TEST_F(AutofillQueryXmlParserTest, ParseExperimentId) {
124  // When the attribute is missing, we should get back the default value -- the
125  // empty string.
126  std::string xml = "<autofillqueryresponse>"
127                    "<field autofilltype=\"0\" />"
128                    "</autofillqueryresponse>";
129
130  ParseQueryXML(xml, true);
131
132  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
133  ASSERT_EQ(1U, field_infos_.size());
134  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
135  EXPECT_TRUE(experiment_id_.empty());
136
137  field_infos_.clear();
138
139  // When the attribute is present, make sure we parse it.
140  xml = "<autofillqueryresponse experimentid=\"FancyNewAlgorithm\">"
141        "<field autofilltype=\"0\" />"
142        "</autofillqueryresponse>";
143
144  ParseQueryXML(xml, true);
145
146  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
147  ASSERT_EQ(1U, field_infos_.size());
148  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
149  EXPECT_EQ(std::string("FancyNewAlgorithm"), experiment_id_);
150
151  field_infos_.clear();
152
153  // Make sure that we can handle parsing both the upload required and the
154  // experiment id attribute together.
155  xml = "<autofillqueryresponse uploadrequired=\"false\""
156        "                       experimentid=\"ServerSmartyPants\">"
157        "<field autofilltype=\"0\" />"
158        "</autofillqueryresponse>";
159
160  ParseQueryXML(xml, true);
161
162  EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required_);
163  ASSERT_EQ(1U, field_infos_.size());
164  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
165  EXPECT_EQ("ServerSmartyPants", experiment_id_);
166}
167
168// Fails on ASAN bot. http://crbug.com/253797
169#if defined(ADDRESS_SANITIZER)
170#define MAYBE_ParseAutofillFlow DISABLED_ParseAutofillFlow
171#else
172#define MAYBE_ParseAutofillFlow ParseAutofillFlow
173#endif
174
175// Test XML response with autofill_flow information.
176TEST_F(AutofillQueryXmlParserTest, MAYBE_ParseAutofillFlow) {
177  std::string xml = "<autofillqueryresponse>"
178                    "<field autofilltype=\"55\"/>"
179                    "<autofill_flow page_no=\"1\" total_pages=\"10\">"
180                    "<page_advance_button id=\"foo\"/>"
181                    "<flow_page page_no=\"0\">"
182                    "<type>1</type>"
183                    "<type>2</type>"
184                    "</flow_page>"
185                    "<flow_page page_no=\"1\">"
186                    "<type>3</type>"
187                    "</flow_page>"
188                    "</autofill_flow>"
189                    "</autofillqueryresponse>";
190
191  ParseQueryXML(xml, true);
192
193  EXPECT_EQ(1U, field_infos_.size());
194  EXPECT_EQ(1, page_meta_data_.current_page_number);
195  EXPECT_EQ(10, page_meta_data_.total_pages);
196  EXPECT_TRUE(page_meta_data_.ignore_ajax);
197  EXPECT_EQ("foo", page_meta_data_.proceed_element_descriptor.descriptor);
198  EXPECT_EQ(autofill::WebElementDescriptor::ID,
199            page_meta_data_.proceed_element_descriptor.retrieval_method);
200  EXPECT_EQ(2U, page_meta_data_.page_types.size());
201  EXPECT_EQ(2U, page_meta_data_.page_types[0].size());
202  EXPECT_EQ(1U, page_meta_data_.page_types[1].size());
203  EXPECT_EQ(AUTOCHECKOUT_STEP_SHIPPING, page_meta_data_.page_types[0][0]);
204  EXPECT_EQ(AUTOCHECKOUT_STEP_DELIVERY, page_meta_data_.page_types[0][1]);
205  EXPECT_EQ(AUTOCHECKOUT_STEP_BILLING, page_meta_data_.page_types[1][0]);
206
207  // Clear |field_infos_| for the next test;
208  field_infos_.clear();
209
210  // Test css_selector as page_advance_button.
211  xml = "<autofillqueryresponse>"
212        "<field autofilltype=\"55\"/>"
213        "<autofill_flow page_no=\"1\" total_pages=\"10\">"
214        "<page_advance_button css_selector=\"[name=&quot;foo&quot;]\"/>"
215        "</autofill_flow>"
216        "</autofillqueryresponse>";
217
218  ParseQueryXML(xml, true);
219
220  EXPECT_EQ(1U, field_infos_.size());
221  EXPECT_EQ(1, page_meta_data_.current_page_number);
222  EXPECT_EQ(10, page_meta_data_.total_pages);
223  EXPECT_EQ("[name=\"foo\"]",
224            page_meta_data_.proceed_element_descriptor.descriptor);
225  EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR,
226            page_meta_data_.proceed_element_descriptor.retrieval_method);
227
228  // Clear |field_infos_| for the next test;
229  field_infos_.clear();
230
231  // Test first attribute is always the one set.
232  xml = "<autofillqueryresponse>"
233        "<field autofilltype=\"55\"/>"
234        "<autofill_flow page_no=\"1\" total_pages=\"10\">"
235        "<page_advance_button css_selector=\"[name=&quot;foo&quot;]\""
236        " id=\"foo\"/>"
237        "</autofill_flow>"
238        "</autofillqueryresponse>";
239
240  ParseQueryXML(xml, true);
241
242  EXPECT_EQ(1U, field_infos_.size());
243  EXPECT_EQ(1, page_meta_data_.current_page_number);
244  EXPECT_EQ(10, page_meta_data_.total_pages);
245  EXPECT_EQ("[name=\"foo\"]",
246            page_meta_data_.proceed_element_descriptor.descriptor);
247  EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR,
248            page_meta_data_.proceed_element_descriptor.retrieval_method);
249
250  // Clear |field_infos_| for the next test;
251  field_infos_.clear();
252
253  // Test parsing click_elements_before_formfill correctly.
254  xml = "<autofillqueryresponse>"
255        "<field autofilltype=\"55\"/>"
256        "<autofill_flow page_no=\"1\" total_pages=\"10\">"
257        "<click_elements_before_formfill>"
258        "<web_element id=\"btn1\" /></click_elements_before_formfill>"
259        "<click_elements_before_formfill>"
260        "<web_element css_selector=\"[name=&quot;btn2&quot;]\"/>"
261        "</click_elements_before_formfill>"
262        "</autofill_flow>"
263        "</autofillqueryresponse>";
264
265  ParseQueryXML(xml, true);
266
267  EXPECT_EQ(1U, field_infos_.size());
268  EXPECT_EQ(1, page_meta_data_.current_page_number);
269  EXPECT_EQ(10, page_meta_data_.total_pages);
270  ASSERT_EQ(2U, page_meta_data_.click_elements_before_form_fill.size());
271  autofill::WebElementDescriptor& click_elment =
272      page_meta_data_.click_elements_before_form_fill[0];
273  EXPECT_EQ("btn1", click_elment.descriptor);
274  EXPECT_EQ(autofill::WebElementDescriptor::ID, click_elment.retrieval_method);
275  click_elment = page_meta_data_.click_elements_before_form_fill[1];
276  EXPECT_EQ("[name=\"btn2\"]", click_elment.descriptor);
277  EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR,
278            click_elment.retrieval_method);
279
280  // Clear |field_infos_| for the next test;
281  field_infos_.clear();
282
283  // Test parsing click_elements_after_formfill correctly.
284  xml = "<autofillqueryresponse>"
285        "<field autofilltype=\"55\"/>"
286        "<autofill_flow page_no=\"1\" total_pages=\"10\">"
287        "<click_elements_after_formfill>"
288        "<web_element id=\"btn1\" /></click_elements_after_formfill>"
289        "</autofill_flow>"
290        "</autofillqueryresponse>";
291
292  ParseQueryXML(xml, true);
293
294  EXPECT_EQ(1U, field_infos_.size());
295  EXPECT_EQ(1, page_meta_data_.current_page_number);
296  EXPECT_EQ(10, page_meta_data_.total_pages);
297  ASSERT_EQ(1U, page_meta_data_.click_elements_after_form_fill.size());
298  click_elment = page_meta_data_.click_elements_after_form_fill[0];
299  EXPECT_EQ("btn1", click_elment.descriptor);
300  EXPECT_EQ(autofill::WebElementDescriptor::ID, click_elment.retrieval_method);
301
302  // Clear |field_infos_| for the next test.
303  field_infos_.clear();
304
305  // Test setting of ignore_ajax attribute.
306  xml = "<autofillqueryresponse>"
307        "<field autofilltype=\"55\"/>"
308        "<autofill_flow page_no=\"1\" total_pages=\"10\" ignore_ajax=\"true\">"
309        "<page_advance_button css_selector=\"[name=&quot;foo&quot;]\""
310        " id=\"foo\"/>"
311        "</autofill_flow>"
312        "</autofillqueryresponse>";
313
314  ParseQueryXML(xml, true);
315
316  EXPECT_EQ(1U, field_infos_.size());
317  EXPECT_EQ(1, page_meta_data_.current_page_number);
318  EXPECT_EQ(10, page_meta_data_.total_pages);
319  EXPECT_TRUE(page_meta_data_.ignore_ajax);
320  EXPECT_EQ("[name=\"foo\"]",
321            page_meta_data_.proceed_element_descriptor.descriptor);
322  EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR,
323            page_meta_data_.proceed_element_descriptor.retrieval_method);
324
325 // Clear |field_infos_| for the next test.
326  field_infos_.clear();
327
328  // Test redundant setting to false of ignore_ajax attribute.
329  xml = "<autofillqueryresponse>"
330        "<field autofilltype=\"55\"/>"
331        "<autofill_flow page_no=\"1\" total_pages=\"10\" ignore_ajax=\"false\">"
332        "<page_advance_button css_selector=\"[name=&quot;foo&quot;]\""
333        " id=\"foo\"/>"
334        "</autofill_flow>"
335        "</autofillqueryresponse>";
336
337  ParseQueryXML(xml, true);
338
339  EXPECT_EQ(1U, field_infos_.size());
340  EXPECT_EQ(1, page_meta_data_.current_page_number);
341  EXPECT_EQ(10, page_meta_data_.total_pages);
342  EXPECT_FALSE(page_meta_data_.ignore_ajax);
343  EXPECT_EQ("[name=\"foo\"]",
344            page_meta_data_.proceed_element_descriptor.descriptor);
345  EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR,
346            page_meta_data_.proceed_element_descriptor.retrieval_method);
347}
348
349// Test badly formed XML queries.
350TEST_F(AutofillQueryXmlParserTest, ParseErrors) {
351  // Test no Autofill type.
352  std::string xml = "<autofillqueryresponse>"
353                    "<field/>"
354                    "</autofillqueryresponse>";
355
356  ParseQueryXML(xml, false);
357
358  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
359  EXPECT_EQ(0U, field_infos_.size());
360  EXPECT_TRUE(experiment_id_.empty());
361
362  // Test an incorrect Autofill type.
363  xml = "<autofillqueryresponse>"
364        "<field autofilltype=\"-1\"/>"
365        "</autofillqueryresponse>";
366
367  ParseQueryXML(xml, true);
368
369  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
370  ASSERT_EQ(1U, field_infos_.size());
371  // AutofillType was out of range and should be set to NO_SERVER_DATA.
372  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
373  EXPECT_TRUE(experiment_id_.empty());
374
375  // Test upper bound for the field type, MAX_VALID_FIELD_TYPE.
376  field_infos_.clear();
377  xml = "<autofillqueryresponse><field autofilltype=\"" +
378      base::IntToString(MAX_VALID_FIELD_TYPE) + "\"/></autofillqueryresponse>";
379
380  ParseQueryXML(xml, true);
381
382  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
383  ASSERT_EQ(1U, field_infos_.size());
384  // AutofillType was out of range and should be set to NO_SERVER_DATA.
385  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
386  EXPECT_TRUE(experiment_id_.empty());
387
388  // Test an incorrect Autofill type.
389  field_infos_.clear();
390  xml = "<autofillqueryresponse>"
391        "<field autofilltype=\"No Type\"/>"
392        "</autofillqueryresponse>";
393
394  // Parse fails but an entry is still added to field_infos_.
395  ParseQueryXML(xml, false);
396
397  EXPECT_EQ(USE_UPLOAD_RATES, upload_required_);
398  ASSERT_EQ(1U, field_infos_.size());
399  EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type);
400  EXPECT_TRUE(experiment_id_.empty());
401}
402
403// Test successfull upload response.
404TEST_F(AutofillUploadXmlParserTest, TestSuccessfulResponse) {
405  ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"0.5\" "
406                 "negativeuploadrate=\"0.3\"/>",
407                 true);
408
409  EXPECT_DOUBLE_EQ(0.5, positive_);
410  EXPECT_DOUBLE_EQ(0.3, negative_);
411}
412
413// Test failed upload response.
414TEST_F(AutofillUploadXmlParserTest, TestFailedResponse) {
415  ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"\" "
416                 "negativeuploadrate=\"0.3\"/>",
417                 false);
418
419  EXPECT_DOUBLE_EQ(0, positive_);
420  EXPECT_DOUBLE_EQ(0.3, negative_);  // Partially parsed.
421  negative_ = 0;
422
423  ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"0.5\" "
424                 "negativeuploadrate=\"0.3\"",
425                 false);
426
427  EXPECT_DOUBLE_EQ(0, positive_);
428  EXPECT_DOUBLE_EQ(0, negative_);
429
430  ParseUploadXML("bad data", false);
431
432  EXPECT_DOUBLE_EQ(0, positive_);
433  EXPECT_DOUBLE_EQ(0, negative_);
434
435  ParseUploadXML(std::string(), false);
436
437  EXPECT_DOUBLE_EQ(0, positive_);
438  EXPECT_DOUBLE_EQ(0, negative_);
439}
440
441}  // namespace
442}  // namespace autofill
443