blob: 21918d7c8b1206a079ab92892332903bbf70f4ba [file] [log] [blame]
Ben Murdocheb525c52013-07-10 11:40:50 +01001// 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"
Ben Murdochca12bfa2013-07-23 11:17:05 +01009#include "base/path_service.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010010#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"
Ben Murdocheb525c52013-07-10 11:40:50 +010018#include "testing/gtest/include/gtest/gtest.h"
19#include "third_party/WebKit/public/web/WebInputElement.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010020#include "url/gurl.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010021
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
Ben Murdoch32409262013-08-07 11:04:47 +010033const ServerFieldType kProfileFieldTypes[] = {
Ben Murdocheb525c52013-07-10 11:40:50 +010034 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
Ben Murdochca12bfa2013-07-23 11:17:05 +010048const 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
Ben Murdocheb525c52013-07-10 11:40:50 +010059// 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) {
Ben Murdoch32409262013-08-07 11:04:47 +010066 ServerFieldType type = kProfileFieldTypes[j];
Ben Murdocheb525c52013-07-10 11:40:50 +010067 std::vector<base::string16> values;
68 profiles[i]->GetRawMultiInfo(type, &values);
69 for (size_t k = 0; k < values.size(); ++k) {
Ben Murdochbb1529c2013-08-08 10:24:53 +010070 result += AutofillType(type).ToString();
Ben Murdocheb525c52013-07-10 11:40:50 +010071 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
Ben Murdochca12bfa2013-07-23 11:17:05 +0100152AutofillMergeTest::AutofillMergeTest() : DataDrivenTest(GetTestDataDir()) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100153}
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));
Ben Murdoch32409262013-08-07 11:04:47 +0100212 ServerFieldType type =
Ben Murdocheb525c52013-07-10 11:40:50 +0100213 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