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