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_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "components/autofill/core/browser/autofill_test_utils.h"
15 #include "components/autofill/core/browser/autofill_type.h"
16 #include "components/autofill/core/browser/data_driven_test.h"
17 #include "components/autofill/core/browser/form_structure.h"
18 #include "components/autofill/core/browser/personal_data_manager.h"
19 #include "components/autofill/core/common/form_data.h"
20 #include "testing/gtest/include/gtest/gtest.h"
27 const base::FilePath::CharType kTestName
[] = FILE_PATH_LITERAL("merge");
28 const base::FilePath::CharType kFileNamePattern
[] = FILE_PATH_LITERAL("*.in");
30 const char kFieldSeparator
[] = ": ";
31 const char kProfileSeparator
[] = "---";
32 const size_t kFieldOffset
= arraysize(kFieldSeparator
) - 1;
34 const ServerFieldType kProfileFieldTypes
[] = {
46 PHONE_HOME_WHOLE_NUMBER
49 const base::FilePath
& GetTestDataDir() {
50 CR_DEFINE_STATIC_LOCAL(base::FilePath
, dir
, ());
52 PathService::Get(base::DIR_SOURCE_ROOT
, &dir
);
53 dir
= dir
.AppendASCII("components");
54 dir
= dir
.AppendASCII("test");
55 dir
= dir
.AppendASCII("data");
60 // Serializes the |profiles| into a string.
61 std::string
SerializeProfiles(const std::vector
<AutofillProfile
*>& profiles
) {
63 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
64 result
+= kProfileSeparator
;
66 for (size_t j
= 0; j
< arraysize(kProfileFieldTypes
); ++j
) {
67 ServerFieldType type
= kProfileFieldTypes
[j
];
68 base::string16 value
= profiles
[i
]->GetRawInfo(type
);
69 result
+= AutofillType(type
).ToString();
70 result
+= kFieldSeparator
;
71 result
+= base::UTF16ToUTF8(value
);
79 class PersonalDataManagerMock
: public PersonalDataManager
{
81 PersonalDataManagerMock();
82 ~PersonalDataManagerMock() override
;
84 // Reset the saved profiles.
87 // PersonalDataManager:
88 std::string
SaveImportedProfile(const AutofillProfile
& profile
) override
;
89 const std::vector
<AutofillProfile
*>& web_profiles() const override
;
92 ScopedVector
<AutofillProfile
> profiles_
;
94 DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerMock
);
97 PersonalDataManagerMock::PersonalDataManagerMock()
98 : PersonalDataManager("en-US") {
101 PersonalDataManagerMock::~PersonalDataManagerMock() {
104 void PersonalDataManagerMock::Reset() {
108 std::string
PersonalDataManagerMock::SaveImportedProfile(
109 const AutofillProfile
& profile
) {
110 std::vector
<AutofillProfile
> profiles
;
111 std::string merged_guid
=
112 MergeProfile(profile
, profiles_
.get(), "en-US", &profiles
);
113 if (merged_guid
== profile
.guid())
114 profiles_
.push_back(new AutofillProfile(profile
));
118 const std::vector
<AutofillProfile
*>& PersonalDataManagerMock::web_profiles()
120 return profiles_
.get();
125 // A data-driven test for verifying merging of Autofill profiles. Each input is
126 // a structured dump of a set of implicitly detected autofill profiles. The
127 // corresponding output file is a dump of the saved profiles that result from
128 // importing the input profiles. The output file format is identical to the
130 class AutofillMergeTest
: public testing::Test
,
131 public DataDrivenTest
{
134 ~AutofillMergeTest() override
;
137 void SetUp() override
;
140 void GenerateResults(const std::string
& input
, std::string
* output
) override
;
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
);
146 // Deserializes |str| into a field type.
147 ServerFieldType
StringToFieldType(const std::string
& str
);
149 PersonalDataManagerMock personal_data_
;
152 std::map
<std::string
, ServerFieldType
> string_to_field_type_map_
;
154 DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest
);
157 AutofillMergeTest::AutofillMergeTest() : DataDrivenTest(GetTestDataDir()) {
158 for (size_t i
= NO_SERVER_DATA
; i
< MAX_VALID_FIELD_TYPE
; ++i
) {
159 ServerFieldType field_type
= static_cast<ServerFieldType
>(i
);
160 string_to_field_type_map_
[AutofillType(field_type
).ToString()] = field_type
;
164 AutofillMergeTest::~AutofillMergeTest() {
167 void AutofillMergeTest::SetUp() {
168 test::DisableSystemServices(NULL
);
171 void AutofillMergeTest::GenerateResults(const std::string
& input
,
172 std::string
* output
) {
173 MergeProfiles(input
, output
);
176 void AutofillMergeTest::MergeProfiles(const std::string
& profiles
,
177 std::string
* merged_profiles
) {
178 // Start with no saved profiles.
179 personal_data_
.Reset();
181 // Create a test form.
183 form
.name
= base::ASCIIToUTF16("MyTestForm");
184 form
.origin
= GURL("https://www.example.com/origin.html");
185 form
.action
= GURL("https://www.example.com/action.html");
187 // Parse the input line by line.
188 std::vector
<std::string
> lines
= base::SplitString(
189 profiles
, "\n", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
190 for (size_t i
= 0; i
< lines
.size(); ++i
) {
191 std::string line
= lines
[i
];
193 if (line
!= kProfileSeparator
) {
194 // Add a field to the current profile.
195 size_t separator_pos
= line
.find(kFieldSeparator
);
196 ASSERT_NE(std::string::npos
, separator_pos
);
197 base::string16 field_type
=
198 base::UTF8ToUTF16(line
.substr(0, separator_pos
));
199 base::string16 value
=
200 base::UTF8ToUTF16(line
.substr(separator_pos
+ kFieldOffset
));
203 field
.label
= field_type
;
204 field
.name
= field_type
;
206 field
.form_control_type
= "text";
207 form
.fields
.push_back(field
);
210 // The first line is always a profile separator, and the last profile is not
211 // followed by an explicit separator.
212 if ((i
> 0 && line
== kProfileSeparator
) || i
== lines
.size() - 1) {
213 // Reached the end of a profile. Try to import it.
214 FormStructure
form_structure(form
);
215 for (size_t i
= 0; i
< form_structure
.field_count(); ++i
) {
216 // Set the heuristic type for each field, which is currently serialized
217 // into the field's name.
218 AutofillField
* field
=
219 const_cast<AutofillField
*>(form_structure
.field(i
));
220 ServerFieldType type
=
221 StringToFieldType(base::UTF16ToUTF8(field
->name
));
222 field
->set_heuristic_type(type
);
225 // Import the profile.
226 scoped_ptr
<CreditCard
> imported_credit_card
;
227 personal_data_
.ImportFormData(form_structure
, &imported_credit_card
);
228 EXPECT_FALSE(imported_credit_card
);
230 // Clear the |form| to start a new profile.
235 *merged_profiles
= SerializeProfiles(personal_data_
.web_profiles());
238 ServerFieldType
AutofillMergeTest::StringToFieldType(const std::string
& str
) {
239 return string_to_field_type_map_
[str
];
242 TEST_F(AutofillMergeTest
, DataDrivenMergeProfiles
) {
243 RunDataDrivenTest(GetInputDirectory(kTestName
), GetOutputDirectory(kTestName
),
247 } // namespace autofill