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