| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/scoped_ptr.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "components/autofill/browser/autofill_xml_parser.h" |
| #include "components/autofill/browser/field_types.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/libjingle/source/talk/xmllite/xmlparser.h" |
| |
| namespace autofill { |
| namespace { |
| |
| TEST(AutofillQueryXmlParserTest, BasicQuery) { |
| // An XML string representing a basic query response. |
| std::string xml = "<autofillqueryresponse>" |
| "<field autofilltype=\"0\" />" |
| "<field autofilltype=\"1\" />" |
| "<field autofilltype=\"3\" />" |
| "<field autofilltype=\"2\" />" |
| "<field autofilltype=\"61\" defaultvalue=\"default\"/>" |
| "</autofillqueryresponse>"; |
| |
| // Create a vector of AutofillServerFieldInfos, to assign the parsed field |
| // types to. |
| std::vector<AutofillServerFieldInfo> field_infos; |
| UploadRequired upload_required = USE_UPLOAD_RATES; |
| std::string experiment_id; |
| |
| // Create a parser. |
| AutofillQueryXmlParser parse_handler(&field_infos, &upload_required, |
| &experiment_id); |
| buzz::XmlParser parser(&parse_handler); |
| parser.Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler.succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| ASSERT_EQ(5U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(UNKNOWN_TYPE, field_infos[1].field_type); |
| EXPECT_EQ(NAME_FIRST, field_infos[2].field_type); |
| EXPECT_EQ(EMPTY_TYPE, field_infos[3].field_type); |
| EXPECT_EQ("", field_infos[3].default_value); |
| EXPECT_EQ(FIELD_WITH_DEFAULT_VALUE, field_infos[4].field_type); |
| EXPECT_EQ("default", field_infos[4].default_value); |
| EXPECT_EQ(std::string(), experiment_id); |
| } |
| |
| // Test parsing the upload required attribute. |
| TEST(AutofillQueryXmlParserTest, TestUploadRequired) { |
| std::vector<AutofillServerFieldInfo> field_infos; |
| UploadRequired upload_required = USE_UPLOAD_RATES; |
| std::string experiment_id; |
| |
| std::string xml = "<autofillqueryresponse uploadrequired=\"true\">" |
| "<field autofilltype=\"0\" />" |
| "</autofillqueryresponse>"; |
| |
| scoped_ptr<AutofillQueryXmlParser> parse_handler( |
| new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(UPLOAD_REQUIRED, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string(), experiment_id); |
| |
| field_infos.clear(); |
| xml = "<autofillqueryresponse uploadrequired=\"false\">" |
| "<field autofilltype=\"0\" />" |
| "</autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string(), experiment_id); |
| |
| field_infos.clear(); |
| xml = "<autofillqueryresponse uploadrequired=\"bad_value\">" |
| "<field autofilltype=\"0\" />" |
| "</autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string(), experiment_id); |
| } |
| |
| // Test parsing the experiment id attribute |
| TEST(AutofillQueryXmlParserTest, ParseExperimentId) { |
| std::vector<AutofillServerFieldInfo> field_infos; |
| UploadRequired upload_required = USE_UPLOAD_RATES; |
| std::string experiment_id; |
| |
| // When the attribute is missing, we should get back the default value -- the |
| // empty string. |
| std::string xml = "<autofillqueryresponse>" |
| "<field autofilltype=\"0\" />" |
| "</autofillqueryresponse>"; |
| |
| scoped_ptr<AutofillQueryXmlParser> parse_handler( |
| new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string(), experiment_id); |
| |
| field_infos.clear(); |
| |
| // When the attribute is present, make sure we parse it. |
| xml = "<autofillqueryresponse experimentid=\"FancyNewAlgorithm\">" |
| "<field autofilltype=\"0\" />" |
| "</autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string("FancyNewAlgorithm"), experiment_id); |
| |
| field_infos.clear(); |
| |
| // Make sure that we can handle parsing both the upload required and the |
| // experiment id attribute together. |
| xml = "<autofillqueryresponse uploadrequired=\"false\"" |
| " experimentid=\"ServerSmartyPants\">" |
| "<field autofilltype=\"0\" />" |
| "</autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string("ServerSmartyPants"), experiment_id); |
| } |
| |
| // Test XML response with autofill_flow information. |
| TEST(AutofillQueryXmlParserTest, ParseAutofillFlow) { |
| std::vector<AutofillServerFieldInfo> field_infos; |
| UploadRequired upload_required = USE_UPLOAD_RATES; |
| std::string experiment_id; |
| |
| std::string xml = "<autofillqueryresponse>" |
| "<field autofilltype=\"55\"/>" |
| "<autofill_flow page_no=\"1\" total_pages=\"10\">" |
| "<page_advance_button id=\"foo\"/>" |
| "</autofill_flow>" |
| "</autofillqueryresponse>"; |
| |
| scoped_ptr<AutofillQueryXmlParser> parse_handler( |
| new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(1, parse_handler->current_page_number()); |
| EXPECT_EQ(10, parse_handler->total_pages()); |
| EXPECT_EQ("foo", parse_handler->proceed_element_descriptor()->descriptor); |
| EXPECT_EQ(autofill::WebElementDescriptor::ID, |
| parse_handler->proceed_element_descriptor()->retrieval_method); |
| |
| // Clear |field_infos| for the next test; |
| field_infos.clear(); |
| |
| // Test css_selector as page_advance_button. |
| xml = "<autofillqueryresponse>" |
| "<field autofilltype=\"55\"/>" |
| "<autofill_flow page_no=\"1\" total_pages=\"10\">" |
| "<page_advance_button css_selector=\"[name="foo"]\"/>" |
| "</autofill_flow>" |
| "</autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, |
| &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(1, parse_handler->current_page_number()); |
| EXPECT_EQ(10, parse_handler->total_pages()); |
| EXPECT_EQ("[name=\"foo\"]", |
| parse_handler->proceed_element_descriptor()->descriptor); |
| EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR, |
| parse_handler->proceed_element_descriptor()->retrieval_method); |
| |
| // Clear |field_infos| for the next test; |
| field_infos.clear(); |
| |
| // Test first attribute is always the one set. |
| xml = "<autofillqueryresponse>" |
| "<field autofilltype=\"55\"/>" |
| "<autofill_flow page_no=\"1\" total_pages=\"10\">" |
| "<page_advance_button css_selector=\"[name="foo"]\"" |
| " id=\"foo\"/>" |
| "</autofill_flow>" |
| "</autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, |
| &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(1, parse_handler->current_page_number()); |
| EXPECT_EQ(10, parse_handler->total_pages()); |
| EXPECT_EQ("[name=\"foo\"]", |
| parse_handler->proceed_element_descriptor()->descriptor); |
| EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR, |
| parse_handler->proceed_element_descriptor()->retrieval_method); |
| } |
| |
| // Test badly formed XML queries. |
| TEST(AutofillQueryXmlParserTest, ParseErrors) { |
| std::vector<AutofillServerFieldInfo> field_infos; |
| UploadRequired upload_required = USE_UPLOAD_RATES; |
| std::string experiment_id; |
| |
| // Test no Autofill type. |
| std::string xml = "<autofillqueryresponse>" |
| "<field/>" |
| "</autofillqueryresponse>"; |
| |
| scoped_ptr<AutofillQueryXmlParser> parse_handler( |
| new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_FALSE(parse_handler->succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| EXPECT_EQ(0U, field_infos.size()); |
| EXPECT_EQ(std::string(), experiment_id); |
| |
| // Test an incorrect Autofill type. |
| xml = "<autofillqueryresponse>" |
| "<field autofilltype=\"-1\"/>" |
| "</autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| // AutofillType was out of range and should be set to NO_SERVER_DATA. |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string(), experiment_id); |
| |
| // Test upper bound for the field type, MAX_VALID_FIELD_TYPE. |
| field_infos.clear(); |
| xml = "<autofillqueryresponse><field autofilltype=\"" + |
| base::IntToString(MAX_VALID_FIELD_TYPE) + "\"/></autofillqueryresponse>"; |
| |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler->succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| // AutofillType was out of range and should be set to NO_SERVER_DATA. |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string(), experiment_id); |
| |
| // Test an incorrect Autofill type. |
| field_infos.clear(); |
| xml = "<autofillqueryresponse>" |
| "<field autofilltype=\"No Type\"/>" |
| "</autofillqueryresponse>"; |
| |
| // Parse fails but an entry is still added to field_infos. |
| parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, |
| &experiment_id)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_FALSE(parse_handler->succeeded()); |
| EXPECT_EQ(USE_UPLOAD_RATES, upload_required); |
| ASSERT_EQ(1U, field_infos.size()); |
| EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); |
| EXPECT_EQ(std::string(), experiment_id); |
| } |
| |
| // Test successfull upload response. |
| TEST(AutofillUploadXmlParser, TestSuccessfulResponse) { |
| std::string xml = "<autofilluploadresponse positiveuploadrate=\"0.5\" " |
| "negativeuploadrate=\"0.3\"/>"; |
| double positive = 0; |
| double negative = 0; |
| AutofillUploadXmlParser parse_handler(&positive, &negative); |
| buzz::XmlParser parser(&parse_handler); |
| parser.Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(parse_handler.succeeded()); |
| EXPECT_DOUBLE_EQ(0.5, positive); |
| EXPECT_DOUBLE_EQ(0.3, negative); |
| } |
| |
| // Test failed upload response. |
| TEST(AutofillUploadXmlParser, TestFailedResponse) { |
| std::string xml = "<autofilluploadresponse positiveuploadrate=\"\" " |
| "negativeuploadrate=\"0.3\"/>"; |
| double positive = 0; |
| double negative = 0; |
| scoped_ptr<AutofillUploadXmlParser> parse_handler( |
| new AutofillUploadXmlParser(&positive, &negative)); |
| scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(!parse_handler->succeeded()); |
| EXPECT_DOUBLE_EQ(0, positive); |
| EXPECT_DOUBLE_EQ(0.3, negative); // Partially parsed. |
| negative = 0; |
| |
| xml = "<autofilluploadresponse positiveuploadrate=\"0.5\" " |
| "negativeuploadrate=\"0.3\""; |
| parse_handler.reset(new AutofillUploadXmlParser(&positive, &negative)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(!parse_handler->succeeded()); |
| EXPECT_DOUBLE_EQ(0, positive); |
| EXPECT_DOUBLE_EQ(0, negative); |
| |
| xml = "bad data"; |
| parse_handler.reset(new AutofillUploadXmlParser(&positive, &negative)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(!parse_handler->succeeded()); |
| EXPECT_DOUBLE_EQ(0, positive); |
| EXPECT_DOUBLE_EQ(0, negative); |
| |
| xml = ""; |
| parse_handler.reset(new AutofillUploadXmlParser(&positive, &negative)); |
| parser.reset(new buzz::XmlParser(parse_handler.get())); |
| parser->Parse(xml.c_str(), xml.length(), true); |
| EXPECT_TRUE(!parse_handler->succeeded()); |
| EXPECT_DOUBLE_EQ(0, positive); |
| EXPECT_DOUBLE_EQ(0, negative); |
| } |
| |
| } // namespace |
| } // namespace autofill |