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