1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/sampler/sampler_app.h"
16 :
17 : #include "base/bind.h"
18 : #include "base/path_service.h"
19 : #include "base/stringprintf.h"
20 : #include "base/files/scoped_temp_dir.h"
21 : #include "base/synchronization/condition_variable.h"
22 : #include "base/threading/thread.h"
23 : #include "base/win/pe_image.h"
24 : #include "gmock/gmock.h"
25 : #include "gtest/gtest.h"
26 : #include "syzygy/common/application.h"
27 : #include "syzygy/core/unittest_util.h"
28 : #include "syzygy/pe/unittest_util.h"
29 : #include "syzygy/trace/parse/parser.h"
30 : #include "syzygy/trace/parse/unittest_util.h"
31 :
32 : namespace sampler {
33 :
34 : namespace {
35 :
36 : using testing::_;
37 :
38 E : const base::TimeDelta kDefaultSamplingInterval;
39 :
40 : class TestSamplerApp : public SamplerApp {
41 : public:
42 : TestSamplerApp()
43 : : start_profiling_(&cv_lock_),
44 : start_profiling_counter_(0),
45 : stop_profiling_(&cv_lock_),
46 : stop_profiling_counter_(0),
47 E : on_stop_profiling_sample_count_(0) {
48 E : }
49 :
50 : using SamplerApp::PidSet;
51 :
52 : using SamplerApp::GetModuleSignature;
53 : using SamplerApp::set_running;
54 :
55 : using SamplerApp::pids_;
56 : using SamplerApp::blacklist_pids_;
57 : using SamplerApp::output_dir_;
58 : using SamplerApp::module_sigs_;
59 : using SamplerApp::log2_bucket_size_;
60 : using SamplerApp::sampling_interval_;
61 : using SamplerApp::running_;
62 :
63 E : void WaitUntilStartProfiling() {
64 E : base::AutoLock auto_lock(cv_lock_);
65 E : while (start_profiling_counter_ == 0)
66 E : start_profiling_.Wait();
67 E : --start_profiling_counter_;
68 E : }
69 :
70 : // Waits until a module has finished profiling, returning the total number of
71 : // samples set.
72 E : uint64 WaitUntilStopProfiling() {
73 E : base::AutoLock auto_lock(cv_lock_);
74 E : while (stop_profiling_counter_ == 0)
75 i : stop_profiling_.Wait();
76 E : --stop_profiling_counter_;
77 E : return on_stop_profiling_sample_count_;
78 E : }
79 :
80 : protected:
81 : virtual void OnStartProfiling(
82 E : const SampledModuleCache::Module* module) OVERRIDE {
83 E : DCHECK(module != NULL);
84 E : base::AutoLock auto_lock(cv_lock_);
85 E : ++start_profiling_counter_;
86 E : start_profiling_.Signal();
87 E : }
88 :
89 : virtual void OnStopProfiling(
90 E : const SampledModuleCache::Module* module) OVERRIDE {
91 E : DCHECK(module != NULL);
92 E : base::AutoLock auto_lock(cv_lock_);
93 :
94 : // Count up the number of samples.
95 E : on_stop_profiling_sample_count_ = 0;
96 E : for (size_t i = 0; i < module->profiler().buckets().size(); ++i)
97 E : on_stop_profiling_sample_count_ += module->profiler().buckets()[i];
98 :
99 E : ++stop_profiling_counter_;
100 E : stop_profiling_.Signal();
101 E : }
102 :
103 : private:
104 : base::Lock cv_lock_;
105 : base::ConditionVariable start_profiling_; // Under cv_lock_.
106 : size_t start_profiling_counter_; // Under cv_lock_.
107 : base::ConditionVariable stop_profiling_; // Under cv_lock_.
108 : size_t stop_profiling_counter_; // Under cv_lock_.
109 :
110 : // This will be set to the total number of samples collected in the last
111 : // OnStopProfiling event.
112 : uint64 on_stop_profiling_sample_count_; // Under cv_lock_.
113 : };
114 :
115 : class TestParseEventHandler : public testing::MockParseEventHandler {
116 : public:
117 E : TestParseEventHandler() : sample_count(0) {
118 E : ::memset(&trace_sample_data, 0, sizeof(trace_sample_data));
119 E : }
120 :
121 : // This is used to inspect the results of an OnSampleData call. We remember
122 : // the number of samples in trace_sample_data_sample_count_.
123 : void TestOnSampleData(base::Time time,
124 : DWORD process_id,
125 E : const TraceSampleData* data) {
126 E : DCHECK(data != NULL);
127 E : sample_count = 0;
128 E : for (size_t i = 0; i < data->bucket_count; ++i)
129 E : sample_count += data->buckets[i];
130 :
131 E : ::memcpy(&trace_sample_data, data, sizeof(trace_sample_data));
132 E : }
133 :
134 : // This will be a copy of the TraceSampleData buffer seen by the last
135 : // call to TestOnSampleData, minus the bucket table.
136 : TraceSampleData trace_sample_data;
137 :
138 : // This will be set to the total number of samples seen in the last
139 : // TraceSampleData buffer seen by TestOnSampleData.
140 : uint64 sample_count;
141 : };
142 :
143 : class SamplerAppTest : public testing::PELibUnitTest {
144 : public:
145 : typedef testing::PELibUnitTest Super;
146 : typedef common::Application<TestSamplerApp> TestApplication;
147 :
148 : SamplerAppTest()
149 : : cmd_line_(base::FilePath(L"sampler.exe")),
150 : impl_(app_.implementation()),
151 E : worker_thread_("worker-thread") {
152 E : }
153 :
154 E : virtual void SetUp() OVERRIDE {
155 E : Super::SetUp();
156 :
157 E : ASSERT_TRUE(worker_thread_.Start());
158 :
159 : // Setup the IO streams.
160 E : ASSERT_NO_FATAL_FAILURE(CreateTemporaryDir(&temp_dir_));
161 E : stdin_path_ = temp_dir_.Append(L"NUL");
162 E : stdout_path_ = temp_dir_.Append(L"stdout.txt");
163 E : stderr_path_ = temp_dir_.Append(L"stderr.txt");
164 E : ASSERT_NO_FATAL_FAILURE(InitStreams(
165 : stdin_path_, stdout_path_, stderr_path_));
166 :
167 : // Point the application at the test's command-line and IO streams.
168 E : app_.set_command_line(&cmd_line_);
169 E : app_.set_in(in());
170 E : app_.set_out(out());
171 E : app_.set_err(err());
172 :
173 E : test_dll_path = testing::GetOutputRelativePath(testing::kTestDllName);
174 E : ASSERT_TRUE(TestSamplerApp::GetModuleSignature(test_dll_path,
175 : &test_dll_sig));
176 :
177 E : ASSERT_TRUE(PathService::Get(base::FILE_EXE, &self_path));
178 E : ASSERT_TRUE(TestSamplerApp::GetModuleSignature(self_path,
179 : &self_sig));
180 :
181 E : output_dir = temp_dir_.AppendASCII("output");
182 E : }
183 :
184 : // Runs the application asynchronously. Provides the return value via the
185 : // output parameter.
186 E : void RunAppAsync(int* ret) {
187 E : DCHECK(ret != NULL);
188 E : *ret = impl_.Run();
189 E : }
190 :
191 : base::FilePath test_dll_path;
192 : base::FilePath self_path;
193 : TestSamplerApp::ModuleSignature test_dll_sig;
194 : TestSamplerApp::ModuleSignature self_sig;
195 :
196 : // The trace file directory.
197 : base::FilePath output_dir;
198 :
199 : protected:
200 : // The command line to be given to the application under test.
201 : CommandLine cmd_line_;
202 :
203 : // The application object under test.
204 : TestApplication app_;
205 :
206 : // A reference to the underlying application implementation for convenience.
207 : TestSamplerApp& impl_;
208 :
209 : // A temporary folder where all IO will be stored.
210 : base::FilePath temp_dir_;
211 :
212 : // @name File paths used for the standard IO streams.
213 : // @{
214 : base::FilePath stdin_path_;
215 : base::FilePath stdout_path_;
216 : base::FilePath stderr_path_;
217 : // @}
218 :
219 : // A worker thread for posting asynchronous tasks.
220 : base::Thread worker_thread_;
221 : };
222 :
223 : } // namespace
224 :
225 : // Comparison operator for ModuleSignatures. This is outside the anonymous
226 : // namespace so that it is found by name resolution.
227 : bool operator==(const TestSamplerApp::ModuleSignature& s1,
228 E : const TestSamplerApp::ModuleSignature& s2) {
229 : return s1.size == s2.size && s1.time_date_stamp == s2.time_date_stamp &&
230 E : s1.checksum == s2.checksum;
231 E : }
232 :
233 E : TEST_F(SamplerAppTest, ParseEmptyCommandLineFails) {
234 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
235 E : }
236 :
237 E : TEST_F(SamplerAppTest, ParseEmptyPidsFails) {
238 E : cmd_line_.AppendSwitch(TestSamplerApp::kPids);
239 E : cmd_line_.AppendArgPath(test_dll_path);
240 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
241 E : }
242 :
243 E : TEST_F(SamplerAppTest, ParseInvalidPidFails) {
244 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1234,ab");
245 E : cmd_line_.AppendArgPath(test_dll_path);
246 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
247 E : }
248 :
249 E : TEST_F(SamplerAppTest, ParseEmptyPids) {
250 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, ",,,");
251 E : cmd_line_.AppendArgPath(test_dll_path);
252 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
253 E : }
254 :
255 E : TEST_F(SamplerAppTest, ParseOnePidWithManyEmptyPids) {
256 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, ",1234,,");
257 E : cmd_line_.AppendArgPath(test_dll_path);
258 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
259 :
260 E : EXPECT_THAT(impl_.pids_, testing::ElementsAre(1234));
261 E : EXPECT_FALSE(impl_.blacklist_pids_);
262 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
263 E : }
264 :
265 E : TEST_F(SamplerAppTest, ParseNoModulesFails) {
266 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1234");
267 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
268 E : }
269 :
270 E : TEST_F(SamplerAppTest, ParseInvalidModuleFails) {
271 E : cmd_line_.AppendArg("this_module_does_not_exist.dll");
272 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
273 E : }
274 :
275 E : TEST_F(SamplerAppTest, ParseSmallBucketSizeFails) {
276 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "2");
277 E : cmd_line_.AppendArgPath(test_dll_path);
278 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
279 E : }
280 :
281 E : TEST_F(SamplerAppTest, ParseNonPowerOfTwoBucketSizeFails) {
282 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "33");
283 E : cmd_line_.AppendArgPath(test_dll_path);
284 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
285 E : }
286 :
287 E : TEST_F(SamplerAppTest, ParseInvalidBucketSizeFails) {
288 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "yay");
289 E : cmd_line_.AppendArgPath(test_dll_path);
290 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
291 E : }
292 :
293 E : TEST_F(SamplerAppTest, ParseValidBucketSizeMinimal) {
294 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "8");
295 E : cmd_line_.AppendArgPath(test_dll_path);
296 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
297 :
298 E : EXPECT_TRUE(impl_.pids_.empty());
299 E : EXPECT_TRUE(impl_.blacklist_pids_);
300 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
301 E : EXPECT_EQ(3u, impl_.log2_bucket_size_);
302 E : EXPECT_EQ(kDefaultSamplingInterval, impl_.sampling_interval_);
303 E : EXPECT_TRUE(impl_.output_dir_.empty());
304 E : }
305 :
306 E : TEST_F(SamplerAppTest, ParseTooSmallSamplingIntervalFails) {
307 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-7");
308 E : cmd_line_.AppendArgPath(test_dll_path);
309 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
310 E : }
311 :
312 E : TEST_F(SamplerAppTest, ParseInvalidSamplingIntervalFails) {
313 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "3zz");
314 E : cmd_line_.AppendArgPath(test_dll_path);
315 E : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
316 E : }
317 :
318 E : TEST_F(SamplerAppTest, ParseValidSamplingIntervalInteger) {
319 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "2");
320 E : cmd_line_.AppendArgPath(test_dll_path);
321 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
322 :
323 E : EXPECT_TRUE(impl_.pids_.empty());
324 E : EXPECT_TRUE(impl_.blacklist_pids_);
325 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
326 E : EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
327 E : EXPECT_EQ(base::TimeDelta::FromSeconds(2), impl_.sampling_interval_);
328 E : EXPECT_TRUE(impl_.output_dir_.empty());
329 E : }
330 :
331 E : TEST_F(SamplerAppTest, ParseValidSamplingIntervalDecimal) {
332 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1.5");
333 E : cmd_line_.AppendArgPath(test_dll_path);
334 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
335 :
336 E : EXPECT_TRUE(impl_.pids_.empty());
337 E : EXPECT_TRUE(impl_.blacklist_pids_);
338 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
339 E : EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
340 E : EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500), impl_.sampling_interval_);
341 E : EXPECT_TRUE(impl_.output_dir_.empty());
342 E : }
343 :
344 E : TEST_F(SamplerAppTest, ParseValidSamplingIntervalScientific) {
345 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-3");
346 E : cmd_line_.AppendArgPath(test_dll_path);
347 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
348 :
349 E : EXPECT_TRUE(impl_.pids_.empty());
350 E : EXPECT_TRUE(impl_.blacklist_pids_);
351 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
352 E : EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
353 E : EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), impl_.sampling_interval_);
354 E : EXPECT_TRUE(impl_.output_dir_.empty());
355 E : }
356 :
357 E : TEST_F(SamplerAppTest, ParseOutputDir) {
358 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kOutputDir, "foo");
359 E : cmd_line_.AppendArgPath(test_dll_path);
360 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
361 :
362 E : EXPECT_TRUE(impl_.pids_.empty());
363 E : EXPECT_TRUE(impl_.blacklist_pids_);
364 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
365 E : EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
366 E : EXPECT_EQ(kDefaultSamplingInterval, impl_.sampling_interval_);
367 E : EXPECT_EQ(base::FilePath(L"foo"), impl_.output_dir_);
368 E : }
369 :
370 E : TEST_F(SamplerAppTest, ParseMinimal) {
371 E : cmd_line_.AppendArgPath(test_dll_path);
372 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
373 :
374 E : EXPECT_TRUE(impl_.pids_.empty());
375 E : EXPECT_TRUE(impl_.blacklist_pids_);
376 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
377 E : EXPECT_EQ(SamplerApp::kDefaultLog2BucketSize, impl_.log2_bucket_size_);
378 E : EXPECT_EQ(kDefaultSamplingInterval, impl_.sampling_interval_);
379 E : EXPECT_TRUE(impl_.output_dir_.empty());
380 E : }
381 :
382 E : TEST_F(SamplerAppTest, ParseFullWhitelist) {
383 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1,2,3");
384 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "8");
385 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-3");
386 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kOutputDir, "foo");
387 E : cmd_line_.AppendArgPath(test_dll_path);
388 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
389 :
390 E : EXPECT_THAT(impl_.pids_, testing::ElementsAre(1, 2, 3));
391 E : EXPECT_FALSE(impl_.blacklist_pids_);
392 E : EXPECT_THAT(impl_.module_sigs_, testing::ElementsAre(test_dll_sig));
393 E : EXPECT_EQ(3, impl_.log2_bucket_size_);
394 E : EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), impl_.sampling_interval_);
395 E : EXPECT_EQ(base::FilePath(L"foo"), impl_.output_dir_);
396 E : }
397 :
398 E : TEST_F(SamplerAppTest, ParseFullBlacklist) {
399 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids, "1,2,3");
400 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kBucketSize, "8");
401 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "1e-3");
402 E : cmd_line_.AppendSwitch(TestSamplerApp::kBlacklistPids);
403 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kOutputDir, "foo");
404 E : cmd_line_.AppendArgPath(test_dll_path);
405 E : cmd_line_.AppendArgPath(self_path);
406 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
407 :
408 E : EXPECT_THAT(impl_.pids_, testing::ElementsAre(1, 2, 3));
409 E : EXPECT_TRUE(impl_.blacklist_pids_);
410 : EXPECT_THAT(impl_.module_sigs_,
411 E : testing::ElementsAre(test_dll_sig, self_sig));
412 E : EXPECT_EQ(3, impl_.log2_bucket_size_);
413 E : EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), impl_.sampling_interval_);
414 E : EXPECT_EQ(base::FilePath(L"foo"), impl_.output_dir_);
415 E : }
416 :
417 E : TEST_F(SamplerAppTest, SampleSelfPidWhitelist) {
418 : cmd_line_.AppendSwitchASCII(TestSamplerApp::kPids,
419 E : base::StringPrintf("%d", ::GetCurrentProcessId()));
420 E : cmd_line_.AppendSwitchASCII(TestSamplerApp::kSamplingInterval, "0.25");
421 E : cmd_line_.AppendSwitchPath(TestSamplerApp::kOutputDir, output_dir);
422 E : cmd_line_.AppendArgPath(self_path);
423 E : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
424 :
425 E : int ret = 0;
426 : base::Closure run = base::Bind(
427 : &SamplerAppTest::RunAppAsync,
428 : base::Unretained(this),
429 E : base::Unretained(&ret));
430 E : worker_thread_.message_loop()->PostTask(FROM_HERE, run);
431 :
432 : // Wait for profiling to start.
433 E : impl_.WaitUntilStartProfiling();
434 :
435 : // We expect the output directory to exist by now.
436 E : EXPECT_TRUE(file_util::PathExists(output_dir));
437 :
438 : // Stop the profiler.
439 E : impl_.set_running(false);
440 :
441 : // Stop the worker thread. This will return when the app has returned.
442 E : worker_thread_.Stop();
443 :
444 : // We should also have received a profiling stop event.
445 E : uint32 sample_count = impl_.WaitUntilStopProfiling();
446 :
447 : // NOTE: There's no way for us to find out exactly when the sampler has
448 : // started, and under high load the system may defer starting the sampler
449 : // or not process the interrupts. Thus, any test that inspects the
450 : // number of samplers seen by the profiler is doomed to be flaky.
451 :
452 : // Ensure that profiler output was produced.
453 : file_util::FileEnumerator fe(output_dir,
454 : false,
455 : file_util::FileEnumerator::FILES,
456 E : L"*.*");
457 E : base::FilePath dmp_path = fe.Next();
458 E : EXPECT_FALSE(dmp_path.empty());
459 :
460 E : int64 dmp_size = 0;
461 E : EXPECT_TRUE(file_util::GetFileSize(dmp_path, &dmp_size));
462 E : EXPECT_LT(0, dmp_size);
463 :
464 : // We expect no other output to have been produced.
465 E : EXPECT_TRUE(fe.Next().empty());
466 :
467 E : ASSERT_EQ(0, ret);
468 :
469 : // Now parse the generated trace file. We expect it to parse without issues
470 : // and to contain a process started, process attached to module, and module
471 : // sample data events.
472 E : testing::StrictMock<TestParseEventHandler> parse_handler;
473 : {
474 E : testing::InSequence in_sequence;
475 E : EXPECT_CALL(parse_handler, OnProcessStarted(_, _, _)).Times(1);
476 E : EXPECT_CALL(parse_handler, OnProcessAttach(_, _, _, _)).Times(1);
477 : EXPECT_CALL(parse_handler, OnSampleData(_, _, _)).Times(1).WillOnce(
478 : testing::Invoke(&parse_handler,
479 E : &TestParseEventHandler::TestOnSampleData));
480 E : }
481 :
482 E : trace::parser::Parser parser;
483 E : ASSERT_TRUE(parser.Init(&parse_handler));
484 E : ASSERT_TRUE(parser.OpenTraceFile(dmp_path));
485 E : ASSERT_TRUE(parser.Consume());
486 E : ASSERT_FALSE(parser.error_occurred());
487 E : ASSERT_TRUE(parser.Close());
488 :
489 : // Make sure that the TraceModuleData the parser saw agrees with our
490 : // expectations.
491 E : base::win::PEImage pe_image(::GetModuleHandleA(NULL));
492 : EXPECT_EQ(reinterpret_cast<ModuleAddr>(pe_image.module()),
493 E : parse_handler.trace_sample_data.module_base_addr);
494 : EXPECT_EQ(pe_image.GetNTHeaders()->OptionalHeader.SizeOfImage,
495 E : parse_handler.trace_sample_data.module_size);
496 : EXPECT_EQ(pe_image.GetNTHeaders()->OptionalHeader.CheckSum,
497 E : parse_handler.trace_sample_data.module_checksum);
498 : EXPECT_EQ(pe_image.GetNTHeaders()->FileHeader.TimeDateStamp,
499 E : parse_handler.trace_sample_data.module_time_date_stamp);
500 E : EXPECT_EQ(sample_count, parse_handler.sample_count);
501 E : }
502 :
503 : } // namespace sampler
|