| Index: base/win/pe_image_unittest.cc
|
| diff --git a/base/win/pe_image_unittest.cc b/base/win/pe_image_unittest.cc
|
| index af4209be18a89c9d845031f56e810a0d2a2fea40..4ced22b7f11aa034179c6747677bc8abc0323301 100644
|
| --- a/base/win/pe_image_unittest.cc
|
| +++ b/base/win/pe_image_unittest.cc
|
| @@ -3,6 +3,8 @@
|
| // found in the LICENSE file.
|
|
|
| // This file contains unit tests for PEImage.
|
| +#include <algorithm>
|
| +#include <vector>
|
|
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "base/win/pe_image.h"
|
| @@ -11,6 +13,139 @@
|
| namespace base {
|
| namespace win {
|
|
|
| +namespace {
|
| +
|
| +class Expectations {
|
| + public:
|
| + enum Value {
|
| + sections = 0,
|
| + imports_dlls,
|
| + delay_dlls,
|
| + exports,
|
| + imports,
|
| + delay_imports,
|
| + relocs
|
| + };
|
| +
|
| + enum Arch {
|
| + ARCH_X86 = 0,
|
| + ARCH_X64,
|
| + ARCH_X86_ON_X64,
|
| + ARCH_X64_ON_X64,
|
| + ARCH_X86_ON_X86,
|
| + ARCH_ALL
|
| + };
|
| +
|
| + int GetExpectation(Value value);
|
| + void SetOverride(Value value, Version version, Arch arch, int count);
|
| + void SetOverride(Value value, Version version, int count);
|
| + void SetOverride(Value value, Arch arch, int count);
|
| +
|
| + void SetDefault(Value value, int count) {
|
| + SetOverride(value, VERSION_WIN_LAST, ARCH_ALL, count);
|
| + }
|
| +
|
| + Expectations() {
|
| + my_version_ = GetVersion();
|
| +#if defined(ARCH_CPU_64_BITS)
|
| + my_arch_ = ARCH_X64_ON_X64;
|
| +#else
|
| + OSInfo* os_info = OSInfo::GetInstance();
|
| + if (os_info->wow64_status() == OSInfo::WOW64_DISABLED)
|
| + my_arch_ = ARCH_X86_ON_X86;
|
| + else
|
| + my_arch_ = ARCH_X86_ON_X64;
|
| +#endif
|
| + }
|
| +
|
| + private:
|
| + class Override {
|
| + public:
|
| + enum MatchType { MATCH_VERSION, MATCH_ARCH, MATCH_BOTH, MATCH_NONE };
|
| + explicit Override(Value value, Version version, Arch arch, int count)
|
| + : value_(value), version_(version), arch_(arch), count_(count){};
|
| +
|
| + bool Matches(Value value, Version version, Arch arch, MatchType type) {
|
| + if (value_ != value)
|
| + return false;
|
| + switch (type) {
|
| + case MATCH_BOTH:
|
| + return MatchesVersion(version) && MatchesArch(arch);
|
| + break;
|
| + case MATCH_ARCH:
|
| + return MatchesArch(arch);
|
| + break;
|
| + case MATCH_VERSION:
|
| + return MatchesVersion(version);
|
| + break;
|
| + case MATCH_NONE:
|
| + return true;
|
| + break;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + int GetCount() { return count_; }
|
| +
|
| + private:
|
| + bool MatchesArch(Arch arch) {
|
| + switch (arch) {
|
| + case ARCH_X64_ON_X64:
|
| + return (arch_ == ARCH_X64_ON_X64 || arch_ == ARCH_X64);
|
| + break;
|
| + case ARCH_X86_ON_X86:
|
| + return (arch_ == ARCH_X86_ON_X86 || arch_ == ARCH_X86);
|
| + break;
|
| + case ARCH_X86_ON_X64:
|
| + return (arch_ == ARCH_X86_ON_X64 || arch_ == ARCH_X86);
|
| + break;
|
| + default:
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + bool MatchesVersion(Version version) { return (version == version_); }
|
| +
|
| + Value value_;
|
| + Version version_;
|
| + Arch arch_;
|
| + int count_;
|
| + };
|
| +
|
| + bool MatchesMyArch(Arch arch);
|
| +
|
| + std::vector<Override> overrides_;
|
| + Arch my_arch_;
|
| + Version my_version_;
|
| +};
|
| +
|
| +int Expectations::GetExpectation(Value value) {
|
| + // Prefer OS version specificity over Arch specificity.
|
| + for (auto type : {Expectations::Override::MATCH_BOTH,
|
| + Expectations::Override::MATCH_VERSION,
|
| + Expectations::Override::MATCH_ARCH,
|
| + Expectations::Override::MATCH_NONE})
|
| + for (auto or : overrides_)
|
| + if (or.Matches(value, my_version_, my_arch_, type))
|
| + return or.GetCount();
|
| + return 0;
|
| +}
|
| +
|
| +void Expectations::SetOverride(Value value,
|
| + Version version,
|
| + Arch arch,
|
| + int count) {
|
| + overrides_.push_back(Override(value, version, arch, count));
|
| +}
|
| +
|
| +void Expectations::SetOverride(Value value, Version version, int count) {
|
| + SetOverride(value, version, ARCH_ALL, count);
|
| +}
|
| +
|
| +void Expectations::SetOverride(Value value, Arch arch, int count) {
|
| + SetOverride(value, VERSION_WIN_LAST, arch, count);
|
| +}
|
| +
|
| // Just counts the number of invocations.
|
| bool ExportsCallback(const PEImage &image,
|
| DWORD ordinal,
|
| @@ -83,167 +218,63 @@ bool DelayImportChunksCallback(const PEImage &image,
|
| return true;
|
| }
|
|
|
| -// Identifiers for the set of supported expectations.
|
| -enum ExpectationSet {
|
| - WIN_2K_SET,
|
| - WIN_XP_SET,
|
| - WIN_VISTA_SET,
|
| - WIN_7_SET,
|
| - WIN_8_SET,
|
| - UNSUPPORTED_SET,
|
| -};
|
| -
|
| -// We'll be using some known values for the tests.
|
| -enum Value {
|
| - sections = 0,
|
| - imports_dlls,
|
| - delay_dlls,
|
| - exports,
|
| - imports,
|
| - delay_imports,
|
| - relocs
|
| -};
|
| -
|
| -ExpectationSet GetExpectationSet(DWORD os) {
|
| - if (os == 50)
|
| - return WIN_2K_SET;
|
| - if (os == 51)
|
| - return WIN_XP_SET;
|
| - if (os == 60)
|
| - return WIN_VISTA_SET;
|
| - if (os == 61)
|
| - return WIN_7_SET;
|
| - if (os >= 62)
|
| - return WIN_8_SET;
|
| - return UNSUPPORTED_SET;
|
| -}
|
| -
|
| -// Retrieves the expected value from advapi32.dll based on the OS.
|
| -int GetExpectedValue(Value value, DWORD os) {
|
| - const int xp_delay_dlls = 2;
|
| - const int xp_exports = 675;
|
| - const int xp_imports = 422;
|
| - const int xp_delay_imports = 8;
|
| - const int xp_relocs = 9180;
|
| - const int vista_delay_dlls = 4;
|
| - const int vista_exports = 799;
|
| - const int vista_imports = 476;
|
| - const int vista_delay_imports = 24;
|
| - const int vista_relocs = 10188;
|
| - const int w2k_delay_dlls = 0;
|
| - const int w2k_exports = 566;
|
| - const int w2k_imports = 357;
|
| - const int w2k_delay_imports = 0;
|
| - const int w2k_relocs = 7388;
|
| - const int win7_delay_dlls = 7;
|
| - const int win7_exports = 806;
|
| - const int win7_imports = 568;
|
| - const int win7_delay_imports = 71;
|
| - int win7_relocs = 7812;
|
| - int win7_sections = 4;
|
| - const int win8_delay_dlls = 9;
|
| - const int win8_exports = 806;
|
| - const int win8_imports = 568;
|
| - const int win8_delay_imports = 113;
|
| - const int win8_relocs = 9478;
|
| - int win8_sections = 4;
|
| - int win8_import_dlls = 17;
|
| -
|
| - base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
|
| - // 32-bit process on a 32-bit system.
|
| - if (os_info->architecture() == base::win::OSInfo::X86_ARCHITECTURE) {
|
| - win8_sections = 5;
|
| - win8_import_dlls = 19;
|
| -
|
| - // 64-bit process on a 64-bit system.
|
| - } else if (os_info->wow64_status() == base::win::OSInfo::WOW64_DISABLED) {
|
| - win7_sections = 6;
|
| - win7_relocs = 2712;
|
| - }
|
| -
|
| - // Contains the expected value, for each enumerated property (Value), and the
|
| - // OS version: [Value][os_version]
|
| - const int expected[][5] = {
|
| - {4, 4, 4, win7_sections, win8_sections},
|
| - {3, 3, 3, 13, win8_import_dlls},
|
| - {w2k_delay_dlls, xp_delay_dlls, vista_delay_dlls, win7_delay_dlls,
|
| - win8_delay_dlls},
|
| - {w2k_exports, xp_exports, vista_exports, win7_exports, win8_exports},
|
| - {w2k_imports, xp_imports, vista_imports, win7_imports, win8_imports},
|
| - {w2k_delay_imports, xp_delay_imports,
|
| - vista_delay_imports, win7_delay_imports, win8_delay_imports},
|
| - {w2k_relocs, xp_relocs, vista_relocs, win7_relocs, win8_relocs}
|
| - };
|
| - COMPILE_ASSERT(arraysize(expected[0]) == UNSUPPORTED_SET,
|
| - expected_value_set_mismatch);
|
| -
|
| - if (value > relocs)
|
| - return 0;
|
| - ExpectationSet expected_set = GetExpectationSet(os);
|
| - if (expected_set >= arraysize(expected)) {
|
| - // This should never happen. Log a failure if it does.
|
| - EXPECT_NE(UNSUPPORTED_SET, expected_set);
|
| - expected_set = WIN_2K_SET;
|
| - }
|
| -
|
| - return expected[value][expected_set];
|
| -}
|
| -
|
| -
|
| -// TODO(jschuh): crbug.com/167707 Need to fix test on Win64 bots
|
| -#if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
|
| -#define MAYBE_EnumeratesPE DISABLED_EnumeratesPE
|
| -#else
|
| -#define MAYBE_EnumeratesPE EnumeratesPE
|
| -#endif
|
| +} // namespace
|
|
|
| // Tests that we are able to enumerate stuff from a PE file, and that
|
| // the actual number of items found is within the expected range.
|
| -TEST(PEImageTest, MAYBE_EnumeratesPE) {
|
| - HMODULE module = LoadLibrary(L"advapi32.dll");
|
| +TEST(PEImageTest, EnumeratesPE) {
|
| + Expectations expectations;
|
| +
|
| + // Default expectations.
|
| + expectations.SetDefault(Expectations::sections, 5);
|
| + expectations.SetDefault(Expectations::imports_dlls, 1);
|
| + expectations.SetDefault(Expectations::delay_dlls, 1);
|
| + expectations.SetDefault(Expectations::exports, 1);
|
| + expectations.SetDefault(Expectations::imports, 63);
|
| + expectations.SetDefault(Expectations::delay_imports, 2);
|
| + expectations.SetDefault(Expectations::relocs, 1584);
|
| +
|
| + // win_chromium_x64_rel_ng (Win7 x64 on x64)
|
| + expectations.SetOverride(Expectations::sections, VERSION_WIN7,
|
| + Expectations::ARCH_X64, 6);
|
| + expectations.SetOverride(Expectations::imports, VERSION_WIN7,
|
| + Expectations::ARCH_X64, 66);
|
| + expectations.SetOverride(Expectations::relocs, VERSION_WIN7,
|
| + Expectations::ARCH_X64, 630);
|
| +
|
| + HMODULE module = LoadLibrary(L"pe_image_test.dll");
|
| ASSERT_TRUE(NULL != module);
|
|
|
| PEImage pe(module);
|
| int count = 0;
|
| EXPECT_TRUE(pe.VerifyMagic());
|
|
|
| - DWORD os = pe.GetNTHeaders()->OptionalHeader.MajorOperatingSystemVersion;
|
| - os = os * 10 + pe.GetNTHeaders()->OptionalHeader.MinorOperatingSystemVersion;
|
| -
|
| - // Skip this test for unsupported OS versions.
|
| - if (GetExpectationSet(os) == UNSUPPORTED_SET)
|
| - return;
|
| -
|
| pe.EnumSections(SectionsCallback, &count);
|
| - EXPECT_EQ(GetExpectedValue(sections, os), count);
|
| + EXPECT_EQ(expectations.GetExpectation(Expectations::sections), count);
|
|
|
| count = 0;
|
| pe.EnumImportChunks(ImportChunksCallback, &count);
|
| - EXPECT_EQ(GetExpectedValue(imports_dlls, os), count);
|
| + EXPECT_EQ(expectations.GetExpectation(Expectations::imports_dlls), count);
|
|
|
| count = 0;
|
| pe.EnumDelayImportChunks(DelayImportChunksCallback, &count);
|
| - EXPECT_EQ(GetExpectedValue(delay_dlls, os), count);
|
| + EXPECT_EQ(expectations.GetExpectation(Expectations::delay_dlls), count);
|
|
|
| count = 0;
|
| pe.EnumExports(ExportsCallback, &count);
|
| - EXPECT_GT(count, GetExpectedValue(exports, os) - 20);
|
| - EXPECT_LT(count, GetExpectedValue(exports, os) + 100);
|
| + EXPECT_EQ(expectations.GetExpectation(Expectations::exports), count);
|
|
|
| count = 0;
|
| pe.EnumAllImports(ImportsCallback, &count);
|
| - EXPECT_GT(count, GetExpectedValue(imports, os) - 20);
|
| - EXPECT_LT(count, GetExpectedValue(imports, os) + 100);
|
| + EXPECT_EQ(expectations.GetExpectation(Expectations::imports), count);
|
|
|
| count = 0;
|
| pe.EnumAllDelayImports(ImportsCallback, &count);
|
| - EXPECT_GT(count, GetExpectedValue(delay_imports, os) - 2);
|
| - EXPECT_LT(count, GetExpectedValue(delay_imports, os) + 8);
|
| + EXPECT_EQ(expectations.GetExpectation(Expectations::delay_imports), count);
|
|
|
| count = 0;
|
| pe.EnumRelocs(RelocsCallback, &count);
|
| - EXPECT_GT(count, GetExpectedValue(relocs, os) - 150);
|
| - EXPECT_LT(count, GetExpectedValue(relocs, os) + 1500);
|
| + EXPECT_EQ(expectations.GetExpectation(Expectations::relocs), count);
|
|
|
| FreeLibrary(module);
|
| }
|
|
|