Home | History | Annotate | Download | only in browser
      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 
     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 
    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 
    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