1 : // Copyright 2012 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/trace/parse/parse_engine.h"
16 :
17 : #include <windows.h> // NOLINT
18 : #include <wmistr.h> // NOLINT
19 : #include <evntrace.h>
20 :
21 : #include <set>
22 : #include <vector>
23 :
24 : #include "base/logging.h"
25 : #include "base/strings/string_util.h"
26 : #include "gmock/gmock.h"
27 : #include "gtest/gtest.h"
28 : #include "syzygy/common/indexed_frequency_data.h"
29 : #include "syzygy/trace/parse/parser.h"
30 :
31 : namespace {
32 :
33 : using testing::_;
34 : using trace::parser::Parser;
35 : using trace::parser::ParseEngine;
36 : using trace::parser::ParseEventHandler;
37 : using trace::parser::ModuleInformation;
38 :
39 : typedef std::multiset<FuncAddr> FunctionSet;
40 : typedef std::vector<TraceModuleData> ModuleSet;
41 :
42 : class ParseEngineUnitTest
43 : : public testing::Test,
44 : public ParseEngine,
45 : public ParseEventHandler {
46 : public:
47 : ParseEngineUnitTest()
48 E : : ParseEngine("Test", true),
49 E : basic_block_frequencies(0),
50 E : expected_data(NULL) {
51 E : ::memset(&event_record_, 0, sizeof(event_record_));
52 E : set_event_handler(this);
53 E : }
54 :
55 E : ~ParseEngineUnitTest() {
56 E : }
57 :
58 E : void DispatchEventData(TraceEventType type, const void* data, size_t size) {
59 E : ::memset(&event_record_, 0, sizeof(event_record_));
60 E : event_record_.Header.ProcessId = kProcessId;
61 E : event_record_.Header.ThreadId = kThreadId;
62 E : event_record_.Header.Guid = kCallTraceEventClass;
63 E : event_record_.Header.Class.Type = type;
64 E : event_record_.MofData = const_cast<void*>(data);
65 E : event_record_.MofLength = size;
66 :
67 E : ASSERT_TRUE(DispatchEvent(&event_record_));
68 E : }
69 :
70 i : bool IsRecognizedTraceFile(const base::FilePath& trace_file_path) override {
71 i : return true;
72 i : }
73 :
74 i : bool OpenTraceFile(const base::FilePath& trace_file_path) override {
75 i : return true;
76 i : }
77 :
78 i : virtual bool ConsumeAllEvents() {
79 i : return true;
80 i : }
81 :
82 i : virtual bool CloseAllTraceFiles() {
83 i : return true;
84 i : }
85 :
86 : // ParseEventHander methods.
87 :
88 : void OnProcessStarted(base::Time time,
89 : DWORD process_id,
90 i : const TraceSystemInfo* data) override {
91 i : ASSERT_EQ(process_id, kProcessId);
92 i : }
93 :
94 i : void OnProcessEnded(base::Time time, DWORD process_id) override {
95 i : ASSERT_EQ(process_id, kProcessId);
96 i : }
97 :
98 : void OnFunctionEntry(base::Time time,
99 : DWORD process_id,
100 : DWORD thread_id,
101 E : const TraceEnterExitEventData* data) override {
102 E : ASSERT_EQ(process_id, kProcessId);
103 E : ASSERT_EQ(thread_id, kThreadId);
104 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
105 E : EXPECT_TRUE(data->function != NULL);
106 E : function_entries.insert(data->function);
107 E : }
108 :
109 : void OnFunctionExit(base::Time time,
110 : DWORD process_id,
111 : DWORD thread_id,
112 E : const TraceEnterExitEventData* data) override {
113 E : ASSERT_EQ(process_id, kProcessId);
114 E : ASSERT_EQ(thread_id, kThreadId);
115 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
116 E : EXPECT_TRUE(data->function != NULL);
117 E : function_exits.insert(data->function);
118 E : }
119 :
120 : void OnBatchFunctionEntry(base::Time time,
121 : DWORD process_id,
122 : DWORD thread_id,
123 E : const TraceBatchEnterData* data) override {
124 E : ASSERT_EQ(process_id, kProcessId);
125 E : ASSERT_EQ(thread_id, kThreadId);
126 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
127 E : for (size_t i = 0; i < data->num_calls; ++i) {
128 E : function_entries.insert(data->calls[i].function);
129 E : }
130 E : }
131 :
132 : void OnProcessAttach(base::Time time,
133 : DWORD process_id,
134 : DWORD thread_id,
135 E : const TraceModuleData* data) override {
136 E : ASSERT_EQ(process_id, kProcessId);
137 E : ASSERT_EQ(thread_id, kThreadId);
138 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
139 E : process_attaches.push_back(*data);
140 E : }
141 :
142 : void OnProcessDetach(base::Time time,
143 : DWORD process_id,
144 : DWORD thread_id,
145 E : const TraceModuleData* data) override {
146 E : ASSERT_EQ(process_id, kProcessId);
147 E : ASSERT_EQ(thread_id, kThreadId);
148 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
149 E : process_detaches.push_back(*data);
150 E : }
151 :
152 : void OnThreadAttach(base::Time time,
153 : DWORD process_id,
154 : DWORD thread_id,
155 E : const TraceModuleData* data) override {
156 E : ASSERT_EQ(process_id, kProcessId);
157 E : ASSERT_EQ(thread_id, kThreadId);
158 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
159 E : thread_attaches.push_back(*data);
160 E : }
161 :
162 : // Issued for DLL_THREAD_DETACH on an instrumented module.
163 : void OnThreadDetach(base::Time time,
164 : DWORD process_id,
165 : DWORD thread_id,
166 E : const TraceModuleData* data) override {
167 E : ASSERT_EQ(process_id, kProcessId);
168 E : ASSERT_EQ(thread_id, kThreadId);
169 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
170 E : thread_detaches.push_back(*data);
171 E : }
172 :
173 : void OnInvocationBatch(
174 : base::Time time,
175 : DWORD process_id,
176 : DWORD thread_id,
177 : size_t num_invocations,
178 i : const TraceBatchInvocationInfo* data) override {
179 : // TODO(anyone): Test this.
180 i : }
181 :
182 : void OnIndexedFrequency(
183 : base::Time time,
184 : DWORD process_id,
185 : DWORD thread_id,
186 E : const TraceIndexedFrequencyData* data) override {
187 E : ASSERT_EQ(process_id, kProcessId);
188 E : ASSERT_EQ(thread_id, kThreadId);
189 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
190 E : ++basic_block_frequencies;
191 E : }
192 :
193 i : MOCK_METHOD4(OnThreadName,
194 : void(base::Time time, DWORD process_id, DWORD thread_id,
195 i : const base::StringPiece& thread_name));
196 E : MOCK_METHOD3(OnDynamicSymbol,
197 : void(DWORD process_id,
198 : uint32_t symbol_id,
199 E : const base::StringPiece& symbol_name));
200 E : MOCK_METHOD3(OnSampleData,
201 : void(base::Time time,
202 : DWORD process_id,
203 E : const TraceSampleData* data));
204 E : MOCK_METHOD3(OnFunctionNameTableEntry,
205 : void(base::Time time,
206 : DWORD process_id,
207 E : const TraceFunctionNameTableEntry* data));
208 E : MOCK_METHOD3(OnStackTrace,
209 : void(base::Time time,
210 : DWORD process_id,
211 E : const TraceStackTrace* data));
212 E : MOCK_METHOD4(OnDetailedFunctionCall,
213 : void(base::Time time,
214 : DWORD process_id,
215 : DWORD thread_id,
216 E : const TraceDetailedFunctionCall* data));
217 E : MOCK_METHOD3(OnComment,
218 : void(base::Time time,
219 : DWORD process_id,
220 E : const TraceComment* data));
221 E : MOCK_METHOD3(OnProcessHeap,
222 : void(base::Time time,
223 : DWORD process_id,
224 E : const TraceProcessHeap* data));
225 :
226 : static const DWORD kProcessId;
227 : static const DWORD kThreadId;
228 : static const ModuleInformation kExeInfo;
229 : static const ModuleInformation kDllInfo;
230 : static const TraceModuleData kModuleData;
231 : static const TraceIndexedFrequencyData kIndexedFrequencyData;
232 : static const TraceIndexedFrequencyData kShortIndexedFrequencyData;
233 :
234 : EVENT_TRACE event_record_;
235 :
236 : FunctionSet function_entries;
237 : FunctionSet function_exits;
238 : ModuleSet process_attaches;
239 : ModuleSet process_detaches;
240 : ModuleSet thread_attaches;
241 : ModuleSet thread_detaches;
242 : size_t basic_block_frequencies;
243 :
244 : const void* expected_data;
245 : };
246 :
247 : const DWORD ParseEngineUnitTest::kProcessId = 0xAAAAAAAA;
248 :
249 : const DWORD ParseEngineUnitTest::kThreadId = 0xBBBBBBBB;
250 :
251 E : const ModuleInformation ParseEngineUnitTest::kExeInfo(
252 : L"file_name.exe", pe::PEFile::AbsoluteAddress(0x11111111), 0x22222222,
253 E : 0x33333333, 0x44444444);
254 :
255 E : const ModuleInformation ParseEngineUnitTest::kDllInfo(
256 : L"file_name.dll", pe::PEFile::AbsoluteAddress(0x55555555), 0x66666666,
257 E : 0x77777777, 0x88888888);
258 :
259 : const TraceModuleData ParseEngineUnitTest::kModuleData = {
260 : reinterpret_cast<ModuleAddr>(0x99999999),
261 : 0x11111111,
262 : 0x22222222,
263 : 0x33333333,
264 : L"module",
265 : L"executable" };
266 :
267 : const TraceIndexedFrequencyData ParseEngineUnitTest::kIndexedFrequencyData = {
268 : reinterpret_cast<ModuleAddr>(0x11111111),
269 : 0x22222222,
270 : 0x33333333,
271 : 0x44444444,
272 : 1,
273 : 1,
274 : common::IndexedFrequencyData::BASIC_BLOCK_ENTRY,
275 : 1,
276 : 0 };
277 :
278 : // This indexed frequency struct does not contain enough data for its implicitly
279 : // encoded length.
280 : const TraceIndexedFrequencyData
281 : ParseEngineUnitTest::kShortIndexedFrequencyData = {
282 : reinterpret_cast<ModuleAddr>(0x11111111),
283 : 0x22222222,
284 : 0x33333333,
285 : 0x44444444,
286 : 10,
287 : 1,
288 : common::IndexedFrequencyData::BASIC_BLOCK_ENTRY,
289 : 4,
290 : 0 };
291 :
292 : // A test function to show up in the trace events.
293 i : void TestFunc1() {
294 i : ::Sleep(100);
295 i : }
296 :
297 : // Another test function to show up in the trace events.
298 i : void TestFunc2() {
299 i : ::time(NULL);
300 i : }
301 :
302 E : TEST_F(ParseEngineUnitTest, ModuleInfo) {
303 E : const ModuleInformation* module_info = NULL;
304 :
305 : // Insert the module information.
306 E : ASSERT_TRUE(AddModuleInformation(kProcessId, kExeInfo));
307 E : ASSERT_TRUE(AddModuleInformation(kProcessId, kDllInfo));
308 E : ASSERT_EQ(1, processes_.size());
309 E : ASSERT_EQ(2, processes_[kProcessId].size());
310 :
311 : // Multiple identical insertions should be ok.
312 E : ASSERT_TRUE(AddModuleInformation(kProcessId, kDllInfo));
313 E : ASSERT_EQ(2, processes_[kProcessId].size());
314 :
315 : // Intersecting but not identical insertions should fail if disallowed.
316 E : ModuleInformation bad_dll_info(kDllInfo);
317 E : bad_dll_info.base_address += 100;
318 E : ASSERT_TRUE(fail_on_module_conflict_);
319 E : ASSERT_FALSE(AddModuleInformation(kProcessId, bad_dll_info));
320 E : ASSERT_EQ(2, processes_[kProcessId].size());
321 :
322 : // If conflicting module info is non-fatal, insertions should appear to
323 : // succeed but not actually happen.
324 E : fail_on_module_conflict_ = false;
325 E : ASSERT_TRUE(AddModuleInformation(kProcessId, bad_dll_info));
326 E : ASSERT_EQ(2, processes_[kProcessId].size());
327 E : fail_on_module_conflict_ = true;
328 :
329 : // Search for unknown process.
330 E : module_info = GetModuleInformation(
331 : kProcessId + 1, kExeInfo.base_address.value());
332 E : ASSERT_TRUE(module_info == NULL);
333 :
334 : // Search before exe start address
335 E : const int kBeforeOffset = -1;
336 E : module_info = GetModuleInformation(
337 : kProcessId, kExeInfo.base_address.value() + kBeforeOffset);
338 E : ASSERT_TRUE(module_info == NULL);
339 :
340 : // Search after exe end address.
341 E : const size_t kAfterOffset = kExeInfo.module_size;
342 E : module_info = GetModuleInformation(
343 : kProcessId, kExeInfo.base_address.value() + kAfterOffset);
344 E : ASSERT_TRUE(module_info == NULL);
345 :
346 : // Get exe module by start address.
347 E : const size_t kStartOffset = 0;
348 E : module_info = GetModuleInformation(
349 : kProcessId, kExeInfo.base_address.value() + kStartOffset);
350 E : ASSERT_TRUE(module_info != NULL);
351 E : ASSERT_TRUE(*module_info == kExeInfo);
352 :
353 : // Get exe module by address somewhere in the middle.
354 E : const size_t kMiddleOffset = kExeInfo.module_size / 2;
355 E : module_info = GetModuleInformation(
356 : kProcessId, kExeInfo.base_address.value() + kMiddleOffset);
357 E : ASSERT_TRUE(module_info != NULL);
358 E : ASSERT_TRUE(*module_info == kExeInfo);
359 :
360 : // Get exe module by address at the end.
361 E : const size_t kEndOffset = kExeInfo.module_size - 1;
362 E : module_info = GetModuleInformation(
363 : kProcessId, kExeInfo.base_address.value() + kEndOffset);
364 E : ASSERT_TRUE(module_info != NULL);
365 E : ASSERT_TRUE(*module_info == kExeInfo);
366 :
367 : // We only remove modules from a given process if a conflicting module is
368 : // loaded after the module has been marked as dirty. This is because (1) we
369 : // don't guarantee temporal order of all events in a process, so you
370 : // might parse a function event after seeing the module get unloaded
371 : // if the buffers are flushed in that order; and (2) because process ids may
372 : // be reused (but not concurrently) so we do want to drop stale module info
373 : // when the process has been replaced.
374 :
375 : // Get dll module by address somewhere in the middle, then remove it and
376 : // see that it's STILL found by that address.
377 E : const size_t kDllOffset = kDllInfo.module_size / 2;
378 E : module_info = GetModuleInformation(
379 : kProcessId, kDllInfo.base_address.value() + kDllOffset);
380 E : ASSERT_TRUE(module_info != NULL);
381 E : ASSERT_TRUE(*module_info == kDllInfo);
382 E : ASSERT_TRUE(RemoveModuleInformation(kProcessId, kDllInfo));
383 E : ASSERT_EQ(2, processes_[kProcessId].size());
384 E : module_info = GetModuleInformation(
385 : kProcessId, kDllInfo.base_address.value() + kDllOffset);
386 E : ASSERT_TRUE(module_info != NULL);
387 E : ASSERT_TRUE(*module_info == kDllInfo);
388 :
389 : // Add conflicting module information and see that the old module is gone.
390 E : ModuleInformation new_dll_info(kDllInfo);
391 E : new_dll_info.base_address += 4;
392 E : ASSERT_TRUE(AddModuleInformation(kProcessId, new_dll_info));
393 E : ASSERT_EQ(2, processes_[kProcessId].size());
394 E : module_info = GetModuleInformation(
395 : kProcessId, kDllInfo.base_address.value());
396 E : ASSERT_TRUE(module_info == NULL);
397 E : module_info = GetModuleInformation(
398 : kProcessId, new_dll_info.base_address.value());
399 E : ASSERT_TRUE(module_info != NULL);
400 E : ASSERT_TRUE(*module_info == new_dll_info);
401 E : }
402 :
403 E : TEST_F(ParseEngineUnitTest, UnhandledEvent) {
404 E : EVENT_TRACE local_record = {};
405 E : ASSERT_FALSE(DispatchEvent(&local_record));
406 :
407 E : local_record.Header.ProcessId = kProcessId;
408 E : local_record.Header.ThreadId = kThreadId;
409 E : local_record.Header.Guid = kCallTraceEventClass;
410 E : local_record.Header.Class.Type = 0xFF; // Invalid value.
411 E : ASSERT_TRUE(DispatchEvent(&local_record));
412 E : ASSERT_TRUE(error_occurred());
413 E : }
414 :
415 E : TEST_F(ParseEngineUnitTest, FunctionEntryEvents) {
416 E : TraceEnterEventData event_data = {};
417 E : event_data.function = &TestFunc1;
418 E : expected_data = &event_data;
419 :
420 E : ASSERT_NO_FATAL_FAILURE(
421 E : DispatchEventData(TRACE_ENTER_EVENT, &event_data, sizeof(event_data)));
422 E : ASSERT_FALSE(error_occurred());
423 E : ASSERT_NO_FATAL_FAILURE(
424 E : DispatchEventData(TRACE_ENTER_EVENT, &event_data, sizeof(event_data)));
425 E : ASSERT_FALSE(error_occurred());
426 E : ASSERT_EQ(function_entries.size(), 2);
427 E : ASSERT_EQ(function_entries.count(&TestFunc1), 2);
428 :
429 : // Check for short event data.
430 E : ASSERT_NO_FATAL_FAILURE(
431 : DispatchEventData(TRACE_ENTER_EVENT,
432 : &event_data,
433 E : sizeof(TraceEnterEventData) - 1));
434 E : ASSERT_TRUE(error_occurred());
435 E : }
436 :
437 E : TEST_F(ParseEngineUnitTest, FunctionExitEvents) {
438 E : TraceExitEventData event_data = {};
439 E : event_data.function = &TestFunc2;
440 E : expected_data = &event_data;
441 :
442 E : ASSERT_NO_FATAL_FAILURE(
443 E : DispatchEventData(TRACE_EXIT_EVENT, &event_data, sizeof(event_data)));
444 E : ASSERT_FALSE(error_occurred());
445 E : ASSERT_NO_FATAL_FAILURE(
446 E : DispatchEventData(TRACE_EXIT_EVENT, &event_data, sizeof(event_data)));
447 E : ASSERT_FALSE(error_occurred());
448 E : ASSERT_EQ(function_exits.size(), 2);
449 E : ASSERT_EQ(function_exits.count(&TestFunc2), 2);
450 :
451 : // Check for short event data.
452 E : ASSERT_NO_FATAL_FAILURE(
453 : DispatchEventData(TRACE_EXIT_EVENT,
454 : &event_data,
455 E : sizeof(TraceEnterEventData) - 1));
456 E : ASSERT_TRUE(error_occurred());
457 E : }
458 :
459 E : TEST_F(ParseEngineUnitTest, BatchFunctionEntry) {
460 E : uint8_t raw_data[sizeof(TraceBatchEnterData) +
461 : 4 * sizeof(TraceEnterEventData)] = {};
462 E : TraceBatchEnterData& event_data =
463 : *reinterpret_cast<TraceBatchEnterData*>(&raw_data);
464 E : event_data.thread_id = kThreadId;
465 E : event_data.num_calls = 5;
466 E : event_data.calls[0].function = &TestFunc1;
467 E : event_data.calls[1].function = &TestFunc2;
468 E : event_data.calls[2].function = &TestFunc1;
469 E : event_data.calls[3].function = &TestFunc2;
470 E : event_data.calls[4].function = NULL;
471 E : expected_data = &raw_data;
472 :
473 E : ASSERT_NO_FATAL_FAILURE(
474 E : DispatchEventData(TRACE_BATCH_ENTER, &raw_data, sizeof(raw_data)));
475 E : ASSERT_FALSE(error_occurred());
476 E : ASSERT_NO_FATAL_FAILURE(
477 E : DispatchEventData(TRACE_BATCH_ENTER, &raw_data, sizeof(raw_data)));
478 E : ASSERT_FALSE(error_occurred());
479 E : ASSERT_EQ(function_entries.size(), 8);
480 E : ASSERT_EQ(function_entries.count(&TestFunc1), 4);
481 E : ASSERT_EQ(function_entries.count(&TestFunc2), 4);
482 :
483 : // Check for short event header.
484 E : ASSERT_NO_FATAL_FAILURE(
485 : DispatchEventData(TRACE_BATCH_ENTER,
486 : &raw_data,
487 E : FIELD_OFFSET(TraceBatchEnterData, num_calls)));
488 E : ASSERT_TRUE(error_occurred());
489 :
490 : // Check for short event tail (remove the empty record + one byte).
491 E : set_error_occurred(false);
492 E : ASSERT_NO_FATAL_FAILURE(
493 : DispatchEventData(TRACE_BATCH_ENTER,
494 : &raw_data,
495 E : sizeof(raw_data) - sizeof(TraceEnterEventData) - 1));
496 E : ASSERT_TRUE(error_occurred());
497 E : }
498 :
499 E : TEST_F(ParseEngineUnitTest, ProcessAttachIncomplete) {
500 E : TraceModuleData incomplete(kModuleData);
501 E : incomplete.module_base_addr = NULL;
502 :
503 : // No error should be reported for NULL module addr, instead the record
504 : // should be ignored.
505 E : expected_data = &kModuleData;
506 E : ASSERT_NO_FATAL_FAILURE(
507 : DispatchEventData(TRACE_PROCESS_ATTACH_EVENT,
508 : &incomplete,
509 E : sizeof(incomplete)));
510 :
511 E : ASSERT_FALSE(error_occurred());
512 E : ASSERT_EQ(process_attaches.size(), 0);
513 E : }
514 :
515 E : TEST_F(ParseEngineUnitTest, ProcessAttach) {
516 E : expected_data = &kModuleData;
517 :
518 E : ASSERT_NO_FATAL_FAILURE(
519 : DispatchEventData(TRACE_PROCESS_ATTACH_EVENT,
520 : &kModuleData,
521 E : sizeof(kModuleData)));
522 E : ASSERT_FALSE(error_occurred());
523 E : ASSERT_EQ(process_attaches.size(), 1);
524 :
525 : // Check for short module event.
526 E : ASSERT_NO_FATAL_FAILURE(
527 : DispatchEventData(TRACE_PROCESS_ATTACH_EVENT,
528 : &kModuleData,
529 E : sizeof(kModuleData) - 1));
530 E : ASSERT_TRUE(error_occurred());
531 E : }
532 :
533 E : TEST_F(ParseEngineUnitTest, ProcessDetach) {
534 E : expected_data = &kModuleData;
535 :
536 E : ASSERT_NO_FATAL_FAILURE(
537 : DispatchEventData(TRACE_PROCESS_DETACH_EVENT,
538 : &kModuleData,
539 E : sizeof(kModuleData)));
540 E : ASSERT_FALSE(error_occurred());
541 E : ASSERT_EQ(process_detaches.size(), 1);
542 :
543 : // Check for short module event.
544 E : ASSERT_NO_FATAL_FAILURE(
545 : DispatchEventData(TRACE_PROCESS_DETACH_EVENT,
546 : &kModuleData,
547 E : sizeof(kModuleData) - 1));
548 E : ASSERT_TRUE(error_occurred());
549 E : }
550 :
551 E : TEST_F(ParseEngineUnitTest, ThreadAttach) {
552 E : expected_data = &kModuleData;
553 :
554 E : ASSERT_NO_FATAL_FAILURE(
555 : DispatchEventData(TRACE_THREAD_ATTACH_EVENT,
556 : &kModuleData,
557 E : sizeof(kModuleData)));
558 E : ASSERT_FALSE(error_occurred());
559 E : ASSERT_EQ(thread_attaches.size(), 1);
560 :
561 : // Check for short module event.
562 E : ASSERT_NO_FATAL_FAILURE(
563 : DispatchEventData(TRACE_THREAD_ATTACH_EVENT,
564 : &kModuleData,
565 E : sizeof(kModuleData) - 1));
566 E : ASSERT_TRUE(error_occurred());
567 E : }
568 :
569 E : TEST_F(ParseEngineUnitTest, ThreadDetach) {
570 E : expected_data = &kModuleData;
571 :
572 E : ASSERT_NO_FATAL_FAILURE(
573 : DispatchEventData(TRACE_THREAD_DETACH_EVENT,
574 : &kModuleData,
575 E : sizeof(kModuleData)));
576 E : ASSERT_FALSE(error_occurred());
577 E : ASSERT_EQ(thread_detaches.size(), 1);
578 :
579 : // Check for short module event.
580 E : ASSERT_NO_FATAL_FAILURE(
581 : DispatchEventData(TRACE_THREAD_DETACH_EVENT,
582 : &kModuleData,
583 E : sizeof(kModuleData) - 1));
584 E : ASSERT_TRUE(error_occurred());
585 E : }
586 :
587 E : TEST_F(ParseEngineUnitTest, IndexedFrequencyTooSmallForHeader) {
588 E : ASSERT_NO_FATAL_FAILURE(
589 : DispatchEventData(TRACE_INDEXED_FREQUENCY,
590 : &kIndexedFrequencyData,
591 E : sizeof(kIndexedFrequencyData) - 1));
592 :
593 E : ASSERT_TRUE(error_occurred());
594 E : ASSERT_EQ(basic_block_frequencies, 0);
595 E : }
596 :
597 E : TEST_F(ParseEngineUnitTest, IndexedFrequencyTooSmallForContents) {
598 E : ASSERT_NO_FATAL_FAILURE(
599 : DispatchEventData(TRACE_INDEXED_FREQUENCY,
600 : &kShortIndexedFrequencyData,
601 E : sizeof(kShortIndexedFrequencyData)));
602 :
603 E : ASSERT_TRUE(error_occurred());
604 E : ASSERT_EQ(basic_block_frequencies, 0);
605 E : }
606 :
607 E : TEST_F(ParseEngineUnitTest, IndexedFrequency) {
608 E : expected_data = &kIndexedFrequencyData;
609 E : ASSERT_NO_FATAL_FAILURE(
610 : DispatchEventData(TRACE_INDEXED_FREQUENCY,
611 : &kIndexedFrequencyData,
612 E : sizeof(kIndexedFrequencyData)));
613 E : ASSERT_FALSE(error_occurred());
614 E : ASSERT_EQ(basic_block_frequencies, 1);
615 E : }
616 :
617 E : TEST_F(ParseEngineUnitTest, DynamicSymbol) {
618 : static const char kSymbolName[] = "aDynamicSymbol";
619 E : const uint32_t kSymbolId = 0x17459A;
620 : char data[FIELD_OFFSET(TraceDynamicSymbol, symbol_name) +
621 : sizeof(kSymbolName)];
622 E : TraceDynamicSymbol* symbol = reinterpret_cast<TraceDynamicSymbol*>(data);
623 E : symbol->symbol_id = kSymbolId;
624 E : ::memcpy(symbol->symbol_name, kSymbolName, sizeof(kSymbolName));
625 :
626 : // Dispatch a valid dynamic symbol record.
627 E : EXPECT_CALL(*this,
628 : OnDynamicSymbol(kProcessId, kSymbolId, base::StringPiece(kSymbolName)));
629 E : ASSERT_NO_FATAL_FAILURE(
630 E : DispatchEventData(TRACE_DYNAMIC_SYMBOL, data, sizeof(data)));
631 E : ASSERT_FALSE(error_occurred());
632 :
633 : // Dispatch a short symbol record, make sure we err out.
634 E : ASSERT_NO_FATAL_FAILURE(
635 : DispatchEventData(TRACE_DYNAMIC_SYMBOL,
636 : data,
637 E : FIELD_OFFSET(TraceDynamicSymbol, symbol_name) - 1));
638 E : ASSERT_TRUE(error_occurred());
639 E : }
640 :
641 E : TEST_F(ParseEngineUnitTest, SampleData) {
642 E : const uint32_t kBucketCount = 42;
643 E : char buffer[FIELD_OFFSET(TraceSampleData, buckets) +
644 : kBucketCount * sizeof(uint32_t)] = {};
645 E : TraceSampleData* data = reinterpret_cast<TraceSampleData*>(buffer);
646 :
647 E : data->module_base_addr = reinterpret_cast<ModuleAddr>(0x01000000);
648 E : data->module_size = 32 * 1024 * 1024;
649 E : data->module_checksum = 0xDEADF00D;
650 E : data->module_time_date_stamp = 0x12345678;
651 E : data->bucket_size = 4;
652 E : data->bucket_start = reinterpret_cast<ModuleAddr>(0x01001000);
653 E : data->bucket_count = kBucketCount;
654 E : data->sampling_start_time = 0x0102030405060708;
655 E : data->sampling_end_time = 0x0203040506070809;
656 E : data->sampling_interval = 0x10000;
657 :
658 E : for (size_t i = 0; i < kBucketCount; ++i)
659 E : data->buckets[i] = i;
660 :
661 E : EXPECT_CALL(*this, OnSampleData(_, kProcessId, data));
662 E : ASSERT_NO_FATAL_FAILURE(
663 E : DispatchEventData(TRACE_SAMPLE_DATA, data, sizeof(buffer)));
664 E : ASSERT_FALSE(error_occurred());
665 :
666 : // Dispatch a malformed record and make sure the parser errors.
667 E : ASSERT_NO_FATAL_FAILURE(
668 E : DispatchEventData(TRACE_SAMPLE_DATA, data, sizeof(buffer) - 1));
669 E : ASSERT_TRUE(error_occurred());
670 E : }
671 :
672 E : TEST_F(ParseEngineUnitTest, FunctionNameTableEntry) {
673 E : const char kDummyFunctionName[] = "DummyFunction";
674 E : char buffer[FIELD_OFFSET(TraceFunctionNameTableEntry, name) +
675 : arraysize(kDummyFunctionName)] = {};
676 : TraceFunctionNameTableEntry* data =
677 E : reinterpret_cast<TraceFunctionNameTableEntry*>(buffer);
678 :
679 E : data->function_id = 37;
680 E : data->name_length = arraysize(kDummyFunctionName);
681 E : base::snprintf(data->name, data->name_length, kDummyFunctionName);
682 :
683 E : EXPECT_CALL(*this, OnFunctionNameTableEntry(_, kProcessId, data));
684 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
685 E : TRACE_FUNCTION_NAME_TABLE_ENTRY, data, sizeof(buffer)));
686 E : ASSERT_FALSE(error_occurred());
687 :
688 : // Dispatch a malformed record and make sure the parser errors.
689 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
690 E : TRACE_FUNCTION_NAME_TABLE_ENTRY, data, sizeof(buffer) - 1));
691 E : ASSERT_TRUE(error_occurred());
692 E : }
693 :
694 E : TEST_F(ParseEngineUnitTest, StackTrace) {
695 E : char buffer[FIELD_OFFSET(TraceStackTrace, frames) +
696 : sizeof(void*) * 4] = {};
697 : TraceStackTrace* data =
698 E : reinterpret_cast<TraceStackTrace*>(buffer);
699 :
700 E : data->stack_trace_id = 42;
701 E : data->num_frames = 4;
702 E : data->frames[0] = reinterpret_cast<void*>(0xDEADBEEF);
703 E : data->frames[1] = reinterpret_cast<void*>(0x900DF00D);
704 E : data->frames[2] = reinterpret_cast<void*>(0xCAFEBABE);
705 E : data->frames[3] = reinterpret_cast<void*>(0x00031337);
706 :
707 E : EXPECT_CALL(*this, OnStackTrace(_, kProcessId, data));
708 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
709 E : TRACE_STACK_TRACE, data, sizeof(buffer)));
710 E : ASSERT_FALSE(error_occurred());
711 :
712 : // Dispatch a malformed record and make sure the parser errors.
713 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
714 E : TRACE_STACK_TRACE, data, sizeof(buffer) - 1));
715 E : ASSERT_TRUE(error_occurred());
716 E : }
717 :
718 E : TEST_F(ParseEngineUnitTest, DetailedFunctionCall) {
719 : const uint8_t kDummyArguments[] = {
720 E : 0x02,
721 E : 0x00,
722 E : 0x00,
723 E : 0x00, // 2 aguments
724 E : 0x04,
725 E : 0x00,
726 E : 0x00,
727 E : 0x00, // Argument 0 length 4.
728 E : 0x01,
729 E : 0x00,
730 E : 0x00,
731 E : 0x00, // Argument 1 length 1.
732 E : 0xDE,
733 E : 0xAD,
734 E : 0xBE,
735 E : 0xEF, // Argument 0: 0xDEADBEEF.
736 E : 'A' // Argument 1: 'A'
737 : };
738 E : char buffer[FIELD_OFFSET(TraceDetailedFunctionCall, argument_data) +
739 : arraysize(kDummyArguments)] = {};
740 : TraceDetailedFunctionCall* data =
741 E : reinterpret_cast<TraceDetailedFunctionCall*>(buffer);
742 :
743 E : data->timestamp = 0x0102030405060708;
744 E : data->function_id = 37;
745 E : data->argument_data_size = arraysize(kDummyArguments);
746 E : ::memcpy(data->argument_data, kDummyArguments, arraysize(kDummyArguments));
747 :
748 E : EXPECT_CALL(*this, OnDetailedFunctionCall(_, kProcessId, kThreadId, data));
749 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
750 E : TRACE_DETAILED_FUNCTION_CALL, data, sizeof(buffer)));
751 E : ASSERT_FALSE(error_occurred());
752 :
753 : // Dispatch a malformed record and make sure the parser errors.
754 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
755 E : TRACE_DETAILED_FUNCTION_CALL, data, sizeof(buffer) - 1));
756 E : ASSERT_TRUE(error_occurred());
757 E : }
758 :
759 E : TEST_F(ParseEngineUnitTest, Comment) {
760 E : const char kDummyComment[] = "This is a comment!";
761 E : char buffer[FIELD_OFFSET(TraceComment, comment) +
762 : arraysize(kDummyComment)] = {};
763 : TraceComment* data =
764 E : reinterpret_cast<TraceComment*>(buffer);
765 :
766 E : data->comment_size = arraysize(kDummyComment);
767 E : ::memcpy(data->comment, kDummyComment, arraysize(kDummyComment));
768 :
769 E : EXPECT_CALL(*this, OnComment(_, kProcessId, data));
770 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
771 E : TRACE_COMMENT, data, sizeof(buffer)));
772 E : ASSERT_FALSE(error_occurred());
773 :
774 : // Dispatch a malformed record and make sure the parser errors.
775 E : ASSERT_NO_FATAL_FAILURE(DispatchEventData(
776 E : TRACE_COMMENT, data, sizeof(buffer) - 1));
777 E : ASSERT_TRUE(error_occurred());
778 E : }
779 :
780 E : TEST_F(ParseEngineUnitTest, ProcessHeap) {
781 E : TraceProcessHeap proc_heap = {0xF005BA11};
782 :
783 E : EXPECT_CALL(*this, OnProcessHeap(_, kProcessId, &proc_heap));
784 E : ASSERT_NO_FATAL_FAILURE(
785 E : DispatchEventData(TRACE_PROCESS_HEAP, &proc_heap, sizeof(proc_heap)));
786 E : ASSERT_FALSE(error_occurred());
787 :
788 : // Dispatch a malformed record and make sure the parser errors.
789 E : ASSERT_NO_FATAL_FAILURE(
790 E : DispatchEventData(TRACE_PROCESS_HEAP, &proc_heap, sizeof(proc_heap) - 1));
791 E : ASSERT_TRUE(error_occurred());
792 E : }
793 :
794 : } // namespace
|