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/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