• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
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"
10 
11 typedef testing::Test EnumerateModulesTest;
12 
13 // Set up some constants to use as default when creating the structs.
14 static const ModuleEnumerator::ModuleType kType =
15     ModuleEnumerator::LOADED_MODULE;
16 
17 static const ModuleEnumerator::ModuleStatus kStatus =
18     ModuleEnumerator::NOT_MATCHED;
19 
20 static const ModuleEnumerator::RecommendedAction kAction =
21     ModuleEnumerator::NONE;
22 
23 static const ModuleEnumerator::OperatingSystem kOs =
24     ModuleEnumerator::ALL;
25 
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[] = {
31   {
32     // Only path normalization needed.
33     {kType, kStatus, L"c:\\foo\\bar.dll", L"",        L"Prod", L"Desc", L"1.0",
34          L"Sig", kAction},
35     {kType, kStatus, L"c:\\foo\\",        L"bar.dll", L"Prod", L"Desc", L"1.0",
36          L"Sig", kAction},
37   }, {
38     // Lower case normalization.
39     {kType, kStatus, L"C:\\Foo\\Bar.dll", L"",        L"", L"", L"1.0",
40          L"", kAction},
41     {kType, kStatus, L"c:\\foo\\",        L"bar.dll", L"", L"", L"1.0",
42          L"", kAction},
43   }, {
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",
46          L"", kAction},
47     {kType, kStatus, L"c:\\",        L"foo.dll", L"", L"", L"1.0",
48          L"", kAction},
49   }, {
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},
53   }, {
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},
57   },
58 };
59 
TEST_F(EnumerateModulesTest,NormalizeEntry)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;
66 
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);
78   }
79 }
80 
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 };
90 
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[] = "";
103 
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.
111 
112   {  // Matches: Name (location doesn't match) => Not enough for a match.
113     ModuleEnumerator::NOT_MATCHED,
114     kStandardModule,
115     { kMatchName, kNoMatchLocation, kEmpty, kEmpty, kEmpty, kOs,
116       ModuleEnumerator::SEE_LINK }
117   }, {  // Matches: Name (location not given) => Suspected match.
118     ModuleEnumerator::SUSPECTED_BAD,
119     kStandardModule,
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,
124     kStandardModule,
125     { kMatchName, kEmpty, kEmpty, kVersionHigh, kVersionHigh, kOs,
126       ModuleEnumerator::SEE_LINK }
127   }, {  // Matches: Name, location => Suspected match.
128     ModuleEnumerator::SUSPECTED_BAD,
129     kStandardModule,
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,
144     kStandardModule,
145     { kMatchName, kMatchLocation, kEmpty, kVersionHigh, kVersionLow, kOs,
146       ModuleEnumerator::SEE_LINK }
147   }, {  // Matches: Name, location, signature => Confirmed match.
148     ModuleEnumerator::CONFIRMED_BAD,
149     kStandardModule,
150     { kMatchName, kMatchLocation, kMatchSignature, kEmpty, kEmpty, kOs,
151       ModuleEnumerator::SEE_LINK }
152   }, {  // Matches: Name, location, signature (not version) => No match.
153     ModuleEnumerator::NOT_MATCHED,
154     kStandardModule,
155     { kMatchName, kMatchLocation, kMatchSignature,
156       kVersionLow, kVersionLow, kOs, ModuleEnumerator::SEE_LINK }
157   }, {  // Matches: Name, location, description => Confirmed match.
158     ModuleEnumerator::CONFIRMED_BAD,
159     kStandardModule,
160     { kMatchName, kMatchLocation, kMatchDesc, kEmpty, kEmpty, kOs,
161       ModuleEnumerator::SEE_LINK }
162   }, {  // Matches: Name, location, description (not version) => No match.
163     ModuleEnumerator::NOT_MATCHED,
164     kStandardModule,
165     { kMatchName, kMatchLocation, kMatchDesc,
166       kVersionHigh, kVersionHigh, kOs, ModuleEnumerator::SEE_LINK }
167   }, {  // Matches: Name, location, signature, version => Confirmed match.
168     ModuleEnumerator::CONFIRMED_BAD,
169     kStandardModule,
170     { kMatchName, kMatchLocation, kMatchSignature,
171       kVersionLow, kVersionHigh, kOs, ModuleEnumerator::SEE_LINK }
172   }, {  // Matches: Name, location, signature, version (lower) => Confirmed.
173     ModuleEnumerator::CONFIRMED_BAD,
174     kStandardModule,
175     { kMatchName, kMatchLocation, kMatchSignature,
176       kVersionLow, kEmpty, kOs, ModuleEnumerator::SEE_LINK }
177   }, {  // Matches: Name, location, signature, version (upper) => Confirmed.
178     ModuleEnumerator::CONFIRMED_BAD,
179     kStandardModule,
180     { kMatchName, kMatchLocation, kMatchSignature,
181       kEmpty, kVersionHigh, kOs, ModuleEnumerator::SEE_LINK }
182   }, {  // Matches: Name, Location, Version lower is inclusive => Confirmed.
183     ModuleEnumerator::CONFIRMED_BAD,
184     kStandardModule,
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,
189     kStandardModule,
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 }
196   },
197 };
198 
TEST_F(EnumerateModulesTest,MatchFunction)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;
205 
206     SCOPED_TRACE("Test case no " + base::IntToString(i) +
207                  ": '" + base::UTF16ToASCII(test.name) + "'");
208     EXPECT_EQ(kMatchineEntryList[i].expected_result,
209               ModuleEnumerator::Match(test, blacklist));
210   }
211 }
212 
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") },
223 };
224 
TEST_F(EnumerateModulesTest,CollapsePath)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%"));
232 
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);
237 
238     SCOPED_TRACE("Test case no " + base::IntToString(i) + ": '" +
239                  base::UTF16ToASCII(kCollapsePathList[i].expected_result) +
240                  "'");
241     EXPECT_EQ(kCollapsePathList[i].expected_result, module.location);
242   }
243 }
244