autofill_merge_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <vector> 6 7#include "base/basictypes.h" 8#include "base/files/file_path.h" 9#include "base/strings/string_util.h" 10#include "base/strings/utf_string_conversions.h" 11#include "components/autofill/core/browser/autofill_common_test.h" 12#include "components/autofill/core/browser/autofill_type.h" 13#include "components/autofill/core/browser/data_driven_test.h" 14#include "components/autofill/core/browser/form_structure.h" 15#include "components/autofill/core/browser/personal_data_manager.h" 16#include "components/autofill/core/common/form_data.h" 17#include "testing/gtest/include/gtest/gtest.h" 18#include "third_party/WebKit/public/web/WebInputElement.h" 19#include "url/gurl.h" 20 21namespace autofill { 22 23namespace { 24 25const base::FilePath::CharType kTestName[] = FILE_PATH_LITERAL("merge"); 26const base::FilePath::CharType kFileNamePattern[] = FILE_PATH_LITERAL("*.in"); 27 28const char kFieldSeparator[] = ": "; 29const char kProfileSeparator[] = "---"; 30const size_t kFieldOffset = arraysize(kFieldSeparator) - 1; 31 32const AutofillFieldType kProfileFieldTypes[] = { 33 NAME_FIRST, 34 NAME_MIDDLE, 35 NAME_LAST, 36 EMAIL_ADDRESS, 37 COMPANY_NAME, 38 ADDRESS_HOME_LINE1, 39 ADDRESS_HOME_LINE2, 40 ADDRESS_HOME_CITY, 41 ADDRESS_HOME_STATE, 42 ADDRESS_HOME_ZIP, 43 ADDRESS_HOME_COUNTRY, 44 PHONE_HOME_WHOLE_NUMBER 45}; 46 47// Serializes the |profiles| into a string. 48std::string SerializeProfiles(const std::vector<AutofillProfile*>& profiles) { 49 std::string result; 50 for (size_t i = 0; i < profiles.size(); ++i) { 51 result += kProfileSeparator; 52 result += "\n"; 53 for (size_t j = 0; j < arraysize(kProfileFieldTypes); ++j) { 54 AutofillFieldType type = kProfileFieldTypes[j]; 55 std::vector<base::string16> values; 56 profiles[i]->GetRawMultiInfo(type, &values); 57 for (size_t k = 0; k < values.size(); ++k) { 58 result += AutofillType::FieldTypeToString(type); 59 result += kFieldSeparator; 60 result += UTF16ToUTF8(values[k]); 61 result += "\n"; 62 } 63 } 64 } 65 66 return result; 67} 68 69class PersonalDataManagerMock : public PersonalDataManager { 70 public: 71 PersonalDataManagerMock(); 72 virtual ~PersonalDataManagerMock(); 73 74 // Reset the saved profiles. 75 void Reset(); 76 77 // PersonalDataManager: 78 virtual void SaveImportedProfile(const AutofillProfile& profile) OVERRIDE; 79 virtual const std::vector<AutofillProfile*>& web_profiles() const OVERRIDE; 80 81 private: 82 ScopedVector<AutofillProfile> profiles_; 83 84 DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerMock); 85}; 86 87PersonalDataManagerMock::PersonalDataManagerMock() 88 : PersonalDataManager("en-US") { 89} 90 91PersonalDataManagerMock::~PersonalDataManagerMock() { 92} 93 94void PersonalDataManagerMock::Reset() { 95 profiles_.clear(); 96} 97 98void PersonalDataManagerMock::SaveImportedProfile( 99 const AutofillProfile& profile) { 100 std::vector<AutofillProfile> profiles; 101 if (!MergeProfile(profile, profiles_.get(), "en-US", &profiles)) 102 profiles_.push_back(new AutofillProfile(profile)); 103} 104 105const std::vector<AutofillProfile*>& PersonalDataManagerMock::web_profiles() 106 const { 107 return profiles_.get(); 108} 109 110} // namespace 111 112// A data-driven test for verifying merging of Autofill profiles. Each input is 113// a structured dump of a set of implicitly detected autofill profiles. The 114// corresponding output file is a dump of the saved profiles that result from 115// importing the input profiles. The output file format is identical to the 116// input format. 117class AutofillMergeTest : public testing::Test, 118 public DataDrivenTest { 119 protected: 120 AutofillMergeTest(); 121 virtual ~AutofillMergeTest(); 122 123 // testing::Test: 124 virtual void SetUp(); 125 126 // DataDrivenTest: 127 virtual void GenerateResults(const std::string& input, 128 std::string* output) OVERRIDE; 129 130 // Deserializes a set of Autofill profiles from |profiles|, imports each 131 // sequentially, and fills |merged_profiles| with the serialized result. 132 void MergeProfiles(const std::string& profiles, std::string* merged_profiles); 133 134 PersonalDataManagerMock personal_data_; 135 136 private: 137 DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest); 138}; 139 140AutofillMergeTest::AutofillMergeTest() : DataDrivenTest() { 141} 142 143AutofillMergeTest::~AutofillMergeTest() { 144} 145 146void AutofillMergeTest::SetUp() { 147 test::DisableSystemServices(NULL); 148} 149 150void AutofillMergeTest::GenerateResults(const std::string& input, 151 std::string* output) { 152 MergeProfiles(input, output); 153} 154 155void AutofillMergeTest::MergeProfiles(const std::string& profiles, 156 std::string* merged_profiles) { 157 // Start with no saved profiles. 158 personal_data_.Reset(); 159 160 // Create a test form. 161 FormData form; 162 form.name = ASCIIToUTF16("MyTestForm"); 163 form.method = ASCIIToUTF16("POST"); 164 form.origin = GURL("https://www.example.com/origin.html"); 165 form.action = GURL("https://www.example.com/action.html"); 166 form.user_submitted = true; 167 168 // Parse the input line by line. 169 std::vector<std::string> lines; 170 Tokenize(profiles, "\n", &lines); 171 for (size_t i = 0; i < lines.size(); ++i) { 172 std::string line = lines[i]; 173 174 if (line != kProfileSeparator) { 175 // Add a field to the current profile. 176 size_t separator_pos = line.find(kFieldSeparator); 177 ASSERT_NE(std::string::npos, separator_pos); 178 base::string16 field_type = UTF8ToUTF16(line.substr(0, separator_pos)); 179 base::string16 value = 180 UTF8ToUTF16(line.substr(separator_pos + kFieldOffset)); 181 182 FormFieldData field; 183 field.label = field_type; 184 field.name = field_type; 185 field.value = value; 186 field.form_control_type = "text"; 187 form.fields.push_back(field); 188 } 189 190 // The first line is always a profile separator, and the last profile is not 191 // followed by an explicit separator. 192 if ((i > 0 && line == kProfileSeparator) || i == lines.size() - 1) { 193 // Reached the end of a profile. Try to import it. 194 FormStructure form_structure(form, std::string()); 195 for (size_t i = 0; i < form_structure.field_count(); ++i) { 196 // Set the heuristic type for each field, which is currently serialized 197 // into the field's name. 198 AutofillField* field = 199 const_cast<AutofillField*>(form_structure.field(i)); 200 AutofillFieldType type = 201 AutofillType::StringToFieldType(UTF16ToUTF8(field->name)); 202 field->set_heuristic_type(type); 203 } 204 205 // Import the profile. 206 const CreditCard* imported_credit_card; 207 personal_data_.ImportFormData(form_structure, &imported_credit_card); 208 EXPECT_EQ(static_cast<const CreditCard*>(NULL), imported_credit_card); 209 210 // Clear the |form| to start a new profile. 211 form.fields.clear(); 212 } 213 } 214 215 *merged_profiles = SerializeProfiles(personal_data_.web_profiles()); 216} 217 218TEST_F(AutofillMergeTest, DataDrivenMergeProfiles) { 219 RunDataDrivenTest(GetInputDirectory(kTestName), GetOutputDirectory(kTestName), 220 kFileNamePattern); 221} 222 223} // namespace autofill 224