1 // Copyright (c) 2011 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.
5 #include "base/strings/string_number_conversions.h"
6 #include "base/strings/string_util.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/enumerate_modules_model_win.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 typedef testing::Test EnumerateModulesTest
;
13 // Set up some constants to use as default when creating the structs.
14 static const ModuleEnumerator::ModuleType kType
=
15 ModuleEnumerator::LOADED_MODULE
;
17 static const ModuleEnumerator::ModuleStatus kStatus
=
18 ModuleEnumerator::NOT_MATCHED
;
20 static const ModuleEnumerator::RecommendedAction kAction
=
21 ModuleEnumerator::NONE
;
23 static const ModuleEnumerator::OperatingSystem kOs
=
24 ModuleEnumerator::ALL
;
26 // This is a list of test cases to normalize.
27 static const struct NormalizationEntryList
{
28 ModuleEnumerator::Module test_case
;
29 ModuleEnumerator::Module expected
;
30 } kNormalizationTestCases
[] = {
32 // Only path normalization needed.
33 {kType
, kStatus
, L
"c:\\foo\\bar.dll", L
"", L
"Prod", L
"Desc", L
"1.0",
35 {kType
, kStatus
, L
"c:\\foo\\", L
"bar.dll", L
"Prod", L
"Desc", L
"1.0",
38 // Lower case normalization.
39 {kType
, kStatus
, L
"C:\\Foo\\Bar.dll", L
"", L
"", L
"", L
"1.0",
41 {kType
, kStatus
, L
"c:\\foo\\", L
"bar.dll", L
"", L
"", L
"1.0",
44 // Version can include strings after the version number. Strip that away.
45 {kType
, kStatus
, L
"c:\\foo.dll", L
"", L
"", L
"", L
"1.0 asdf",
47 {kType
, kStatus
, L
"c:\\", L
"foo.dll", L
"", L
"", L
"1.0",
50 // Corner case: No path (not sure this will ever happen).
51 {kType
, kStatus
, L
"bar.dll", L
"", L
"", L
"", L
"", L
"", kAction
},
52 {kType
, kStatus
, L
"", L
"bar.dll", L
"", L
"", L
"", L
"", kAction
},
54 // Error case: Missing filename (not sure this will ever happen).
55 {kType
, kStatus
, L
"", L
"", L
"", L
"", L
"1.0", L
"", kAction
},
56 {kType
, kStatus
, L
"", L
"", L
"", L
"", L
"1.0", L
"", kAction
},
60 TEST_F(EnumerateModulesTest
, NormalizeEntry
) {
61 for (size_t i
= 0; i
< arraysize(kNormalizationTestCases
); ++i
) {
62 ModuleEnumerator::Module test
= kNormalizationTestCases
[i
].test_case
;
63 EXPECT_FALSE(test
.normalized
);
64 ModuleEnumerator::NormalizeModule(&test
);
65 ModuleEnumerator::Module expected
= kNormalizationTestCases
[i
].expected
;
67 SCOPED_TRACE("Test case no: " + base::IntToString(i
));
68 EXPECT_EQ(expected
.type
, test
.type
);
69 EXPECT_EQ(expected
.status
, test
.status
);
70 EXPECT_STREQ(expected
.location
.c_str(), test
.location
.c_str());
71 EXPECT_STREQ(expected
.name
.c_str(), test
.name
.c_str());
72 EXPECT_STREQ(expected
.product_name
.c_str(), test
.product_name
.c_str());
73 EXPECT_STREQ(expected
.description
.c_str(), test
.description
.c_str());
74 EXPECT_STREQ(expected
.version
.c_str(), test
.version
.c_str());
75 EXPECT_STREQ(expected
.digital_signer
.c_str(), test
.digital_signer
.c_str());
76 EXPECT_EQ(expected
.recommended_action
, test
.recommended_action
);
77 EXPECT_TRUE(test
.normalized
);
81 const ModuleEnumerator::Module kStandardModule
=
82 { kType
, kStatus
, L
"c:\\foo\\bar.dll", L
"", L
"Prod", L
"Desc", L
"1.0", L
"Sig",
83 ModuleEnumerator::NONE
};
84 const ModuleEnumerator::Module kStandardModuleNoDescription
=
85 { kType
, kStatus
, L
"c:\\foo\\bar.dll", L
"", L
"Prod", L
"", L
"1.0", L
"Sig",
86 ModuleEnumerator::NONE
};
87 const ModuleEnumerator::Module kStandardModuleNoSignature
=
88 { kType
, kStatus
, L
"c:\\foo\\bar.dll", L
"", L
"Prod", L
"Desc", L
"1.0", L
"",
89 ModuleEnumerator::NONE
};
91 // Name, location, description and signature are compared by hashing.
92 static const char kMatchName
[] = "88e8c9e0"; // "bar.dll".
93 static const char kNoMatchName
[] = "barfoo.dll";
94 static const char kMatchLocation
[] = "e6ca7b1c"; // "c:\\foo\\".
95 static const char kNoMatchLocation
[] = "c:\\foobar\\";
96 static const char kMatchDesc
[] = "5c4419a6"; // "Desc".
97 static const char kNoMatchDesc
[] = "NoDesc";
98 static const char kVersionHigh
[] = "2.0";
99 static const char kVersionLow
[] = "0.5";
100 static const char kMatchSignature
[] = "7bfd87e1"; // "Sig".
101 static const char kNoMatchSignature
[] = "giS";
102 static const char kEmpty
[] = "";
104 const struct MatchingEntryList
{
105 ModuleEnumerator::ModuleStatus expected_result
;
106 ModuleEnumerator::Module test_case
;
107 ModuleEnumerator::BlacklistEntry blacklist
;
108 } kMatchineEntryList
[] = {
109 // Each BlacklistEntry is:
110 // Filename, location, desc_or_signer, version from, version to, help_tip.
112 { // Matches: Name (location doesn't match) => Not enough for a match.
113 ModuleEnumerator::NOT_MATCHED
,
115 { kMatchName
, kNoMatchLocation
, kEmpty
, kEmpty
, kEmpty
, kOs
,
116 ModuleEnumerator::SEE_LINK
}
117 }, { // Matches: Name (location not given) => Suspected match.
118 ModuleEnumerator::SUSPECTED_BAD
,
120 { kMatchName
, kEmpty
, kEmpty
, kEmpty
, kEmpty
, kOs
,
121 ModuleEnumerator::SEE_LINK
}
122 }, { // Matches: Name, not version (location not given) => Not a match.
123 ModuleEnumerator::NOT_MATCHED
,
125 { kMatchName
, kEmpty
, kEmpty
, kVersionHigh
, kVersionHigh
, kOs
,
126 ModuleEnumerator::SEE_LINK
}
127 }, { // Matches: Name, location => Suspected match.
128 ModuleEnumerator::SUSPECTED_BAD
,
130 { kMatchName
, kMatchLocation
, kEmpty
, kEmpty
, kEmpty
, kOs
,
131 ModuleEnumerator::SEE_LINK
}
132 }, { // Matches: Name, location, (description not given) => Confirmed match.
133 ModuleEnumerator::CONFIRMED_BAD
,
134 kStandardModuleNoDescription
, // Note: No description.
135 { kMatchName
, kMatchLocation
, kEmpty
, kEmpty
, kEmpty
, kOs
,
136 ModuleEnumerator::SEE_LINK
}
137 }, { // Matches: Name, location, (signature not given) => Confirmed match.
138 ModuleEnumerator::CONFIRMED_BAD
,
139 kStandardModuleNoSignature
, // Note: No signature.
140 { kMatchName
, kMatchLocation
, kEmpty
, kEmpty
, kEmpty
, kOs
,
141 ModuleEnumerator::SEE_LINK
}
142 }, { // Matches: Name, location (not version) => Not a match.
143 ModuleEnumerator::NOT_MATCHED
,
145 { kMatchName
, kMatchLocation
, kEmpty
, kVersionHigh
, kVersionLow
, kOs
,
146 ModuleEnumerator::SEE_LINK
}
147 }, { // Matches: Name, location, signature => Confirmed match.
148 ModuleEnumerator::CONFIRMED_BAD
,
150 { kMatchName
, kMatchLocation
, kMatchSignature
, kEmpty
, kEmpty
, kOs
,
151 ModuleEnumerator::SEE_LINK
}
152 }, { // Matches: Name, location, signature (not version) => No match.
153 ModuleEnumerator::NOT_MATCHED
,
155 { kMatchName
, kMatchLocation
, kMatchSignature
,
156 kVersionLow
, kVersionLow
, kOs
, ModuleEnumerator::SEE_LINK
}
157 }, { // Matches: Name, location, description => Confirmed match.
158 ModuleEnumerator::CONFIRMED_BAD
,
160 { kMatchName
, kMatchLocation
, kMatchDesc
, kEmpty
, kEmpty
, kOs
,
161 ModuleEnumerator::SEE_LINK
}
162 }, { // Matches: Name, location, description (not version) => No match.
163 ModuleEnumerator::NOT_MATCHED
,
165 { kMatchName
, kMatchLocation
, kMatchDesc
,
166 kVersionHigh
, kVersionHigh
, kOs
, ModuleEnumerator::SEE_LINK
}
167 }, { // Matches: Name, location, signature, version => Confirmed match.
168 ModuleEnumerator::CONFIRMED_BAD
,
170 { kMatchName
, kMatchLocation
, kMatchSignature
,
171 kVersionLow
, kVersionHigh
, kOs
, ModuleEnumerator::SEE_LINK
}
172 }, { // Matches: Name, location, signature, version (lower) => Confirmed.
173 ModuleEnumerator::CONFIRMED_BAD
,
175 { kMatchName
, kMatchLocation
, kMatchSignature
,
176 kVersionLow
, kEmpty
, kOs
, ModuleEnumerator::SEE_LINK
}
177 }, { // Matches: Name, location, signature, version (upper) => Confirmed.
178 ModuleEnumerator::CONFIRMED_BAD
,
180 { kMatchName
, kMatchLocation
, kMatchSignature
,
181 kEmpty
, kVersionHigh
, kOs
, ModuleEnumerator::SEE_LINK
}
182 }, { // Matches: Name, Location, Version lower is inclusive => Confirmed.
183 ModuleEnumerator::CONFIRMED_BAD
,
185 { kMatchName
, kMatchLocation
, kMatchSignature
,
186 "1.0", "2.0", kOs
, ModuleEnumerator::SEE_LINK
}
187 }, { // Matches: Name, Location, Version higher is exclusive => No match.
188 ModuleEnumerator::NOT_MATCHED
,
190 { kMatchName
, kMatchLocation
, kEmpty
,
191 "0.0", "1.0", kOs
, ModuleEnumerator::SEE_LINK
}
192 }, { // All empty fields doesn't produce a match.
193 ModuleEnumerator::NOT_MATCHED
,
194 { kType
, kStatus
, L
"", L
"", L
"", L
"", L
""},
195 { "a.dll", "", "", "", "", kOs
, ModuleEnumerator::SEE_LINK
}
199 TEST_F(EnumerateModulesTest
, MatchFunction
) {
200 for (size_t i
= 0; i
< arraysize(kMatchineEntryList
); ++i
) {
201 ModuleEnumerator::Module test
= kMatchineEntryList
[i
].test_case
;
202 ModuleEnumerator::NormalizeModule(&test
);
203 ModuleEnumerator::BlacklistEntry blacklist
=
204 kMatchineEntryList
[i
].blacklist
;
206 SCOPED_TRACE("Test case no " + base::IntToString(i
) +
207 ": '" + UTF16ToASCII(test
.name
) + "'");
208 EXPECT_EQ(kMatchineEntryList
[i
].expected_result
,
209 ModuleEnumerator::Match(test
, blacklist
));
213 const struct CollapsePathList
{
214 base::string16 expected_result
;
215 base::string16 test_case
;
216 } kCollapsePathList
[] = {
217 // Negative testing (should not collapse this path).
218 { base::ASCIIToUTF16("c:\\a\\a.dll"), base::ASCIIToUTF16("c:\\a\\a.dll") },
219 // These two are to test that we select the maximum collapsed path.
220 { base::ASCIIToUTF16("%foo%\\a.dll"), base::ASCIIToUTF16("c:\\foo\\a.dll") },
221 { base::ASCIIToUTF16("%x%\\a.dll"),
222 base::ASCIIToUTF16("c:\\foo\\bar\\a.dll") },
225 TEST_F(EnumerateModulesTest
, CollapsePath
) {
226 scoped_refptr
<ModuleEnumerator
> module_enumerator(new ModuleEnumerator(NULL
));
227 module_enumerator
->path_mapping_
.clear();
228 module_enumerator
->path_mapping_
.push_back(
229 std::make_pair(L
"c:\\foo\\", L
"%foo%"));
230 module_enumerator
->path_mapping_
.push_back(
231 std::make_pair(L
"c:\\foo\\bar\\", L
"%x%"));
233 for (size_t i
= 0; i
< arraysize(kCollapsePathList
); ++i
) {
234 ModuleEnumerator::Module module
;
235 module
.location
= kCollapsePathList
[i
].test_case
;
236 module_enumerator
->CollapsePath(&module
);
238 SCOPED_TRACE("Test case no " + base::IntToString(i
) +
239 ": '" + UTF16ToASCII(kCollapsePathList
[i
].expected_result
) +
241 EXPECT_EQ(kCollapsePathList
[i
].expected_result
, module
.location
);