// 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