This source file includes following definitions.
- Hash64Bit
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
#include "components/autofill/core/browser/form_structure.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using base::ASCIIToUTF16;
namespace autofill {
namespace {
class TestAutofillMetrics : public AutofillMetrics {
 public:
  TestAutofillMetrics() {}
  virtual ~TestAutofillMetrics() {}
};
}  
namespace content {
std::ostream& operator<<(std::ostream& os, const FormData& form) {
  os << base::UTF16ToUTF8(form.name)
     << " "
     << base::UTF16ToUTF8(form.method)
     << " "
     << form.origin.spec()
     << " "
     << form.action.spec()
     << " ";
  for (std::vector<FormFieldData>::const_iterator iter =
           form.fields.begin();
       iter != form.fields.end(); ++iter) {
    os << *iter
       << " ";
  }
  return os;
}
}  
class FormStructureTest {
 public:
  static std::string Hash64Bit(const std::string& str) {
    return FormStructure::Hash64Bit(str);
  }
};
TEST(FormStructureTest, FieldCount) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.label = ASCIIToUTF16("username");
  field.name = ASCIIToUTF16("username");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("password");
  field.name = ASCIIToUTF16("password");
  field.form_control_type = "password";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("address1");
  field.name = ASCIIToUTF16("address1");
  field.form_control_type = "text";
  field.should_autocomplete = false;
  form.fields.push_back(field);
  
  
  form_structure.reset(new FormStructure(form));
  EXPECT_EQ(4U, form_structure->field_count());
}
TEST(FormStructureTest, AutofillCount) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.label = ASCIIToUTF16("username");
  field.name = ASCIIToUTF16("username");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("password");
  field.name = ASCIIToUTF16("password");
  field.form_control_type = "password";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("state");
  field.name = ASCIIToUTF16("state");
  field.form_control_type = "select-one";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_EQ(1U, form_structure->autofill_count());
  
  
  field.label = ASCIIToUTF16("address1");
  field.name = ASCIIToUTF16("address1");
  field.form_control_type = "text";
  field.should_autocomplete = false;
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_EQ(1U, form_structure->autofill_count());
}
TEST(FormStructureTest, SourceURL) {
  FormData form;
  form.origin = GURL("http://www.foo.com/");
  form.method = ASCIIToUTF16("post");
  FormStructure form_structure(form);
  EXPECT_EQ(form.origin, form_structure.source_url());
}
TEST(FormStructureTest, IsAutofillable) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.label = ASCIIToUTF16("username");
  field.name = ASCIIToUTF16("username");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("password");
  field.name = ASCIIToUTF16("password");
  field.form_control_type = "password";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_FALSE(form_structure->IsAutofillable(true));
  
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("firstname");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("lastname");
  field.form_control_type = "text";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_FALSE(form_structure->IsAutofillable(true));
  
  field.label = ASCIIToUTF16("Email");
  field.name = ASCIIToUTF16("email");
  field.form_control_type = "email";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  
  
  form.method = ASCIIToUTF16("get");
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_FALSE(form_structure->IsAutofillable(true));
  EXPECT_TRUE(form_structure->IsAutofillable(false));
  
  form.method = ASCIIToUTF16("post");
  form.action = GURL("http://google.com/search?q=hello");
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_FALSE(form_structure->IsAutofillable(true));
  
  form.action = GURL("http://search.com/?q=hello");
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
}
TEST(FormStructureTest, ShouldBeParsed) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.label = ASCIIToUTF16("username");
  field.name = ASCIIToUTF16("username");
  field.form_control_type = "text";
  form.fields.push_back(field);
  FormFieldData checkable_field;
  checkable_field.is_checkable = true;
  checkable_field.name = ASCIIToUTF16("radiobtn");
  checkable_field.form_control_type = "radio";
  form.fields.push_back(checkable_field);
  checkable_field.name = ASCIIToUTF16("checkbox");
  checkable_field.form_control_type = "checkbox";
  form.fields.push_back(checkable_field);
  
  form_structure.reset(new FormStructure(form));
  EXPECT_FALSE(form_structure->ShouldBeParsed(true));
  
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("firstname");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("lastname");
  field.form_control_type = "text";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  EXPECT_TRUE(form_structure->ShouldBeParsed(true));
  
  
  form.method = ASCIIToUTF16("get");
  form_structure.reset(new FormStructure(form));
  EXPECT_FALSE(form_structure->IsAutofillable(true));
  EXPECT_TRUE(form_structure->ShouldBeParsed(false));
  
  form.method = ASCIIToUTF16("post");
  form.action = GURL("http://google.com/search?q=hello");
  form_structure.reset(new FormStructure(form));
  EXPECT_FALSE(form_structure->ShouldBeParsed(true));
  
  form.action = GURL("http://search.com/?q=hello");
  form_structure.reset(new FormStructure(form));
  EXPECT_TRUE(form_structure->ShouldBeParsed(true));
  
  
  form.fields.clear();
  field.label = ASCIIToUTF16("Email");
  field.name = ASCIIToUTF16("email");
  field.form_control_type = "email";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("State");
  field.name = ASCIIToUTF16("state");
  field.form_control_type = "select-one";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Country");
  field.name = ASCIIToUTF16("country");
  field.form_control_type = "select-one";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  EXPECT_TRUE(form_structure->ShouldBeParsed(true));
  form.fields[0].form_control_type = "select-one";
  
  form_structure.reset(new FormStructure(form));
  EXPECT_FALSE(form_structure->ShouldBeParsed(true));
}
TEST(FormStructureTest, HeuristicsContactInfo) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("firstname");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("lastname");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Email");
  field.name = ASCIIToUTF16("email");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Phone");
  field.name = ASCIIToUTF16("phone");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address");
  field.name = ASCIIToUTF16("address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("City");
  field.name = ASCIIToUTF16("city");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Zip code");
  field.name = ASCIIToUTF16("zipcode");
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  
  ASSERT_EQ(8U, form_structure->field_count());
  ASSERT_EQ(7U, form_structure->autofill_count());
  
  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER,
      form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(4)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(5)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_ZIP, form_structure->field(6)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(7)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsAutocompleteAttribute) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = base::string16();
  field.name = ASCIIToUTF16("field1");
  field.autocomplete_attribute = "given-name";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("field2");
  field.autocomplete_attribute = "family-name";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("field3");
  field.autocomplete_attribute = "email";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  
  ASSERT_EQ(3U, form_structure->field_count());
  ASSERT_EQ(3U, form_structure->autofill_count());
  EXPECT_EQ(HTML_TYPE_GIVEN_NAME, form_structure->field(0)->html_type());
  EXPECT_EQ(HTML_TYPE_FAMILY_NAME, form_structure->field(1)->html_type());
  EXPECT_EQ(HTML_TYPE_EMAIL, form_structure->field(2)->html_type());
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(0)->heuristic_type());
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(1)->heuristic_type());
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(2)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsAutocompleteAttributePhoneTypes) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = base::string16();
  field.name = ASCIIToUTF16("field1");
  field.autocomplete_attribute = "tel-local";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("field2");
  field.autocomplete_attribute = "tel-local-prefix";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("field3");
  field.autocomplete_attribute = "tel-local-suffix";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  
  ASSERT_EQ(3U, form_structure->field_count());
  EXPECT_EQ(3U, form_structure->autofill_count());
  EXPECT_EQ(HTML_TYPE_TEL_LOCAL, form_structure->field(0)->html_type());
  EXPECT_EQ(AutofillField::IGNORED, form_structure->field(0)->phone_part());
  EXPECT_EQ(HTML_TYPE_TEL_LOCAL_PREFIX, form_structure->field(1)->html_type());
  EXPECT_EQ(AutofillField::PHONE_PREFIX,
            form_structure->field(1)->phone_part());
  EXPECT_EQ(HTML_TYPE_TEL_LOCAL_SUFFIX, form_structure->field(2)->html_type());
  EXPECT_EQ(AutofillField::PHONE_SUFFIX,
            form_structure->field(2)->phone_part());
}
TEST(FormStructureTest, AutocompleteAttributeOverridesOtherHeuristics) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("firstname");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("lastname");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Email");
  field.name = ASCIIToUTF16("email");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  EXPECT_TRUE(form_structure->ShouldBeCrowdsourced());
  ASSERT_EQ(3U, form_structure->field_count());
  ASSERT_EQ(3U, form_structure->autofill_count());
  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type());
  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type());
  EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(2)->heuristic_type());
  
  form.fields.front().autocomplete_attribute = "x-other";
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_FALSE(form_structure->IsAutofillable(true));
  EXPECT_FALSE(form_structure->ShouldBeCrowdsourced());
  ASSERT_EQ(3U, form_structure->field_count());
  ASSERT_EQ(0U, form_structure->autofill_count());
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(0)->heuristic_type());
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(1)->heuristic_type());
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(2)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsAutocompleteAttributeWithSections) {
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  
  
  field.autocomplete_attribute = "email";
  form.fields.push_back(field);
  
  field.autocomplete_attribute = "section-foo email";
  form.fields.push_back(field);
  
  
  field.autocomplete_attribute = "shipping email";
  form.fields.push_back(field);
  field.autocomplete_attribute = "billing email";
  form.fields.push_back(field);
  
  field.autocomplete_attribute = "section-foo shipping email";
  form.fields.push_back(field);
  field.autocomplete_attribute = "section-foo billing email";
  form.fields.push_back(field);
  
  
  field.autocomplete_attribute = "section--foo email";
  form.fields.push_back(field);
  
  
  
  
  field.autocomplete_attribute = "section--shipping email";
  form.fields.push_back(field);
  
  field.autocomplete_attribute = "section-foo cc-number";
  form.fields.push_back(field);
  FormStructure form_structure(form);
  form_structure.DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure.IsAutofillable(true));
  
  ASSERT_EQ(9U, form_structure.field_count());
  EXPECT_EQ(9U, form_structure.autofill_count());
  
  
  std::set<std::string> section_names;
  for (size_t i = 0; i < 9; ++i) {
    section_names.insert(form_structure.field(i)->section());
  }
  EXPECT_EQ(9U, section_names.size());
}
TEST(FormStructureTest, HeuristicsAutocompleteAttributeWithSectionsDegenerate) {
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  
  
  field.autocomplete_attribute = "email";
  form.fields.push_back(field);
  
  field.autocomplete_attribute = "section- email";
  form.fields.push_back(field);
  
  field.autocomplete_attribute = "garbage section-foo email";
  form.fields.push_back(field);
  field.autocomplete_attribute = "garbage section-bar email";
  form.fields.push_back(field);
  field.autocomplete_attribute = "garbage shipping email";
  form.fields.push_back(field);
  field.autocomplete_attribute = "garbage billing email";
  form.fields.push_back(field);
  FormStructure form_structure(form);
  form_structure.DetermineHeuristicTypes(TestAutofillMetrics());
  
  ASSERT_EQ(6U, form_structure.field_count());
  EXPECT_EQ(2U, form_structure.autofill_count());
  
  
  std::set<std::string> section_names;
  for (size_t i = 0; i < 6; ++i) {
    section_names.insert(form_structure.field(i)->section());
  }
  EXPECT_EQ(1U, section_names.size());
}
TEST(FormStructureTest, HeuristicsAutocompleteAttributeWithSectionsRepeated) {
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.autocomplete_attribute = "section-foo email";
  form.fields.push_back(field);
  field.autocomplete_attribute = "section-foo address-line1";
  form.fields.push_back(field);
  FormStructure form_structure(form);
  form_structure.DetermineHeuristicTypes(TestAutofillMetrics());
  
  ASSERT_EQ(2U, form_structure.field_count());
  EXPECT_EQ(2U, form_structure.autofill_count());
  
  
  std::set<std::string> section_names;
  for (size_t i = 0; i < 2; ++i) {
    section_names.insert(form_structure.field(i)->section());
  }
  EXPECT_EQ(1U, section_names.size());
}
TEST(FormStructureTest, HeuristicsDontOverrideAutocompleteAttributeSections) {
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.name = ASCIIToUTF16("one");
  field.autocomplete_attribute = "address-line1";
  form.fields.push_back(field);
  field.name = base::string16();
  field.autocomplete_attribute = "section-foo email";
  form.fields.push_back(field);
  field.name = base::string16();
  field.autocomplete_attribute = "name";
  form.fields.push_back(field);
  field.name = ASCIIToUTF16("two");
  field.autocomplete_attribute = "address-line1";
  form.fields.push_back(field);
  FormStructure form_structure(form);
  form_structure.DetermineHeuristicTypes(TestAutofillMetrics());
  
  ASSERT_EQ(4U, form_structure.field_count());
  EXPECT_EQ(4U, form_structure.autofill_count());
  
  
  
  EXPECT_EQ(ASCIIToUTF16("one"), form_structure.field(0)->name);
  EXPECT_EQ(ASCIIToUTF16("two"), form_structure.field(3)->name);
  EXPECT_EQ(form_structure.field(0)->section(),
            form_structure.field(3)->section());
}
TEST(FormStructureTest, HeuristicsSample8) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Your First Name:");
  field.name = ASCIIToUTF16("bill.first");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Your Last Name:");
  field.name = ASCIIToUTF16("bill.last");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Street Address Line 1:");
  field.name = ASCIIToUTF16("bill.street1");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Street Address Line 2:");
  field.name = ASCIIToUTF16("bill.street2");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("City");
  field.name = ASCIIToUTF16("bill.city");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("State (U.S.):");
  field.name = ASCIIToUTF16("bill.state");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Zip/Postal Code:");
  field.name = ASCIIToUTF16("BillTo.PostalCode");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Country:");
  field.name = ASCIIToUTF16("bill.country");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Phone Number:");
  field.name = ASCIIToUTF16("BillTo.Phone");
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(10U, form_structure->field_count());
  ASSERT_EQ(9U, form_structure->autofill_count());
  
  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(4)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_STATE, form_structure->field(5)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_ZIP, form_structure->field(6)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_COUNTRY, form_structure->field(7)->heuristic_type());
  
  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER,
      form_structure->field(8)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(9)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsSample6) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("E-mail address");
  field.name = ASCIIToUTF16("email");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Full name");
  field.name = ASCIIToUTF16("name");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Company");
  field.name = ASCIIToUTF16("company");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address");
  field.name = ASCIIToUTF16("address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("City");
  field.name = ASCIIToUTF16("city");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Zip Code");
  field.name = ASCIIToUTF16("Home.PostalCode");
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.value = ASCIIToUTF16("continue");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(7U, form_structure->field_count());
  ASSERT_EQ(6U, form_structure->autofill_count());
  
  EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(NAME_FULL, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(COMPANY_NAME, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(4)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_ZIP, form_structure->field(5)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(6)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsLabelsOnly) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("First Name");
  field.name = base::string16();
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last Name");
  field.name = base::string16();
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Email");
  field.name = base::string16();
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Phone");
  field.name = base::string16();
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address");
  field.name = base::string16();
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address");
  field.name = base::string16();
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Zip code");
  field.name = base::string16();
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(8U, form_structure->field_count());
  ASSERT_EQ(7U, form_structure->autofill_count());
  
  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER,
      form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(4)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(5)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_ZIP, form_structure->field(6)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(7)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsCreditCardInfo) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Name on Card");
  field.name = ASCIIToUTF16("name_on_card");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Card Number");
  field.name = ASCIIToUTF16("card_number");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Exp Month");
  field.name = ASCIIToUTF16("ccmonth");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Exp Year");
  field.name = ASCIIToUTF16("ccyear");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Verification");
  field.name = ASCIIToUTF16("verification");
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(6U, form_structure->field_count());
  ASSERT_EQ(5U, form_structure->autofill_count());
  
  EXPECT_EQ(CREDIT_CARD_NAME, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_MONTH, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
            form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_VERIFICATION_CODE,
            form_structure->field(4)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(5)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsCreditCardInfoWithUnknownCardField) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Name on Card");
  field.name = ASCIIToUTF16("name_on_card");
  form.fields.push_back(field);
  
  
  field.label = ASCIIToUTF16("Card image");
  field.name = ASCIIToUTF16("card_image");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Card Number");
  field.name = ASCIIToUTF16("card_number");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Exp Month");
  field.name = ASCIIToUTF16("ccmonth");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Exp Year");
  field.name = ASCIIToUTF16("ccyear");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Verification");
  field.name = ASCIIToUTF16("verification");
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(7U, form_structure->field_count());
  ASSERT_EQ(5U, form_structure->autofill_count());
  
  EXPECT_EQ(CREDIT_CARD_NAME, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_MONTH, form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
            form_structure->field(4)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_VERIFICATION_CODE,
            form_structure->field(5)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(6)->heuristic_type());
}
TEST(FormStructureTest, ThreeAddressLines) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Address Line1");
  field.name = ASCIIToUTF16("Address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address Line2");
  field.name = ASCIIToUTF16("Address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address Line3");
  field.name = ASCIIToUTF16("Address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("City");
  field.name = ASCIIToUTF16("city");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(4U, form_structure->field_count());
  ASSERT_EQ(3U, form_structure->autofill_count());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(3)->heuristic_type());
}
TEST(FormStructureTest, SurplusAddressLinesIgnored) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Address Line1");
  field.name = ASCIIToUTF16("shipping.address.addressLine1");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address Line2");
  field.name = ASCIIToUTF16("shipping.address.addressLine2");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address Line3");
  field.name = ASCIIToUTF16("billing.address.addressLine3");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address Line4");
  field.name = ASCIIToUTF16("billing.address.addressLine4");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  ASSERT_EQ(4U, form_structure->field_count());
  ASSERT_EQ(2U, form_structure->autofill_count());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(3)->heuristic_type());
}
TEST(FormStructureTest, ThreeAddressLinesExpedia) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Street:");
  field.name = ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_ads1");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Suite or Apt:");
  field.name = ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_adap");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Street address second line");
  field.name = ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_ads2");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("City:");
  field.name = ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_adct");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(4U, form_structure->field_count());
  EXPECT_EQ(3U, form_structure->autofill_count());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(3)->heuristic_type());
}
TEST(FormStructureTest, TwoAddressLinesEbay) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Address Line1");
  field.name = ASCIIToUTF16("address1");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Floor number, suite number, etc");
  field.name = ASCIIToUTF16("address2");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("City:");
  field.name = ASCIIToUTF16("city");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(3U, form_structure->field_count());
  ASSERT_EQ(3U, form_structure->autofill_count());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(2)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsStateWithProvince) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Address Line1");
  field.name = ASCIIToUTF16("Address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address Line2");
  field.name = ASCIIToUTF16("Address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("State/Province/Region");
  field.name = ASCIIToUTF16("State");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(3U, form_structure->field_count());
  ASSERT_EQ(3U, form_structure->autofill_count());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_STATE, form_structure->field(2)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsWithBilling) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("First Name*:");
  field.name = ASCIIToUTF16("editBillingAddress$firstNameBox");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last Name*:");
  field.name = ASCIIToUTF16("editBillingAddress$lastNameBox");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Company Name:");
  field.name = ASCIIToUTF16("editBillingAddress$companyBox");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address*:");
  field.name = ASCIIToUTF16("editBillingAddress$addressLine1Box");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Apt/Suite :");
  field.name = ASCIIToUTF16("editBillingAddress$addressLine2Box");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("City*:");
  field.name = ASCIIToUTF16("editBillingAddress$cityBox");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("State/Province*:");
  field.name = ASCIIToUTF16("editBillingAddress$stateDropDown");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Country*:");
  field.name = ASCIIToUTF16("editBillingAddress$countryDropDown");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Postal Code*:");
  field.name = ASCIIToUTF16("editBillingAddress$zipCodeBox");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Phone*:");
  field.name = ASCIIToUTF16("editBillingAddress$phoneBox");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Email Address*:");
  field.name = ASCIIToUTF16("email$emailBox");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(11U, form_structure->field_count());
  ASSERT_EQ(11U, form_structure->autofill_count());
  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type());
  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type());
  EXPECT_EQ(COMPANY_NAME, form_structure->field(2)->heuristic_type());
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(3)->heuristic_type());
  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(4)->heuristic_type());
  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(5)->heuristic_type());
  EXPECT_EQ(ADDRESS_HOME_STATE, form_structure->field(6)->heuristic_type());
  EXPECT_EQ(ADDRESS_HOME_COUNTRY, form_structure->field(7)->heuristic_type());
  EXPECT_EQ(ADDRESS_HOME_ZIP, form_structure->field(8)->heuristic_type());
  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER,
            form_structure->field(9)->heuristic_type());
  EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(10)->heuristic_type());
}
TEST(FormStructureTest, ThreePartPhoneNumber) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Phone:");
  field.name = ASCIIToUTF16("dayphone1");
  field.max_length = 0;
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("-");
  field.name = ASCIIToUTF16("dayphone2");
  field.max_length = 3;  
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("-");
  field.name = ASCIIToUTF16("dayphone3");
  field.max_length = 4;  
                         
                         
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("ext.:");
  field.name = ASCIIToUTF16("dayphone4");
  field.max_length = 0;
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  ASSERT_EQ(4U, form_structure->field_count());
  ASSERT_EQ(3U, form_structure->autofill_count());
  
  EXPECT_EQ(PHONE_HOME_CITY_CODE, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(PHONE_HOME_NUMBER,
            form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(PHONE_HOME_NUMBER,
            form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(3)->heuristic_type());
}
TEST(FormStructureTest, HeuristicsInfernoCC) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Name on Card");
  field.name = ASCIIToUTF16("name_on_card");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address");
  field.name = ASCIIToUTF16("billing_address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Card Number");
  field.name = ASCIIToUTF16("card_number");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Expiration Date");
  field.name = ASCIIToUTF16("expiration_month");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Expiration Year");
  field.name = ASCIIToUTF16("expiration_year");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  
  ASSERT_EQ(5U, form_structure->field_count());
  EXPECT_EQ(5U, form_structure->autofill_count());
  
  EXPECT_EQ(CREDIT_CARD_NAME, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_MONTH, form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
            form_structure->field(4)->heuristic_type());
}
TEST(FormStructureTest, CVCCodeClash) {
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Card number");
  field.name = ASCIIToUTF16("ccnumber");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("First name");
  field.name = ASCIIToUTF16("first_name");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last name");
  field.name = ASCIIToUTF16("last_name");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Expiration date");
  field.name = ASCIIToUTF16("ccexpiresmonth");
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("ccexpiresyear");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("cvc number");
  field.name = ASCIIToUTF16("csc");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  EXPECT_TRUE(form_structure->IsAutofillable(true));
  
  ASSERT_EQ(6U, form_structure->field_count());
  ASSERT_EQ(5U, form_structure->autofill_count());
  
  EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(0)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_NAME, form_structure->field(1)->heuristic_type());
  
  EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(2)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_MONTH, form_structure->field(3)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
            form_structure->field(4)->heuristic_type());
  
  EXPECT_EQ(CREDIT_CARD_VERIFICATION_CODE,
            form_structure->field(5)->heuristic_type());
}
TEST(FormStructureTest, EncodeQueryRequest) {
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("Name on Card");
  field.name = ASCIIToUTF16("name_on_card");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Address");
  field.name = ASCIIToUTF16("billing_address");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Card Number");
  field.name = ASCIIToUTF16("card_number");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Expiration Date");
  field.name = ASCIIToUTF16("expiration_month");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Expiration Year");
  field.name = ASCIIToUTF16("expiration_year");
  form.fields.push_back(field);
  
  FormFieldData checkable_field;
  checkable_field.is_checkable = true;
  checkable_field.label = ASCIIToUTF16("Checkable1");
  checkable_field.name = ASCIIToUTF16("Checkable1");
  form.fields.push_back(checkable_field);
  ScopedVector<FormStructure> forms;
  forms.push_back(new FormStructure(form));
  std::vector<std::string> encoded_signatures;
  std::string encoded_xml;
  const char kSignature1[] = "11337937696949187602";
  const char kResponse1[] =
      "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
      "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">"
      "<form signature=\"11337937696949187602\">"
      "<field signature=\"412125936\"/>"
      "<field signature=\"1917667676\"/>"
      "<field signature=\"2226358947\"/>"
      "<field signature=\"747221617\"/>"
      "<field signature=\"4108155786\"/>"
      "</form>"
      "</autofillquery>";
  ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms.get(),
                                                &encoded_signatures,
                                                &encoded_xml));
  ASSERT_EQ(1U, encoded_signatures.size());
  EXPECT_EQ(kSignature1, encoded_signatures[0]);
  EXPECT_EQ(kResponse1, encoded_xml);
  
  
  forms.push_back(new FormStructure(form));
  ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms.get(),
                                                &encoded_signatures,
                                                &encoded_xml));
  ASSERT_EQ(1U, encoded_signatures.size());
  EXPECT_EQ(kSignature1, encoded_signatures[0]);
  EXPECT_EQ(kResponse1, encoded_xml);
  
  for (size_t i = 0; i < 5; ++i) {
    field.label = ASCIIToUTF16("Address");
    field.name = ASCIIToUTF16("address");
    form.fields.push_back(field);
  }
  forms.push_back(new FormStructure(form));
  ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms.get(),
                                                &encoded_signatures,
                                                &encoded_xml));
  ASSERT_EQ(2U, encoded_signatures.size());
  EXPECT_EQ(kSignature1, encoded_signatures[0]);
  const char kSignature2[] = "8308881815906226214";
  EXPECT_EQ(kSignature2, encoded_signatures[1]);
  const char kResponse2[] =
      "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
      "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">"
      "<form signature=\"11337937696949187602\">"
      "<field signature=\"412125936\"/>"
      "<field signature=\"1917667676\"/>"
      "<field signature=\"2226358947\"/>"
      "<field signature=\"747221617\"/>"
      "<field signature=\"4108155786\"/>"
      "</form>"
      "<form signature=\"8308881815906226214\">"
      "<field signature=\"412125936\"/>"
      "<field signature=\"1917667676\"/>"
      "<field signature=\"2226358947\"/>"
      "<field signature=\"747221617\"/>"
      "<field signature=\"4108155786\"/>"
      "<field signature=\"509334676\"/>"
      "<field signature=\"509334676\"/>"
      "<field signature=\"509334676\"/>"
      "<field signature=\"509334676\"/>"
      "<field signature=\"509334676\"/>"
      "</form>"
      "</autofillquery>";
  EXPECT_EQ(kResponse2, encoded_xml);
  FormData malformed_form(form);
  
  
  for (size_t i = 0; i < 50; ++i) {
    field.label = ASCIIToUTF16("Address");
    field.name = ASCIIToUTF16("address");
    malformed_form.fields.push_back(field);
  }
  forms.push_back(new FormStructure(malformed_form));
  ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms.get(),
                                                &encoded_signatures,
                                                &encoded_xml));
  ASSERT_EQ(2U, encoded_signatures.size());
  EXPECT_EQ(kSignature1, encoded_signatures[0]);
  EXPECT_EQ(kSignature2, encoded_signatures[1]);
  EXPECT_EQ(kResponse2, encoded_xml);
  
  ScopedVector<FormStructure> bad_forms;
  bad_forms.push_back(new FormStructure(malformed_form));
  EXPECT_FALSE(FormStructure::EncodeQueryRequest(bad_forms.get(),
                                                 &encoded_signatures,
                                                 &encoded_xml));
  EXPECT_EQ(0U, encoded_signatures.size());
  EXPECT_EQ("", encoded_xml);
}
TEST(FormStructureTest, EncodeUploadRequest) {
  scoped_ptr<FormStructure> form_structure;
  std::vector<ServerFieldTypeSet> possible_field_types;
  FormData form;
  form.method = ASCIIToUTF16("post");
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("firstname");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(NAME_FIRST);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("lastname");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(NAME_LAST);
  field.label = ASCIIToUTF16("Email");
  field.name = ASCIIToUTF16("email");
  field.form_control_type = "email";
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(EMAIL_ADDRESS);
  field.label = ASCIIToUTF16("Phone");
  field.name = ASCIIToUTF16("phone");
  field.form_control_type = "number";
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(PHONE_HOME_WHOLE_NUMBER);
  field.label = ASCIIToUTF16("Country");
  field.name = ASCIIToUTF16("country");
  field.form_control_type = "select-one";
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(ADDRESS_HOME_COUNTRY);
  
  FormFieldData checkable_field;
  checkable_field.is_checkable = true;
  checkable_field.label = ASCIIToUTF16("Checkable1");
  checkable_field.name = ASCIIToUTF16("Checkable1");
  form.fields.push_back(checkable_field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(ADDRESS_HOME_COUNTRY);
  form_structure.reset(new FormStructure(form));
  ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
  for (size_t i = 0; i < form_structure->field_count(); ++i)
    form_structure->field(i)->set_possible_types(possible_field_types[i]);
  ServerFieldTypeSet available_field_types;
  available_field_types.insert(NAME_FIRST);
  available_field_types.insert(NAME_LAST);
  available_field_types.insert(ADDRESS_HOME_LINE1);
  available_field_types.insert(ADDRESS_HOME_LINE2);
  available_field_types.insert(ADDRESS_HOME_COUNTRY);
  available_field_types.insert(ADDRESS_BILLING_LINE1);
  available_field_types.insert(ADDRESS_BILLING_LINE2);
  available_field_types.insert(EMAIL_ADDRESS);
  available_field_types.insert(PHONE_HOME_WHOLE_NUMBER);
  std::string encoded_xml;
  EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false,
                                                  &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\" "
            "formsignature=\"8736493185895608956\" autofillused=\"false\" "
            "datapresent=\"144200030e\">"
            "<field signature=\"3763331450\" autofilltype=\"3\"/>"
            "<field signature=\"3494530716\" autofilltype=\"5\"/>"
            "<field signature=\"1029417091\" autofilltype=\"9\"/>"
            "<field signature=\"466116101\" autofilltype=\"14\"/>"
            "<field signature=\"2799270304\" autofilltype=\"36\"/>"
            "</autofillupload>",
            encoded_xml);
  EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true,
                                                  &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\" "
            "formsignature=\"8736493185895608956\" autofillused=\"true\" "
            "datapresent=\"144200030e\">"
            "<field signature=\"3763331450\" autofilltype=\"3\"/>"
            "<field signature=\"3494530716\" autofilltype=\"5\"/>"
            "<field signature=\"1029417091\" autofilltype=\"9\"/>"
            "<field signature=\"466116101\" autofilltype=\"14\"/>"
            "<field signature=\"2799270304\" autofilltype=\"36\"/>"
            "</autofillupload>",
            encoded_xml);
  
  for (size_t i = 0; i < 2; ++i) {
    field.label = ASCIIToUTF16("Address");
    field.name = ASCIIToUTF16("address");
    field.form_control_type = "text";
    form.fields.push_back(field);
    possible_field_types.push_back(ServerFieldTypeSet());
    possible_field_types.back().insert(ADDRESS_HOME_LINE1);
    possible_field_types.back().insert(ADDRESS_HOME_LINE2);
    possible_field_types.back().insert(ADDRESS_BILLING_LINE1);
    possible_field_types.back().insert(ADDRESS_BILLING_LINE2);
  }
  form_structure.reset(new FormStructure(form));
  ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
  for (size_t i = 0; i < form_structure->field_count(); ++i)
    form_structure->field(i)->set_possible_types(possible_field_types[i]);
  EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false,
                                                  &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\" "
            "formsignature=\"7816485729218079147\" autofillused=\"false\" "
            "datapresent=\"144200030e\">"
            "<field signature=\"3763331450\" autofilltype=\"3\"/>"
            "<field signature=\"3494530716\" autofilltype=\"5\"/>"
            "<field signature=\"1029417091\" autofilltype=\"9\"/>"
            "<field signature=\"466116101\" autofilltype=\"14\"/>"
            "<field signature=\"2799270304\" autofilltype=\"36\"/>"
            "<field signature=\"509334676\" autofilltype=\"30\"/>"
            "<field signature=\"509334676\" autofilltype=\"31\"/>"
            "<field signature=\"509334676\" autofilltype=\"37\"/>"
            "<field signature=\"509334676\" autofilltype=\"38\"/>"
            "<field signature=\"509334676\" autofilltype=\"30\"/>"
            "<field signature=\"509334676\" autofilltype=\"31\"/>"
            "<field signature=\"509334676\" autofilltype=\"37\"/>"
            "<field signature=\"509334676\" autofilltype=\"38\"/>"
            "</autofillupload>",
            encoded_xml);
  
  for (size_t i = 0; i < 50; ++i) {
    field.label = ASCIIToUTF16("Address");
    field.name = ASCIIToUTF16("address");
    field.form_control_type = "text";
    form.fields.push_back(field);
    possible_field_types.push_back(ServerFieldTypeSet());
    possible_field_types.back().insert(ADDRESS_HOME_LINE1);
    possible_field_types.back().insert(ADDRESS_HOME_LINE2);
    possible_field_types.back().insert(ADDRESS_BILLING_LINE1);
    possible_field_types.back().insert(ADDRESS_BILLING_LINE2);
  }
  form_structure.reset(new FormStructure(form));
  ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
  for (size_t i = 0; i < form_structure->field_count(); ++i)
    form_structure->field(i)->set_possible_types(possible_field_types[i]);
  EXPECT_FALSE(form_structure->EncodeUploadRequest(available_field_types, false,
                                                   &encoded_xml));
}
TEST(FormStructureTest, EncodeFieldAssignments) {
  scoped_ptr<FormStructure> form_structure;
  std::vector<ServerFieldTypeSet> possible_field_types;
  FormData form;
  form.method = ASCIIToUTF16("post");
  form_structure.reset(new FormStructure(form));
  form_structure->DetermineHeuristicTypes(TestAutofillMetrics());
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("firstname");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(NAME_FIRST);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("lastname");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(NAME_LAST);
  field.label = ASCIIToUTF16("Email");
  field.name = ASCIIToUTF16("email");
  field.form_control_type = "email";
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(EMAIL_ADDRESS);
  field.label = ASCIIToUTF16("Phone");
  field.name = ASCIIToUTF16("phone");
  field.form_control_type = "number";
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(PHONE_HOME_WHOLE_NUMBER);
  field.label = ASCIIToUTF16("Country");
  field.name = ASCIIToUTF16("country");
  field.form_control_type = "select-one";
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(ADDRESS_HOME_COUNTRY);
  
  FormFieldData checkable_field;
  checkable_field.is_checkable = true;
  checkable_field.label = ASCIIToUTF16("Checkable1");
  checkable_field.name = ASCIIToUTF16("Checkable1");
  form.fields.push_back(checkable_field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(ADDRESS_HOME_COUNTRY);
  form_structure.reset(new FormStructure(form));
  ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
  for (size_t i = 0; i < form_structure->field_count(); ++i)
    form_structure->field(i)->set_possible_types(possible_field_types[i]);
  ServerFieldTypeSet available_field_types;
  available_field_types.insert(NAME_FIRST);
  available_field_types.insert(NAME_LAST);
  available_field_types.insert(ADDRESS_HOME_LINE1);
  available_field_types.insert(ADDRESS_HOME_LINE2);
  available_field_types.insert(ADDRESS_HOME_COUNTRY);
  available_field_types.insert(ADDRESS_BILLING_LINE1);
  available_field_types.insert(ADDRESS_BILLING_LINE2);
  available_field_types.insert(EMAIL_ADDRESS);
  available_field_types.insert(PHONE_HOME_WHOLE_NUMBER);
  std::string encoded_xml;
  EXPECT_TRUE(form_structure->EncodeFieldAssignments(
      available_field_types, &encoded_xml));
  EXPECT_EQ(
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
      "<fieldassignments formsignature=\"8736493185895608956\">"
      "<fields fieldid=\"3763331450\" fieldtype=\"3\" name=\"firstname\"/>"
      "<fields fieldid=\"3494530716\" fieldtype=\"5\" name=\"lastname\"/>"
      "<fields fieldid=\"1029417091\" fieldtype=\"9\" name=\"email\"/>"
      "<fields fieldid=\"466116101\" fieldtype=\"14\" name=\"phone\"/>"
      "<fields fieldid=\"2799270304\" fieldtype=\"36\" name=\"country\"/>"
      "<fields fieldid=\"3410250678\" fieldtype=\"36\" name=\"Checkable1\"/>"
      "</fieldassignments>",
      encoded_xml);
  
  for (size_t i = 0; i < 2; ++i) {
    field.label = ASCIIToUTF16("Address");
    field.name = ASCIIToUTF16("address");
    field.form_control_type = "text";
    form.fields.push_back(field);
    possible_field_types.push_back(ServerFieldTypeSet());
    possible_field_types.back().insert(ADDRESS_HOME_LINE1);
    possible_field_types.back().insert(ADDRESS_HOME_LINE2);
    possible_field_types.back().insert(ADDRESS_BILLING_LINE1);
    possible_field_types.back().insert(ADDRESS_BILLING_LINE2);
  }
  form_structure.reset(new FormStructure(form));
  ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
  for (size_t i = 0; i < form_structure->field_count(); ++i)
    form_structure->field(i)->set_possible_types(possible_field_types[i]);
  EXPECT_TRUE(form_structure->EncodeFieldAssignments(
      available_field_types, &encoded_xml));
  EXPECT_EQ(
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
      "<fieldassignments formsignature=\"7816485729218079147\">"
      "<fields fieldid=\"3763331450\" fieldtype=\"3\" name=\"firstname\"/>"
      "<fields fieldid=\"3494530716\" fieldtype=\"5\" name=\"lastname\"/>"
      "<fields fieldid=\"1029417091\" fieldtype=\"9\" name=\"email\"/>"
      "<fields fieldid=\"466116101\" fieldtype=\"14\" name=\"phone\"/>"
      "<fields fieldid=\"2799270304\" fieldtype=\"36\" name=\"country\"/>"
      "<fields fieldid=\"3410250678\" fieldtype=\"36\" name=\"Checkable1\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"30\" name=\"address\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"31\" name=\"address\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"37\" name=\"address\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"38\" name=\"address\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"30\" name=\"address\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"31\" name=\"address\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"37\" name=\"address\"/>"
      "<fields fieldid=\"509334676\" fieldtype=\"38\" name=\"address\"/>"
      "</fieldassignments>",
      encoded_xml);
}
TEST(FormStructureTest, CheckDataPresence) {
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("first");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("last");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Email");
  field.name = ASCIIToUTF16("email");
  form.fields.push_back(field);
  FormStructure form_structure(form);
  ServerFieldTypeSet unknown_type;
  unknown_type.insert(UNKNOWN_TYPE);
  for (size_t i = 0; i < form_structure.field_count(); ++i)
    form_structure.field(i)->set_possible_types(unknown_type);
  
  
  
  ServerFieldTypeSet available_field_types;
  std::string encoded_xml;
  EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false,
                                                 &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"6402244543831589061\" autofillused=\"false\""
            " datapresent=\"\">"
            "<field signature=\"1089846351\" autofilltype=\"1\"/>"
            "<field signature=\"2404144663\" autofilltype=\"1\"/>"
            "<field signature=\"420638584\" autofilltype=\"1\"/>"
            "</autofillupload>",
            encoded_xml);
  
  
  
  
  
  
  
  
  
  
  available_field_types.clear();
  available_field_types.insert(NAME_FIRST);
  available_field_types.insert(NAME_LAST);
  available_field_types.insert(NAME_FULL);
  available_field_types.insert(EMAIL_ADDRESS);
  available_field_types.insert(ADDRESS_HOME_LINE1);
  available_field_types.insert(ADDRESS_HOME_CITY);
  EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false,
                                                 &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"6402244543831589061\" autofillused=\"false\""
            " datapresent=\"1540000240\">"
            "<field signature=\"1089846351\" autofilltype=\"1\"/>"
            "<field signature=\"2404144663\" autofilltype=\"1\"/>"
            "<field signature=\"420638584\" autofilltype=\"1\"/>"
            "</autofillupload>",
            encoded_xml);
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  available_field_types.clear();
  available_field_types.insert(NAME_FIRST);
  available_field_types.insert(NAME_MIDDLE);
  available_field_types.insert(NAME_LAST);
  available_field_types.insert(NAME_MIDDLE_INITIAL);
  available_field_types.insert(NAME_FULL);
  available_field_types.insert(EMAIL_ADDRESS);
  available_field_types.insert(PHONE_HOME_NUMBER);
  available_field_types.insert(PHONE_HOME_CITY_CODE);
  available_field_types.insert(PHONE_HOME_COUNTRY_CODE);
  available_field_types.insert(PHONE_HOME_CITY_AND_NUMBER);
  available_field_types.insert(PHONE_HOME_WHOLE_NUMBER);
  available_field_types.insert(ADDRESS_HOME_LINE1);
  available_field_types.insert(ADDRESS_HOME_LINE2);
  available_field_types.insert(ADDRESS_HOME_CITY);
  available_field_types.insert(ADDRESS_HOME_STATE);
  available_field_types.insert(ADDRESS_HOME_ZIP);
  available_field_types.insert(ADDRESS_HOME_COUNTRY);
  available_field_types.insert(COMPANY_NAME);
  EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false,
                                                 &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"6402244543831589061\" autofillused=\"false\""
            " datapresent=\"1f7e000378000008\">"
            "<field signature=\"1089846351\" autofilltype=\"1\"/>"
            "<field signature=\"2404144663\" autofilltype=\"1\"/>"
            "<field signature=\"420638584\" autofilltype=\"1\"/>"
            "</autofillupload>",
            encoded_xml);
  
  
  
  
  
  
  
  
  
  
  
  available_field_types.clear();
  available_field_types.insert(CREDIT_CARD_NAME);
  available_field_types.insert(CREDIT_CARD_NUMBER);
  available_field_types.insert(CREDIT_CARD_EXP_MONTH);
  available_field_types.insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
  available_field_types.insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
  available_field_types.insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
  available_field_types.insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
  EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false,
                                                 &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"6402244543831589061\" autofillused=\"false\""
            " datapresent=\"0000000000001fc0\">"
            "<field signature=\"1089846351\" autofilltype=\"1\"/>"
            "<field signature=\"2404144663\" autofilltype=\"1\"/>"
            "<field signature=\"420638584\" autofilltype=\"1\"/>"
            "</autofillupload>",
            encoded_xml);
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  available_field_types.clear();
  available_field_types.insert(NAME_FIRST);
  available_field_types.insert(NAME_MIDDLE);
  available_field_types.insert(NAME_LAST);
  available_field_types.insert(NAME_MIDDLE_INITIAL);
  available_field_types.insert(NAME_FULL);
  available_field_types.insert(EMAIL_ADDRESS);
  available_field_types.insert(PHONE_HOME_NUMBER);
  available_field_types.insert(PHONE_HOME_CITY_CODE);
  available_field_types.insert(PHONE_HOME_COUNTRY_CODE);
  available_field_types.insert(PHONE_HOME_CITY_AND_NUMBER);
  available_field_types.insert(PHONE_HOME_WHOLE_NUMBER);
  available_field_types.insert(ADDRESS_HOME_LINE1);
  available_field_types.insert(ADDRESS_HOME_LINE2);
  available_field_types.insert(ADDRESS_HOME_CITY);
  available_field_types.insert(ADDRESS_HOME_STATE);
  available_field_types.insert(ADDRESS_HOME_ZIP);
  available_field_types.insert(ADDRESS_HOME_COUNTRY);
  available_field_types.insert(CREDIT_CARD_NAME);
  available_field_types.insert(CREDIT_CARD_NUMBER);
  available_field_types.insert(CREDIT_CARD_EXP_MONTH);
  available_field_types.insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
  available_field_types.insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
  available_field_types.insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
  available_field_types.insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
  available_field_types.insert(COMPANY_NAME);
  EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false,
                                                 &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"6402244543831589061\" autofillused=\"false\""
            " datapresent=\"1f7e000378001fc8\">"
            "<field signature=\"1089846351\" autofilltype=\"1\"/>"
            "<field signature=\"2404144663\" autofilltype=\"1\"/>"
            "<field signature=\"420638584\" autofilltype=\"1\"/>"
            "</autofillupload>",
            encoded_xml);
}
TEST(FormStructureTest, CheckMultipleTypes) {
  
  
  
  
  
  
  
  
  
  
  
  
  ServerFieldTypeSet available_field_types;
  available_field_types.insert(NAME_FIRST);
  available_field_types.insert(NAME_LAST);
  available_field_types.insert(EMAIL_ADDRESS);
  available_field_types.insert(ADDRESS_HOME_LINE1);
  available_field_types.insert(ADDRESS_HOME_LINE2);
  available_field_types.insert(ADDRESS_HOME_CITY);
  available_field_types.insert(ADDRESS_HOME_STATE);
  available_field_types.insert(COMPANY_NAME);
  
  scoped_ptr<FormStructure> form_structure;
  std::vector<ServerFieldTypeSet> possible_field_types;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("email");
  field.name = ASCIIToUTF16("email");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(EMAIL_ADDRESS);
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("first");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(NAME_FIRST);
  field.label = ASCIIToUTF16("Last Name");
  field.name = ASCIIToUTF16("last");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(NAME_LAST);
  field.label = ASCIIToUTF16("Address");
  field.name = ASCIIToUTF16("address");
  form.fields.push_back(field);
  possible_field_types.push_back(ServerFieldTypeSet());
  possible_field_types.back().insert(ADDRESS_HOME_LINE1);
  form_structure.reset(new FormStructure(form));
  for (size_t i = 0; i < form_structure->field_count(); ++i)
    form_structure->field(i)->set_possible_types(possible_field_types[i]);
  std::string encoded_xml;
  
  EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false,
                                                  &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"18062476096658145866\" autofillused=\"false\""
            " datapresent=\"1440000360000008\">"
            "<field signature=\"420638584\" autofilltype=\"9\"/>"
            "<field signature=\"1089846351\" autofilltype=\"3\"/>"
            "<field signature=\"2404144663\" autofilltype=\"5\"/>"
            "<field signature=\"509334676\" autofilltype=\"30\"/>"
            "</autofillupload>",
            encoded_xml);
  
  possible_field_types[2].insert(NAME_FIRST);
  form_structure->field(2)->set_possible_types(possible_field_types[2]);
  EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false,
                                                  &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"18062476096658145866\" autofillused=\"false\""
            " datapresent=\"1440000360000008\">"
            "<field signature=\"420638584\" autofilltype=\"9\"/>"
            "<field signature=\"1089846351\" autofilltype=\"3\"/>"
            "<field signature=\"2404144663\" autofilltype=\"3\"/>"
            "<field signature=\"2404144663\" autofilltype=\"5\"/>"
            "<field signature=\"509334676\" autofilltype=\"30\"/>"
            "</autofillupload>",
            encoded_xml);
  possible_field_types[3].insert(ADDRESS_HOME_LINE2);
  form_structure->field(form_structure->field_count() - 1)->set_possible_types(
      possible_field_types[form_structure->field_count() - 1]);
  EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false,
                                                  &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"18062476096658145866\" autofillused=\"false\""
            " datapresent=\"1440000360000008\">"
            "<field signature=\"420638584\" autofilltype=\"9\"/>"
            "<field signature=\"1089846351\" autofilltype=\"3\"/>"
            "<field signature=\"2404144663\" autofilltype=\"3\"/>"
            "<field signature=\"2404144663\" autofilltype=\"5\"/>"
            "<field signature=\"509334676\" autofilltype=\"30\"/>"
            "<field signature=\"509334676\" autofilltype=\"31\"/>"
            "</autofillupload>",
            encoded_xml);
  possible_field_types[3].clear();
  possible_field_types[3].insert(ADDRESS_HOME_LINE1);
  possible_field_types[3].insert(COMPANY_NAME);
  form_structure->field(form_structure->field_count() - 1)->set_possible_types(
      possible_field_types[form_structure->field_count() - 1]);
  EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false,
                                                  &encoded_xml));
  EXPECT_EQ("<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>"
            "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
            " formsignature=\"18062476096658145866\" autofillused=\"false\""
            " datapresent=\"1440000360000008\">"
            "<field signature=\"420638584\" autofilltype=\"9\"/>"
            "<field signature=\"1089846351\" autofilltype=\"3\"/>"
            "<field signature=\"2404144663\" autofilltype=\"3\"/>"
            "<field signature=\"2404144663\" autofilltype=\"5\"/>"
            "<field signature=\"509334676\" autofilltype=\"30\"/>"
            "<field signature=\"509334676\" autofilltype=\"60\"/>"
            "</autofillupload>",
            encoded_xml);
}
TEST(FormStructureTest, CheckFormSignature) {
  
  scoped_ptr<FormStructure> form_structure;
  FormData form;
  form.method = ASCIIToUTF16("post");
  FormFieldData field;
  field.form_control_type = "text";
  field.label = ASCIIToUTF16("email");
  field.name = ASCIIToUTF16("email");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("First Name");
  field.name = ASCIIToUTF16("first");
  form.fields.push_back(field);
  
  field.label = ASCIIToUTF16("Select");
  field.name = ASCIIToUTF16("Select");
  field.form_control_type = "checkbox";
  field.is_checkable = true;
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  EXPECT_EQ(FormStructureTest::Hash64Bit(
      std::string("://&&email&first")),
      form_structure->FormSignature());
  form.origin = GURL(std::string("http://www.facebook.com"));
  form_structure.reset(new FormStructure(form));
  EXPECT_EQ(FormStructureTest::Hash64Bit(
      std::string("http://www.facebook.com&&email&first")),
      form_structure->FormSignature());
  form.action = GURL(std::string("https://login.facebook.com/path"));
  form_structure.reset(new FormStructure(form));
  EXPECT_EQ(FormStructureTest::Hash64Bit(
      std::string("https://login.facebook.com&&email&first")),
      form_structure->FormSignature());
  form.name = ASCIIToUTF16("login_form");
  form_structure.reset(new FormStructure(form));
  EXPECT_EQ(FormStructureTest::Hash64Bit(
      std::string("https://login.facebook.com&login_form&email&first")),
      form_structure->FormSignature());
  field.is_checkable = false;
  field.label = ASCIIToUTF16("Random Field label");
  field.name = ASCIIToUTF16("random1234");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Random Field label2");
  field.name = ASCIIToUTF16("random12345");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Random Field label3");
  field.name = ASCIIToUTF16("1random12345678");
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("Random Field label3");
  field.name = ASCIIToUTF16("12345random");
  form.fields.push_back(field);
  form_structure.reset(new FormStructure(form));
  EXPECT_EQ(FormStructureTest::Hash64Bit(
      std::string("https://login.facebook.com&login_form&email&first&"
                  "random1234&random&1random&random")),
      form_structure->FormSignature());
}
TEST(FormStructureTest, ToFormData) {
  FormData form;
  form.name = ASCIIToUTF16("the-name");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://cool.com");
  form.action = form.origin.Resolve("/login");
  FormFieldData field;
  field.label = ASCIIToUTF16("username");
  field.name = ASCIIToUTF16("username");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("password");
  field.name = ASCIIToUTF16("password");
  field.form_control_type = "password";
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("Submit");
  field.form_control_type = "submit";
  form.fields.push_back(field);
  EXPECT_EQ(form, FormStructure(form).ToFormData());
  
  
  form.user_submitted = true;
  EXPECT_NE(form, FormStructure(form).ToFormData());
}
TEST(FormStructureTest, SkipFieldTest) {
  FormData form;
  form.name = ASCIIToUTF16("the-name");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://cool.com");
  form.action = form.origin.Resolve("/login");
  FormFieldData field;
  field.label = ASCIIToUTF16("username");
  field.name = ASCIIToUTF16("username");
  field.form_control_type = "text";
  form.fields.push_back(field);
  field.label = ASCIIToUTF16("select");
  field.name = ASCIIToUTF16("select");
  field.form_control_type = "checkbox";
  field.is_checkable = true;
  form.fields.push_back(field);
  field.label = base::string16();
  field.name = ASCIIToUTF16("email");
  field.form_control_type = "text";
  field.is_checkable = false;
  form.fields.push_back(field);
  ScopedVector<FormStructure> forms;
  forms.push_back(new FormStructure(form));
  std::vector<std::string> encoded_signatures;
  std::string encoded_xml;
  const char kSignature[] = "18006745212084723782";
  const char kResponse[] =
      "<\?xml version=\"1.0\" encoding=\"UTF-8\"?>"
      "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">"
      "<form signature=\"18006745212084723782\">"
      "<field signature=\"239111655\"/>"
      "<field signature=\"420638584\"/>"
      "</form>"
      "</autofillquery>";
  ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms.get(),
                                                &encoded_signatures,
                                                &encoded_xml));
  ASSERT_EQ(1U, encoded_signatures.size());
  EXPECT_EQ(kSignature, encoded_signatures[0]);
  EXPECT_EQ(kResponse, encoded_xml);
}
TEST(FormStructureTest, PossibleValues) {
  FormData form_data;
  FormFieldData field;
  field.autocomplete_attribute = "billing country";
  field.option_contents.push_back(ASCIIToUTF16("Down Under"));
  field.option_values.push_back(ASCIIToUTF16("AU"));
  field.option_contents.push_back(ASCIIToUTF16("Fr"));
  field.option_values.push_back(ASCIIToUTF16(""));
  field.option_contents.push_back(ASCIIToUTF16("Germany"));
  field.option_values.push_back(ASCIIToUTF16("GRMNY"));
  form_data.fields.push_back(field);
  FormStructure form_structure(form_data);
  bool unused;
  form_structure.ParseFieldTypesFromAutocompleteAttributes(&unused, &unused);
  
  std::set<base::string16> possible_values =
      form_structure.PossibleValues(ADDRESS_BILLING_COUNTRY);
  EXPECT_EQ(5U, possible_values.size());
  EXPECT_EQ(1U, possible_values.count(ASCIIToUTF16("AU")));
  EXPECT_EQ(1U, possible_values.count(ASCIIToUTF16("FR")));
  EXPECT_EQ(1U, possible_values.count(ASCIIToUTF16("DOWN UNDER")));
  EXPECT_EQ(1U, possible_values.count(ASCIIToUTF16("GERMANY")));
  EXPECT_EQ(1U, possible_values.count(ASCIIToUTF16("GRMNY")));
  EXPECT_EQ(0U, possible_values.count(ASCIIToUTF16("Fr")));
  EXPECT_EQ(0U, possible_values.count(ASCIIToUTF16("DE")));
  
  EXPECT_EQ(0U, form_structure.PossibleValues(ADDRESS_HOME_COUNTRY).size());
  
  FormFieldData freeform_field;
  freeform_field.autocomplete_attribute = "billing country";
  form_data.fields.push_back(freeform_field);
  FormStructure form_structure2(form_data);
  form_structure2.ParseFieldTypesFromAutocompleteAttributes(&unused, &unused);
  EXPECT_EQ(0U, form_structure2.PossibleValues(ADDRESS_BILLING_COUNTRY).size());
}
}