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