// 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 "chrome/browser/autofill/autofill_xml_parser.h" #include "chrome/browser/autofill/field_types.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/libjingle/source/talk/xmllite/xmlparser.h" 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\" />" "</autofillqueryresponse>"; // Create a vector of AutofillFieldTypes, to assign the parsed field types to. std::vector<AutofillFieldType> field_types; UploadRequired upload_required = USE_UPLOAD_RATES; std::string experiment_id; // Create a parser. AutofillQueryXmlParser parse_handler(&field_types, &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(4U, field_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(UNKNOWN_TYPE, field_types[1]); EXPECT_EQ(NAME_FIRST, field_types[2]); EXPECT_EQ(EMPTY_TYPE, field_types[3]); EXPECT_EQ(std::string(), experiment_id); } // Test parsing the upload required attribute. TEST(AutofillQueryXmlParserTest, TestUploadRequired) { std::vector<AutofillFieldType> field_types; 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_types, &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_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(std::string(), experiment_id); field_types.clear(); xml = "<autofillqueryresponse uploadrequired=\"false\">" "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; parse_handler.reset(new AutofillQueryXmlParser(&field_types, &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_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(std::string(), experiment_id); field_types.clear(); xml = "<autofillqueryresponse uploadrequired=\"bad_value\">" "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; parse_handler.reset(new AutofillQueryXmlParser(&field_types, &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_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(std::string(), experiment_id); } // Test parsing the experiment id attribute TEST(AutofillQueryXmlParserTest, ParseExperimentId) { std::vector<AutofillFieldType> field_types; 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_types, &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_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(std::string(), experiment_id); field_types.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_types, &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_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(std::string("FancyNewAlgorithm"), experiment_id); field_types.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_types, &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_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(std::string("ServerSmartyPants"), experiment_id); } // Test badly formed XML queries. TEST(AutofillQueryXmlParserTest, ParseErrors) { std::vector<AutofillFieldType> field_types; 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_types, &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_types.size()); EXPECT_EQ(std::string(), experiment_id); // Test an incorrect Autofill type. xml = "<autofillqueryresponse>" "<field autofilltype=\"307\"/>" "</autofillqueryresponse>"; parse_handler.reset(new AutofillQueryXmlParser(&field_types, &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_types.size()); // AutofillType was out of range and should be set to NO_SERVER_DATA. EXPECT_EQ(NO_SERVER_DATA, field_types[0]); EXPECT_EQ(std::string(), experiment_id); // Test an incorrect Autofill type. field_types.clear(); xml = "<autofillqueryresponse>" "<field autofilltype=\"No Type\"/>" "</autofillqueryresponse>"; // Parse fails but an entry is still added to field_types. parse_handler.reset(new AutofillQueryXmlParser(&field_types, &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_types.size()); EXPECT_EQ(NO_SERVER_DATA, field_types[0]); 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