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.
8 #include "base/basictypes.h"
9 #include "base/files/file_path.h"
10 #include "base/path_service.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/autofill/core/browser/autofill_test_utils.h"
14 #include "components/autofill/core/browser/autofill_type.h"
15 #include "components/autofill/core/browser/data_driven_test.h"
16 #include "components/autofill/core/browser/form_structure.h"
17 #include "components/autofill/core/browser/personal_data_manager.h"
18 #include "components/autofill/core/common/form_data.h"
19 #include "testing/gtest/include/gtest/gtest.h"
26 const base::FilePath::CharType kTestName
[] = FILE_PATH_LITERAL("merge");
27 const base::FilePath::CharType kFileNamePattern
[] = FILE_PATH_LITERAL("*.in");
29 const char kFieldSeparator
[] = ": ";
30 const char kProfileSeparator
[] = "---";
31 const size_t kFieldOffset
= arraysize(kFieldSeparator
) - 1;
33 const ServerFieldType kProfileFieldTypes
[] = {
45 PHONE_HOME_WHOLE_NUMBER
48 const base::FilePath
& GetTestDataDir() {
49 CR_DEFINE_STATIC_LOCAL(base::FilePath
, dir
, ());
51 PathService::Get(base::DIR_SOURCE_ROOT
, &dir
);
52 dir
= dir
.AppendASCII("components");
53 dir
= dir
.AppendASCII("test");
54 dir
= dir
.AppendASCII("data");
59 // Serializes the |profiles| into a string.
60 std::string
SerializeProfiles(const std::vector
<AutofillProfile
*>& profiles
) {
62 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
63 result
+= kProfileSeparator
;
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(type
).ToString();
71 result
+= kFieldSeparator
;
72 result
+= base::UTF16ToUTF8(values
[k
]);
81 class PersonalDataManagerMock
: public PersonalDataManager
{
83 PersonalDataManagerMock();
84 virtual ~PersonalDataManagerMock();
86 // Reset the saved profiles.
89 // PersonalDataManager:
90 virtual std::string
SaveImportedProfile(
91 const AutofillProfile
& profile
) OVERRIDE
;
92 virtual const std::vector
<AutofillProfile
*>& web_profiles() const OVERRIDE
;
95 ScopedVector
<AutofillProfile
> profiles_
;
97 DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerMock
);
100 PersonalDataManagerMock::PersonalDataManagerMock()
101 : PersonalDataManager("en-US") {
104 PersonalDataManagerMock::~PersonalDataManagerMock() {
107 void PersonalDataManagerMock::Reset() {
111 std::string
PersonalDataManagerMock::SaveImportedProfile(
112 const AutofillProfile
& profile
) {
113 std::vector
<AutofillProfile
> profiles
;
114 std::string merged_guid
=
115 MergeProfile(profile
, profiles_
.get(), "en-US", &profiles
);
116 if (merged_guid
== profile
.guid())
117 profiles_
.push_back(new AutofillProfile(profile
));
121 const std::vector
<AutofillProfile
*>& PersonalDataManagerMock::web_profiles()
123 return profiles_
.get();
128 // A data-driven test for verifying merging of Autofill profiles. Each input is
129 // a structured dump of a set of implicitly detected autofill profiles. The
130 // corresponding output file is a dump of the saved profiles that result from
131 // importing the input profiles. The output file format is identical to the
133 class AutofillMergeTest
: public testing::Test
,
134 public DataDrivenTest
{
137 virtual ~AutofillMergeTest();
140 virtual void SetUp();
143 virtual void GenerateResults(const std::string
& input
,
144 std::string
* output
) OVERRIDE
;
146 // Deserializes a set of Autofill profiles from |profiles|, imports each
147 // sequentially, and fills |merged_profiles| with the serialized result.
148 void MergeProfiles(const std::string
& profiles
, std::string
* merged_profiles
);
150 // Deserializes |str| into a field type.
151 ServerFieldType
StringToFieldType(const std::string
& str
);
153 PersonalDataManagerMock personal_data_
;
156 std::map
<std::string
, ServerFieldType
> string_to_field_type_map_
;
158 DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest
);
161 AutofillMergeTest::AutofillMergeTest() : DataDrivenTest(GetTestDataDir()) {
162 for (size_t i
= NO_SERVER_DATA
; i
< MAX_VALID_FIELD_TYPE
; ++i
) {
163 ServerFieldType field_type
= static_cast<ServerFieldType
>(i
);
164 string_to_field_type_map_
[AutofillType(field_type
).ToString()] = field_type
;
168 AutofillMergeTest::~AutofillMergeTest() {
171 void AutofillMergeTest::SetUp() {
172 test::DisableSystemServices(NULL
);
175 void AutofillMergeTest::GenerateResults(const std::string
& input
,
176 std::string
* output
) {
177 MergeProfiles(input
, output
);
180 void AutofillMergeTest::MergeProfiles(const std::string
& profiles
,
181 std::string
* merged_profiles
) {
182 // Start with no saved profiles.
183 personal_data_
.Reset();
185 // Create a test form.
187 form
.name
= base::ASCIIToUTF16("MyTestForm");
188 form
.origin
= GURL("https://www.example.com/origin.html");
189 form
.action
= GURL("https://www.example.com/action.html");
190 form
.user_submitted
= true;
192 // Parse the input line by line.
193 std::vector
<std::string
> lines
;
194 Tokenize(profiles
, "\n", &lines
);
195 for (size_t i
= 0; i
< lines
.size(); ++i
) {
196 std::string line
= lines
[i
];
198 if (line
!= kProfileSeparator
) {
199 // Add a field to the current profile.
200 size_t separator_pos
= line
.find(kFieldSeparator
);
201 ASSERT_NE(std::string::npos
, separator_pos
);
202 base::string16 field_type
=
203 base::UTF8ToUTF16(line
.substr(0, separator_pos
));
204 base::string16 value
=
205 base::UTF8ToUTF16(line
.substr(separator_pos
+ kFieldOffset
));
208 field
.label
= field_type
;
209 field
.name
= field_type
;
211 field
.form_control_type
= "text";
212 form
.fields
.push_back(field
);
215 // The first line is always a profile separator, and the last profile is not
216 // followed by an explicit separator.
217 if ((i
> 0 && line
== kProfileSeparator
) || i
== lines
.size() - 1) {
218 // Reached the end of a profile. Try to import it.
219 FormStructure
form_structure(form
);
220 for (size_t i
= 0; i
< form_structure
.field_count(); ++i
) {
221 // Set the heuristic type for each field, which is currently serialized
222 // into the field's name.
223 AutofillField
* field
=
224 const_cast<AutofillField
*>(form_structure
.field(i
));
225 ServerFieldType type
=
226 StringToFieldType(base::UTF16ToUTF8(field
->name
));
227 field
->set_heuristic_type(type
);
230 // Import the profile.
231 scoped_ptr
<CreditCard
> imported_credit_card
;
232 personal_data_
.ImportFormData(form_structure
, &imported_credit_card
);
233 EXPECT_EQ(static_cast<CreditCard
*>(NULL
), imported_credit_card
.get());
235 // Clear the |form| to start a new profile.
240 *merged_profiles
= SerializeProfiles(personal_data_
.web_profiles());
243 ServerFieldType
AutofillMergeTest::StringToFieldType(const std::string
& str
) {
244 return string_to_field_type_map_
[str
];
247 TEST_F(AutofillMergeTest
, DataDrivenMergeProfiles
) {
248 RunDataDrivenTest(GetInputDirectory(kTestName
), GetOutputDirectory(kTestName
),
252 } // namespace autofill