Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: base/win/pe_image_unittest.cc

Issue 946183002: Add base_unittests to win8 trybot. Fix PEImage tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix expectations Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This file contains unit tests for PEImage. 5 // This file contains unit tests for PEImage.
6 #include <algorithm>
7 #include <vector>
6 8
7 #include "testing/gtest/include/gtest/gtest.h" 9 #include "testing/gtest/include/gtest/gtest.h"
8 #include "base/win/pe_image.h" 10 #include "base/win/pe_image.h"
9 #include "base/win/windows_version.h" 11 #include "base/win/windows_version.h"
10 12
11 namespace base { 13 namespace base {
12 namespace win { 14 namespace win {
13 15
14 // Just counts the number of invocations. 16 namespace {
15 bool ExportsCallback(const PEImage &image,
16 DWORD ordinal,
17 DWORD hint,
18 LPCSTR name,
19 PVOID function,
20 LPCSTR forward,
21 PVOID cookie) {
22 int* count = reinterpret_cast<int*>(cookie);
23 (*count)++;
24 return true;
25 }
26 17
27 // Just counts the number of invocations. 18 // Just counts the number of invocations.
28 bool ImportsCallback(const PEImage &image, 19 bool ImportsCallback(const PEImage& image,
29 LPCSTR module, 20 LPCSTR module,
30 DWORD ordinal, 21 DWORD ordinal,
31 LPCSTR name, 22 LPCSTR name,
32 DWORD hint, 23 DWORD hint,
33 PIMAGE_THUNK_DATA iat, 24 PIMAGE_THUNK_DATA iat,
34 PVOID cookie) { 25 PVOID cookie) {
35 int* count = reinterpret_cast<int*>(cookie); 26 int* count = reinterpret_cast<int*>(cookie);
36 (*count)++; 27 (*count)++;
37 return true; 28 return true;
38 } 29 }
39 30
40 // Just counts the number of invocations. 31 // Just counts the number of invocations.
41 bool SectionsCallback(const PEImage &image, 32 bool SectionsCallback(const PEImage& image,
42 PIMAGE_SECTION_HEADER header, 33 PIMAGE_SECTION_HEADER header,
43 PVOID section_start, 34 PVOID section_start,
44 DWORD section_size, 35 DWORD section_size,
45 PVOID cookie) { 36 PVOID cookie) {
46 int* count = reinterpret_cast<int*>(cookie); 37 int* count = reinterpret_cast<int*>(cookie);
47 (*count)++; 38 (*count)++;
48 return true; 39 return true;
49 } 40 }
50 41
51 // Just counts the number of invocations. 42 // Just counts the number of invocations.
52 bool RelocsCallback(const PEImage &image, 43 bool RelocsCallback(const PEImage& image,
53 WORD type, 44 WORD type,
54 PVOID address, 45 PVOID address,
55 PVOID cookie) { 46 PVOID cookie) {
56 int* count = reinterpret_cast<int*>(cookie); 47 int* count = reinterpret_cast<int*>(cookie);
57 (*count)++; 48 (*count)++;
58 return true; 49 return true;
59 } 50 }
60 51
61 // Just counts the number of invocations. 52 // Just counts the number of invocations.
62 bool ImportChunksCallback(const PEImage &image, 53 bool ImportChunksCallback(const PEImage& image,
63 LPCSTR module, 54 LPCSTR module,
64 PIMAGE_THUNK_DATA name_table, 55 PIMAGE_THUNK_DATA name_table,
65 PIMAGE_THUNK_DATA iat, 56 PIMAGE_THUNK_DATA iat,
66 PVOID cookie) { 57 PVOID cookie) {
67 int* count = reinterpret_cast<int*>(cookie); 58 int* count = reinterpret_cast<int*>(cookie);
68 (*count)++; 59 (*count)++;
69 return true; 60 return true;
70 } 61 }
71 62
72 // Just counts the number of invocations. 63 // Just counts the number of invocations.
73 bool DelayImportChunksCallback(const PEImage &image, 64 bool DelayImportChunksCallback(const PEImage& image,
74 PImgDelayDescr delay_descriptor, 65 PImgDelayDescr delay_descriptor,
75 LPCSTR module, 66 LPCSTR module,
76 PIMAGE_THUNK_DATA name_table, 67 PIMAGE_THUNK_DATA name_table,
77 PIMAGE_THUNK_DATA iat, 68 PIMAGE_THUNK_DATA iat,
78 PIMAGE_THUNK_DATA bound_iat, 69 PIMAGE_THUNK_DATA bound_iat,
79 PIMAGE_THUNK_DATA unload_iat, 70 PIMAGE_THUNK_DATA unload_iat,
80 PVOID cookie) { 71 PVOID cookie) {
81 int* count = reinterpret_cast<int*>(cookie); 72 int* count = reinterpret_cast<int*>(cookie);
82 (*count)++; 73 (*count)++;
83 return true; 74 return true;
84 } 75 }
85 76
86 // Identifiers for the set of supported expectations. 77 // Just counts the number of invocations.
87 enum ExpectationSet { 78 bool ExportsCallback(const PEImage& image,
88 WIN_2K_SET, 79 DWORD ordinal,
89 WIN_XP_SET, 80 DWORD hint,
90 WIN_VISTA_SET, 81 LPCSTR name,
91 WIN_7_SET, 82 PVOID function,
92 WIN_8_SET, 83 LPCSTR forward,
93 UNSUPPORTED_SET, 84 PVOID cookie) {
85 int* count = reinterpret_cast<int*>(cookie);
86 (*count)++;
87 return true;
88 }
89 } // namespace
90
91 class Expectations {
92 public:
93 enum Value {
94 SECTIONS = 0,
95 IMPORTS_DLLS,
96 DELAY_DLLS,
97 EXPORTS,
98 IMPORTS,
99 DELAY_IMPORTS,
100 RELOCS
101 };
102
103 // Arch is hierarchical and used when specifying an Expectation.
104 // ARCH_ALL - Matches all architectures.
105 // ARCH_X86 - Matches 32-bit binary.
106 // ARCH_X86_ON_X64 - Matches 32-bit binary on 64-bit OS.
107 // ARCH_X86_ON_X86 - Matches 32-bit binary on 32-bit OS.
rvargas (doing something else) 2015/02/24 20:03:22 This still looks to me like stuff that we'll never
Will Harris 2015/02/24 20:46:54 Done, with :(
108 // ARCH_X64 - Matches 64-bit binary.
109 enum Arch {
110 ARCH_X86 = 0,
111 ARCH_X64,
112 ARCH_X86_ON_X64,
113 ARCH_X86_ON_X86,
114 ARCH_ALL
115 };
116
117 Expectations();
118
119 bool VerifyExpectation(Value value, int count);
120 void SetOverride(Value value, Version version, Arch arch, int count);
121 void SetOverride(Value value, Version version, int count);
122 void SetOverride(Value value, Arch arch, int count);
123 void SetDefault(Value value, int count);
124
125 // returns -1 on failure.
126 int GetExpectation(Value value);
127
128 private:
129 class Override {
130 public:
131 enum MatchType { MATCH_VERSION, MATCH_ARCH, MATCH_BOTH, MATCH_NONE };
132
133 Override(Value value, Version version, Arch arch, int count)
134 : value_(value), version_(version), arch_(arch), count_(count) {
135 };
136
137 bool Matches(Value value, Version version, Arch arch, MatchType type) {
138 if (value_ != value)
139 return false;
140
141 switch (type) {
142 case MATCH_BOTH:
143 return MatchesVersion(version) && MatchesArch(arch);
144 case MATCH_ARCH:
145 return MatchesArch(arch) && version_ == VERSION_WIN_LAST;
146 case MATCH_VERSION:
147 return MatchesVersion(version) && arch_ == ARCH_ALL;
148 case MATCH_NONE:
149 return (arch_ == ARCH_ALL && version_ == VERSION_WIN_LAST);
150 }
151 return false;
152 }
153
154 int GetCount() { return count_; }
155
156 private:
157 bool MatchesArch(Arch arch) {
158 switch (arch) {
159 case ARCH_X64:
160 return (arch_ == ARCH_X64);
161 break;
162 case ARCH_X86_ON_X86:
163 return (arch_ == ARCH_X86_ON_X86 || arch_ == ARCH_X86);
164 break;
165 case ARCH_X86_ON_X64:
166 return (arch_ == ARCH_X86_ON_X64 || arch_ == ARCH_X86);
167 break;
168 default:
169 return false;
170 }
171 }
172
173 bool MatchesVersion(Version version) { return (version == version_); }
174
175 Value value_;
176 Version version_;
177 Arch arch_;
178 int count_;
179 };
180
181 bool MatchesMyArch(Arch arch);
182
183 std::vector<Override> overrides_;
184 Arch my_arch_;
185 Version my_version_;
94 }; 186 };
95 187
96 // We'll be using some known values for the tests. 188 Expectations::Expectations() {
97 enum Value { 189 my_version_ = GetVersion();
98 sections = 0, 190 #if defined(ARCH_CPU_64_BITS)
99 imports_dlls, 191 my_arch_ = ARCH_X64;
100 delay_dlls, 192 #else
101 exports, 193 OSInfo* os_info = OSInfo::GetInstance();
102 imports, 194 if (os_info->wow64_status() == OSInfo::WOW64_DISABLED)
103 delay_imports, 195 my_arch_ = ARCH_X86_ON_X86;
104 relocs 196 else
105 }; 197 my_arch_ = ARCH_X86_ON_X64;
106 198 #endif
107 ExpectationSet GetExpectationSet(DWORD os) { 199 }
108 if (os == 50) 200
109 return WIN_2K_SET; 201 int Expectations::GetExpectation(Value value) {
110 if (os == 51) 202 // Prefer OS version specificity over Arch specificity.
111 return WIN_XP_SET; 203 for (auto type : { Override::MATCH_BOTH,
112 if (os == 60) 204 Override::MATCH_VERSION,
113 return WIN_VISTA_SET; 205 Override::MATCH_ARCH,
114 if (os == 61) 206 Override::MATCH_NONE }) {
115 return WIN_7_SET; 207 for (auto override : overrides_) {
116 if (os >= 62) 208 if (override.Matches(value, my_version_, my_arch_, type))
117 return WIN_8_SET; 209 return override.GetCount();
118 return UNSUPPORTED_SET; 210 }
119 }
120
121 // Retrieves the expected value from advapi32.dll based on the OS.
122 int GetExpectedValue(Value value, DWORD os) {
123 const int xp_delay_dlls = 2;
124 const int xp_exports = 675;
125 const int xp_imports = 422;
126 const int xp_delay_imports = 8;
127 const int xp_relocs = 9180;
128 const int vista_delay_dlls = 4;
129 const int vista_exports = 799;
130 const int vista_imports = 476;
131 const int vista_delay_imports = 24;
132 const int vista_relocs = 10188;
133 const int w2k_delay_dlls = 0;
134 const int w2k_exports = 566;
135 const int w2k_imports = 357;
136 const int w2k_delay_imports = 0;
137 const int w2k_relocs = 7388;
138 const int win7_delay_dlls = 7;
139 const int win7_exports = 806;
140 const int win7_imports = 568;
141 const int win7_delay_imports = 71;
142 int win7_relocs = 7812;
143 int win7_sections = 4;
144 const int win8_delay_dlls = 9;
145 const int win8_exports = 806;
146 const int win8_imports = 568;
147 const int win8_delay_imports = 113;
148 const int win8_relocs = 9478;
149 int win8_sections = 4;
150 int win8_import_dlls = 17;
151
152 base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
153 // 32-bit process on a 32-bit system.
154 if (os_info->architecture() == base::win::OSInfo::X86_ARCHITECTURE) {
155 win8_sections = 5;
156 win8_import_dlls = 19;
157
158 // 64-bit process on a 64-bit system.
159 } else if (os_info->wow64_status() == base::win::OSInfo::WOW64_DISABLED) {
160 win7_sections = 6;
161 win7_relocs = 2712;
162 } 211 }
163 212 return -1;
164 // Contains the expected value, for each enumerated property (Value), and the 213 }
165 // OS version: [Value][os_version] 214
166 const int expected[][5] = { 215 void Expectations::SetDefault(Value value, int count) {
167 {4, 4, 4, win7_sections, win8_sections}, 216 SetOverride(value, VERSION_WIN_LAST, ARCH_ALL, count);
168 {3, 3, 3, 13, win8_import_dlls}, 217 }
169 {w2k_delay_dlls, xp_delay_dlls, vista_delay_dlls, win7_delay_dlls, 218
170 win8_delay_dlls}, 219 void Expectations::SetOverride(Value value,
171 {w2k_exports, xp_exports, vista_exports, win7_exports, win8_exports}, 220 Version version,
172 {w2k_imports, xp_imports, vista_imports, win7_imports, win8_imports}, 221 Arch arch,
173 {w2k_delay_imports, xp_delay_imports, 222 int count) {
174 vista_delay_imports, win7_delay_imports, win8_delay_imports}, 223 overrides_.push_back(Override(value, version, arch, count));
175 {w2k_relocs, xp_relocs, vista_relocs, win7_relocs, win8_relocs} 224 }
176 }; 225
177 COMPILE_ASSERT(arraysize(expected[0]) == UNSUPPORTED_SET, 226 void Expectations::SetOverride(Value value, Version version, int count) {
178 expected_value_set_mismatch); 227 SetOverride(value, version, ARCH_ALL, count);
179 228 }
180 if (value > relocs) 229
181 return 0; 230 void Expectations::SetOverride(Value value, Arch arch, int count) {
182 ExpectationSet expected_set = GetExpectationSet(os); 231 SetOverride(value, VERSION_WIN_LAST, arch, count);
183 if (expected_set >= arraysize(expected)) { 232 }
184 // This should never happen. Log a failure if it does.
185 EXPECT_NE(UNSUPPORTED_SET, expected_set);
186 expected_set = WIN_2K_SET;
187 }
188
189 return expected[value][expected_set];
190 }
191
192
193 // TODO(jschuh): crbug.com/167707 Need to fix test on Win64 bots
194 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
195 #define MAYBE_EnumeratesPE DISABLED_EnumeratesPE
196 #else
197 #define MAYBE_EnumeratesPE EnumeratesPE
198 #endif
199 233
200 // Tests that we are able to enumerate stuff from a PE file, and that 234 // Tests that we are able to enumerate stuff from a PE file, and that
201 // the actual number of items found is within the expected range. 235 // the actual number of items found is within the expected range.
202 TEST(PEImageTest, MAYBE_EnumeratesPE) { 236 TEST(PEImageTest, EnumeratesPE) {
203 HMODULE module = LoadLibrary(L"advapi32.dll"); 237 Expectations expectations;
238
239 #ifndef NDEBUG
240 // Default Debug expectations.
241 expectations.SetDefault(Expectations::SECTIONS, 7);
242 expectations.SetDefault(Expectations::IMPORTS_DLLS, 3);
243 expectations.SetDefault(Expectations::DELAY_DLLS, 2);
244 expectations.SetDefault(Expectations::EXPORTS, 2);
245 expectations.SetDefault(Expectations::IMPORTS, 49);
246 expectations.SetDefault(Expectations::DELAY_IMPORTS, 2);
247 expectations.SetDefault(Expectations::RELOCS, 438);
248
249 // 64-bit Debug expectations.
250 expectations.SetOverride(Expectations::SECTIONS, Expectations::ARCH_X64, 8);
251 expectations.SetOverride(Expectations::IMPORTS, Expectations::ARCH_X64, 69);
252 expectations.SetOverride(Expectations::RELOCS, Expectations::ARCH_X64, 632);
253 #else
254 // Default Release expectations.
255 expectations.SetDefault(Expectations::SECTIONS, 5);
256 expectations.SetDefault(Expectations::IMPORTS_DLLS, 2);
257 expectations.SetDefault(Expectations::DELAY_DLLS, 2);
258 expectations.SetDefault(Expectations::EXPORTS, 2);
259 expectations.SetDefault(Expectations::IMPORTS, 66);
260 expectations.SetDefault(Expectations::DELAY_IMPORTS, 2);
261 expectations.SetDefault(Expectations::RELOCS, 1586);
262
263 // 64-bit Release expectations.
264 expectations.SetOverride(Expectations::SECTIONS, Expectations::ARCH_X64, 6);
265 expectations.SetOverride(Expectations::IMPORTS, Expectations::ARCH_X64, 69);
266 expectations.SetOverride(Expectations::RELOCS, Expectations::ARCH_X64, 632);
267 #endif
268
269 HMODULE module = LoadLibrary(L"pe_image_test.dll");
204 ASSERT_TRUE(NULL != module); 270 ASSERT_TRUE(NULL != module);
205 271
206 PEImage pe(module); 272 PEImage pe(module);
207 int count = 0; 273 int count = 0;
208 EXPECT_TRUE(pe.VerifyMagic()); 274 EXPECT_TRUE(pe.VerifyMagic());
209 275
210 DWORD os = pe.GetNTHeaders()->OptionalHeader.MajorOperatingSystemVersion;
211 os = os * 10 + pe.GetNTHeaders()->OptionalHeader.MinorOperatingSystemVersion;
212
213 // Skip this test for unsupported OS versions.
214 if (GetExpectationSet(os) == UNSUPPORTED_SET)
215 return;
216
217 pe.EnumSections(SectionsCallback, &count); 276 pe.EnumSections(SectionsCallback, &count);
218 EXPECT_EQ(GetExpectedValue(sections, os), count); 277 EXPECT_EQ(expectations.GetExpectation(Expectations::SECTIONS), count);
219 278
220 count = 0; 279 count = 0;
221 pe.EnumImportChunks(ImportChunksCallback, &count); 280 pe.EnumImportChunks(ImportChunksCallback, &count);
222 EXPECT_EQ(GetExpectedValue(imports_dlls, os), count); 281 EXPECT_EQ(expectations.GetExpectation(Expectations::IMPORTS_DLLS), count);
223 282
224 count = 0; 283 count = 0;
225 pe.EnumDelayImportChunks(DelayImportChunksCallback, &count); 284 pe.EnumDelayImportChunks(DelayImportChunksCallback, &count);
226 EXPECT_EQ(GetExpectedValue(delay_dlls, os), count); 285 EXPECT_EQ(expectations.GetExpectation(Expectations::DELAY_DLLS), count);
227 286
228 count = 0; 287 count = 0;
229 pe.EnumExports(ExportsCallback, &count); 288 pe.EnumExports(ExportsCallback, &count);
230 EXPECT_GT(count, GetExpectedValue(exports, os) - 20); 289 EXPECT_EQ(expectations.GetExpectation(Expectations::EXPORTS), count);
231 EXPECT_LT(count, GetExpectedValue(exports, os) + 100);
232 290
233 count = 0; 291 count = 0;
234 pe.EnumAllImports(ImportsCallback, &count); 292 pe.EnumAllImports(ImportsCallback, &count);
235 EXPECT_GT(count, GetExpectedValue(imports, os) - 20); 293 EXPECT_EQ(expectations.GetExpectation(Expectations::IMPORTS), count);
236 EXPECT_LT(count, GetExpectedValue(imports, os) + 100);
237 294
238 count = 0; 295 count = 0;
239 pe.EnumAllDelayImports(ImportsCallback, &count); 296 pe.EnumAllDelayImports(ImportsCallback, &count);
240 EXPECT_GT(count, GetExpectedValue(delay_imports, os) - 2); 297 EXPECT_EQ(expectations.GetExpectation(Expectations::DELAY_IMPORTS), count);
241 EXPECT_LT(count, GetExpectedValue(delay_imports, os) + 8);
242 298
243 count = 0; 299 count = 0;
244 pe.EnumRelocs(RelocsCallback, &count); 300 pe.EnumRelocs(RelocsCallback, &count);
245 EXPECT_GT(count, GetExpectedValue(relocs, os) - 150); 301 EXPECT_EQ(expectations.GetExpectation(Expectations::RELOCS), count);
246 EXPECT_LT(count, GetExpectedValue(relocs, os) + 1500);
247 302
248 FreeLibrary(module); 303 FreeLibrary(module);
249 } 304 }
250 305
251 // Tests that we can locate an specific exported symbol, by name and by ordinal. 306 // Tests that we can locate an specific exported symbol, by name and by ordinal.
252 TEST(PEImageTest, RetrievesExports) { 307 TEST(PEImageTest, RetrievesExports) {
253 HMODULE module = LoadLibrary(L"advapi32.dll"); 308 HMODULE module = LoadLibrary(L"advapi32.dll");
254 ASSERT_TRUE(NULL != module); 309 ASSERT_TRUE(NULL != module);
255 310
256 PEImage pe(module); 311 PEImage pe(module);
(...skipping 21 matching lines...) Expand all
278 EXPECT_TRUE(pe.GetDebugId(&guid, &age)); 333 EXPECT_TRUE(pe.GetDebugId(&guid, &age));
279 334
280 GUID empty_guid = {0}; 335 GUID empty_guid = {0};
281 EXPECT_TRUE(!IsEqualGUID(empty_guid, guid)); 336 EXPECT_TRUE(!IsEqualGUID(empty_guid, guid));
282 EXPECT_NE(0U, age); 337 EXPECT_NE(0U, age);
283 FreeLibrary(module); 338 FreeLibrary(module);
284 } 339 }
285 340
286 } // namespace win 341 } // namespace win
287 } // namespace base 342 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698