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

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: expectation logic fix 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
16 namespace {
17
18 class Expectations {
rvargas (doing something else) 2015/02/24 01:52:20 Please move this outside of the namespaces...
Will Harris 2015/02/24 19:00:28 Done.
rvargas (doing something else) 2015/02/24 20:03:22 Sorry, what I meant was to move the anonymous name
19 public:
20 enum Value {
21 sections = 0,
rvargas (doing something else) 2015/02/24 01:52:21 Shout for enums
Will Harris 2015/02/24 19:00:29 Done.
22 imports_dlls,
23 delay_dlls,
24 exports,
25 imports,
26 delay_imports,
27 relocs
28 };
29
30 enum Arch {
31 ARCH_X86 = 0,
32 ARCH_X64,
33 ARCH_X86_ON_X64,
34 ARCH_X64_ON_X64,
35 ARCH_X86_ON_X86,
36 ARCH_ALL
37 };
38
39 int GetExpectation(Value value);
40 void SetOverride(Value value, Version version, Arch arch, int count);
rvargas (doing something else) 2015/02/24 01:52:20 ... so that it becomes obvious what Version is
Will Harris 2015/02/24 19:00:28 Done.
41 void SetOverride(Value value, Version version, int count);
42 void SetOverride(Value value, Arch arch, int count);
43
44 void SetDefault(Value value, int count) {
45 SetOverride(value, VERSION_WIN_LAST, ARCH_ALL, count);
46 }
47
48 Expectations() {
rvargas (doing something else) 2015/02/24 01:52:20 nit: The constructor goes before all other methods
Will Harris 2015/02/24 19:00:29 Done.
49 my_version_ = GetVersion();
50 #if defined(ARCH_CPU_64_BITS)
51 my_arch_ = ARCH_X64_ON_X64;
rvargas (doing something else) 2015/02/24 01:52:20 X64?
Will Harris 2015/02/24 19:00:28 Done.
52 #else
53 OSInfo* os_info = OSInfo::GetInstance();
54 if (os_info->wow64_status() == OSInfo::WOW64_DISABLED)
55 my_arch_ = ARCH_X86_ON_X86;
rvargas (doing something else) 2015/02/24 01:52:21 X86?... Arch seems to have too many values :)
Will Harris 2015/02/24 19:00:28 Acknowledged.
56 else
57 my_arch_ = ARCH_X86_ON_X64;
58 #endif
59 }
60
61 private:
62 class Override {
63 public:
64 enum MatchType { MATCH_VERSION, MATCH_ARCH, MATCH_BOTH, MATCH_NONE };
65 explicit Override(Value value, Version version, Arch arch, int count)
rvargas (doing something else) 2015/02/24 01:52:20 no need for explicit.
rvargas (doing something else) 2015/02/24 01:52:21 nit: add empty line before this one.
Will Harris 2015/02/24 19:00:28 Done.
Will Harris 2015/02/24 19:00:28 Done.
66 : value_(value), version_(version), arch_(arch), count_(count){};
rvargas (doing something else) 2015/02/24 01:52:21 nit: space before {}... and this is not a single l
Will Harris 2015/02/24 19:00:28 Done.
67
68 bool Matches(Value value, Version version, Arch arch, MatchType type) {
69 if (value_ != value)
70 return false;
71 switch (type) {
rvargas (doing something else) 2015/02/24 01:52:21 nit: empty line before this
Will Harris 2015/02/24 19:00:28 Done.
72 case MATCH_BOTH:
73 return MatchesVersion(version) && MatchesArch(arch);
74 break;
rvargas (doing something else) 2015/02/24 01:52:21 nit: no break after return
Will Harris 2015/02/24 19:00:28 Done.
75 case MATCH_ARCH:
76 return MatchesArch(arch) && version_ == VERSION_WIN_LAST;
77 break;
78 case MATCH_VERSION:
79 return MatchesVersion(version) && arch_ == ARCH_ALL;
80 break;
81 case MATCH_NONE:
82 return (arch_ == ARCH_ALL && version_ == VERSION_WIN_LAST);
83 break;
84 }
85 return false;
86 }
87
88 int GetCount() { return count_; }
89
90 private:
91 bool MatchesArch(Arch arch) {
92 switch (arch) {
93 case ARCH_X64_ON_X64:
94 return (arch_ == ARCH_X64_ON_X64 || arch_ == ARCH_X64);
95 break;
96 case ARCH_X86_ON_X86:
97 return (arch_ == ARCH_X86_ON_X86 || arch_ == ARCH_X86);
98 break;
99 case ARCH_X86_ON_X64:
100 return (arch_ == ARCH_X86_ON_X64 || arch_ == ARCH_X86);
101 break;
102 default:
103 return false;
104 }
105 }
106
107 bool MatchesVersion(Version version) { return (version == version_); }
108
109 Value value_;
110 Version version_;
111 Arch arch_;
112 int count_;
113 };
114
115 bool MatchesMyArch(Arch arch);
116
117 std::vector<Override> overrides_;
118 Arch my_arch_;
119 Version my_version_;
120 };
121
122 int Expectations::GetExpectation(Value value) {
123 // Prefer OS version specificity over Arch specificity.
124 for (auto type : {Expectations::Override::MATCH_BOTH,
rvargas (doing something else) 2015/02/24 01:52:20 nit: space after {
Will Harris 2015/02/24 19:00:28 Done. Strange, all these are being done by clang
125 Expectations::Override::MATCH_VERSION,
126 Expectations::Override::MATCH_ARCH,
127 Expectations::Override::MATCH_NONE})
rvargas (doing something else) 2015/02/24 01:52:21 nit: needs {}
Will Harris 2015/02/24 19:00:28 Done.
128 for (auto or : overrides_)
rvargas (doing something else) 2015/02/24 01:52:20 nit: needs {}
rvargas (doing something else) 2015/02/24 01:52:21 nit: use a name longer than "or" (in general, name
Will Harris 2015/02/24 19:00:28 Done.
Will Harris 2015/02/24 19:00:29 Done.
129 if (or.Matches(value, my_version_, my_arch_, type))
130 return or.GetCount();
131 return 0;
rvargas (doing something else) 2015/02/24 01:52:21 Shouldn't this be a failure instead?
Will Harris 2015/02/24 19:00:29 returns -1 which makes it never possible in the te
132 }
133
134 void Expectations::SetOverride(Value value,
135 Version version,
136 Arch arch,
137 int count) {
138 overrides_.push_back(Override(value, version, arch, count));
139 }
140
141 void Expectations::SetOverride(Value value, Version version, int count) {
142 SetOverride(value, version, ARCH_ALL, count);
143 }
144
145 void Expectations::SetOverride(Value value, Arch arch, int count) {
146 SetOverride(value, VERSION_WIN_LAST, arch, count);
147 }
148
14 // Just counts the number of invocations. 149 // Just counts the number of invocations.
15 bool ExportsCallback(const PEImage &image, 150 bool ExportsCallback(const PEImage &image,
16 DWORD ordinal, 151 DWORD ordinal,
17 DWORD hint, 152 DWORD hint,
18 LPCSTR name, 153 LPCSTR name,
19 PVOID function, 154 PVOID function,
20 LPCSTR forward, 155 LPCSTR forward,
21 PVOID cookie) { 156 PVOID cookie) {
22 int* count = reinterpret_cast<int*>(cookie); 157 int* count = reinterpret_cast<int*>(cookie);
23 (*count)++; 158 (*count)++;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 PIMAGE_THUNK_DATA name_table, 211 PIMAGE_THUNK_DATA name_table,
77 PIMAGE_THUNK_DATA iat, 212 PIMAGE_THUNK_DATA iat,
78 PIMAGE_THUNK_DATA bound_iat, 213 PIMAGE_THUNK_DATA bound_iat,
79 PIMAGE_THUNK_DATA unload_iat, 214 PIMAGE_THUNK_DATA unload_iat,
80 PVOID cookie) { 215 PVOID cookie) {
81 int* count = reinterpret_cast<int*>(cookie); 216 int* count = reinterpret_cast<int*>(cookie);
82 (*count)++; 217 (*count)++;
83 return true; 218 return true;
84 } 219 }
85 220
86 // Identifiers for the set of supported expectations. 221 } // namespace
87 enum ExpectationSet {
88 WIN_2K_SET,
89 WIN_XP_SET,
90 WIN_VISTA_SET,
91 WIN_7_SET,
92 WIN_8_SET,
93 UNSUPPORTED_SET,
94 };
95
96 // We'll be using some known values for the tests.
97 enum Value {
98 sections = 0,
99 imports_dlls,
100 delay_dlls,
101 exports,
102 imports,
103 delay_imports,
104 relocs
105 };
106
107 ExpectationSet GetExpectationSet(DWORD os) {
108 if (os == 50)
109 return WIN_2K_SET;
110 if (os == 51)
111 return WIN_XP_SET;
112 if (os == 60)
113 return WIN_VISTA_SET;
114 if (os == 61)
115 return WIN_7_SET;
116 if (os >= 62)
117 return WIN_8_SET;
118 return UNSUPPORTED_SET;
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 }
163
164 // Contains the expected value, for each enumerated property (Value), and the
165 // OS version: [Value][os_version]
166 const int expected[][5] = {
167 {4, 4, 4, win7_sections, win8_sections},
168 {3, 3, 3, 13, win8_import_dlls},
169 {w2k_delay_dlls, xp_delay_dlls, vista_delay_dlls, win7_delay_dlls,
170 win8_delay_dlls},
171 {w2k_exports, xp_exports, vista_exports, win7_exports, win8_exports},
172 {w2k_imports, xp_imports, vista_imports, win7_imports, win8_imports},
173 {w2k_delay_imports, xp_delay_imports,
174 vista_delay_imports, win7_delay_imports, win8_delay_imports},
175 {w2k_relocs, xp_relocs, vista_relocs, win7_relocs, win8_relocs}
176 };
177 COMPILE_ASSERT(arraysize(expected[0]) == UNSUPPORTED_SET,
178 expected_value_set_mismatch);
179
180 if (value > relocs)
181 return 0;
182 ExpectationSet expected_set = GetExpectationSet(os);
183 if (expected_set >= arraysize(expected)) {
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 222
200 // Tests that we are able to enumerate stuff from a PE file, and that 223 // 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. 224 // the actual number of items found is within the expected range.
202 TEST(PEImageTest, MAYBE_EnumeratesPE) { 225 TEST(PEImageTest, EnumeratesPE) {
203 HMODULE module = LoadLibrary(L"advapi32.dll"); 226 Expectations expectations;
227
228 // Default expectations.
229 expectations.SetDefault(Expectations::sections, 5);
230 expectations.SetDefault(Expectations::imports_dlls, 1);
231 expectations.SetDefault(Expectations::delay_dlls, 1);
232 expectations.SetDefault(Expectations::exports, 1);
233 expectations.SetDefault(Expectations::imports, 63);
234 expectations.SetDefault(Expectations::delay_imports, 2);
235 expectations.SetDefault(Expectations::relocs, 1584);
236
237 // 64-bit expectations (taken from win_chromium_x64_rel_ng).
rvargas (doing something else) 2015/02/24 01:52:20 nit: Don't add comments that are prone to be stale
Will Harris 2015/02/24 19:00:28 Done.
238 expectations.SetOverride(Expectations::sections, Expectations::ARCH_X64, 6);
239 expectations.SetOverride(Expectations::imports, Expectations::ARCH_X64, 66);
240 expectations.SetOverride(Expectations::relocs, Expectations::ARCH_X64, 630);
241
242 HMODULE module = LoadLibrary(L"pe_image_test.dll");
rvargas (doing something else) 2015/02/24 01:52:21 If we want to at least keep the same coverage leve
Will Harris 2015/02/24 19:00:28 Done.
204 ASSERT_TRUE(NULL != module); 243 ASSERT_TRUE(NULL != module);
205 244
206 PEImage pe(module); 245 PEImage pe(module);
207 int count = 0; 246 int count = 0;
208 EXPECT_TRUE(pe.VerifyMagic()); 247 EXPECT_TRUE(pe.VerifyMagic());
209 248
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); 249 pe.EnumSections(SectionsCallback, &count);
218 EXPECT_EQ(GetExpectedValue(sections, os), count); 250 EXPECT_EQ(expectations.GetExpectation(Expectations::sections), count);
219 251
220 count = 0; 252 count = 0;
221 pe.EnumImportChunks(ImportChunksCallback, &count); 253 pe.EnumImportChunks(ImportChunksCallback, &count);
222 EXPECT_EQ(GetExpectedValue(imports_dlls, os), count); 254 EXPECT_EQ(expectations.GetExpectation(Expectations::imports_dlls), count);
223 255
224 count = 0; 256 count = 0;
225 pe.EnumDelayImportChunks(DelayImportChunksCallback, &count); 257 pe.EnumDelayImportChunks(DelayImportChunksCallback, &count);
226 EXPECT_EQ(GetExpectedValue(delay_dlls, os), count); 258 EXPECT_EQ(expectations.GetExpectation(Expectations::delay_dlls), count);
227 259
228 count = 0; 260 count = 0;
229 pe.EnumExports(ExportsCallback, &count); 261 pe.EnumExports(ExportsCallback, &count);
230 EXPECT_GT(count, GetExpectedValue(exports, os) - 20); 262 EXPECT_EQ(expectations.GetExpectation(Expectations::exports), count);
231 EXPECT_LT(count, GetExpectedValue(exports, os) + 100);
232 263
233 count = 0; 264 count = 0;
234 pe.EnumAllImports(ImportsCallback, &count); 265 pe.EnumAllImports(ImportsCallback, &count);
235 EXPECT_GT(count, GetExpectedValue(imports, os) - 20); 266 EXPECT_EQ(expectations.GetExpectation(Expectations::imports), count);
236 EXPECT_LT(count, GetExpectedValue(imports, os) + 100);
237 267
238 count = 0; 268 count = 0;
239 pe.EnumAllDelayImports(ImportsCallback, &count); 269 pe.EnumAllDelayImports(ImportsCallback, &count);
240 EXPECT_GT(count, GetExpectedValue(delay_imports, os) - 2); 270 EXPECT_EQ(expectations.GetExpectation(Expectations::delay_imports), count);
241 EXPECT_LT(count, GetExpectedValue(delay_imports, os) + 8);
242 271
243 count = 0; 272 count = 0;
244 pe.EnumRelocs(RelocsCallback, &count); 273 pe.EnumRelocs(RelocsCallback, &count);
245 EXPECT_GT(count, GetExpectedValue(relocs, os) - 150); 274 EXPECT_EQ(expectations.GetExpectation(Expectations::relocs), count);
246 EXPECT_LT(count, GetExpectedValue(relocs, os) + 1500);
247 275
248 FreeLibrary(module); 276 FreeLibrary(module);
249 } 277 }
250 278
251 // Tests that we can locate an specific exported symbol, by name and by ordinal. 279 // Tests that we can locate an specific exported symbol, by name and by ordinal.
252 TEST(PEImageTest, RetrievesExports) { 280 TEST(PEImageTest, RetrievesExports) {
253 HMODULE module = LoadLibrary(L"advapi32.dll"); 281 HMODULE module = LoadLibrary(L"advapi32.dll");
254 ASSERT_TRUE(NULL != module); 282 ASSERT_TRUE(NULL != module);
255 283
256 PEImage pe(module); 284 PEImage pe(module);
(...skipping 21 matching lines...) Expand all
278 EXPECT_TRUE(pe.GetDebugId(&guid, &age)); 306 EXPECT_TRUE(pe.GetDebugId(&guid, &age));
279 307
280 GUID empty_guid = {0}; 308 GUID empty_guid = {0};
281 EXPECT_TRUE(!IsEqualGUID(empty_guid, guid)); 309 EXPECT_TRUE(!IsEqualGUID(empty_guid, guid));
282 EXPECT_NE(0U, age); 310 EXPECT_NE(0U, age);
283 FreeLibrary(module); 311 FreeLibrary(module);
284 } 312 }
285 313
286 } // namespace win 314 } // namespace win
287 } // namespace base 315 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698