1 : // Copyright 2012 Google Inc.
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 "gmock/gmock.h"
26 : #include "gtest/gtest.h"
27 : #include "syzygy/trace/parse/parser.h"
28 :
29 : using trace::parser::Parser;
30 : using trace::parser::ParseEngine;
31 : using trace::parser::ParseEventHandlerImpl;
32 : using trace::parser::ModuleInformation;
33 :
34 : namespace {
35 :
36 : typedef std::multiset<FuncAddr> FunctionSet;
37 : typedef std::vector<TraceModuleData> ModuleSet;
38 :
39 : class ParseEngineUnitTest
40 : : public testing::Test,
41 : public ParseEngine,
42 : public ParseEventHandlerImpl {
43 : public:
44 : ParseEngineUnitTest()
45 : : ParseEngine("Test", true),
46 : basic_block_frequencies(0),
47 E : expected_data(NULL) {
48 E : set_event_handler(this);
49 E : }
50 :
51 E : ~ParseEngineUnitTest() {
52 E : }
53 :
54 :
55 i : bool IsRecognizedTraceFile(const FilePath& trace_file_path) OVERRIDE {
56 i : return true;
57 i : }
58 :
59 i : bool OpenTraceFile(const FilePath& trace_file_path) OVERRIDE {
60 i : return true;
61 i : }
62 :
63 i : virtual bool ConsumeAllEvents() {
64 i : return true;
65 i : }
66 :
67 i : virtual bool CloseAllTraceFiles() {
68 i : return true;
69 i : }
70 :
71 : // ParseEventHander methods.
72 :
73 : virtual void OnProcessStarted(base::Time time,
74 : DWORD process_id,
75 i : const TraceSystemInfo* data) {
76 i : ASSERT_EQ(process_id, kProcessId);
77 i : }
78 :
79 i : virtual void OnProcessEnded(base::Time time, DWORD process_id) {
80 i : ASSERT_EQ(process_id, kProcessId);
81 i : }
82 :
83 : virtual void OnFunctionEntry(base::Time time,
84 : DWORD process_id,
85 : DWORD thread_id,
86 E : const TraceEnterExitEventData* data) {
87 E : ASSERT_EQ(process_id, kProcessId);
88 E : ASSERT_EQ(thread_id, kThreadId);
89 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
90 E : EXPECT_TRUE(data->function != NULL);
91 E : function_entries.insert(data->function);
92 E : }
93 :
94 : virtual void OnFunctionExit(base::Time time,
95 : DWORD process_id,
96 : DWORD thread_id,
97 E : const TraceEnterExitEventData* data) {
98 E : ASSERT_EQ(process_id, kProcessId);
99 E : ASSERT_EQ(thread_id, kThreadId);
100 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
101 E : EXPECT_TRUE(data->function != NULL);
102 E : function_exits.insert(data->function);
103 E : }
104 :
105 : virtual void OnBatchFunctionEntry(base::Time time,
106 : DWORD process_id,
107 : DWORD thread_id,
108 E : const TraceBatchEnterData* data) {
109 E : ASSERT_EQ(process_id, kProcessId);
110 E : ASSERT_EQ(thread_id, kThreadId);
111 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
112 E : for (size_t i = 0; i < data->num_calls; ++i) {
113 E : function_entries.insert(data->calls[i].function);
114 E : }
115 E : }
116 :
117 : virtual void OnProcessAttach(base::Time time,
118 : DWORD process_id,
119 : DWORD thread_id,
120 E : const TraceModuleData* data) {
121 E : ASSERT_EQ(process_id, kProcessId);
122 E : ASSERT_EQ(thread_id, kThreadId);
123 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
124 E : process_attaches.push_back(*data);
125 E : }
126 :
127 : virtual void OnProcessDetach(base::Time time,
128 : DWORD process_id,
129 : DWORD thread_id,
130 E : const TraceModuleData* data) {
131 E : ASSERT_EQ(process_id, kProcessId);
132 E : ASSERT_EQ(thread_id, kThreadId);
133 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
134 E : process_detaches.push_back(*data);
135 E : }
136 :
137 : virtual void OnThreadAttach(base::Time time,
138 : DWORD process_id,
139 : DWORD thread_id,
140 E : const TraceModuleData* data) {
141 E : ASSERT_EQ(process_id, kProcessId);
142 E : ASSERT_EQ(thread_id, kThreadId);
143 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
144 E : thread_attaches.push_back(*data);
145 E : }
146 :
147 : // Issued for DLL_THREAD_DETACH on an instrumented module.
148 : virtual void OnThreadDetach(base::Time time,
149 : DWORD process_id,
150 : DWORD thread_id,
151 E : const TraceModuleData* data) {
152 E : ASSERT_EQ(process_id, kProcessId);
153 E : ASSERT_EQ(thread_id, kThreadId);
154 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
155 E : thread_detaches.push_back(*data);
156 E : }
157 :
158 : virtual void OnBasicBlockFrequency(
159 : base::Time time,
160 : DWORD process_id,
161 : DWORD thread_id,
162 E : const TraceBasicBlockFrequencyData* data) {
163 E : ASSERT_EQ(process_id, kProcessId);
164 E : ASSERT_EQ(thread_id, kThreadId);
165 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
166 E : ++basic_block_frequencies;
167 E : }
168 :
169 : static const DWORD kProcessId;
170 : static const DWORD kThreadId;
171 : static const ModuleInformation kExeInfo;
172 : static const ModuleInformation kDllInfo;
173 : static const TraceModuleData kModuleData;
174 : static const TraceBasicBlockFrequencyData kBasicBlockFrequencyData;
175 : static const TraceBasicBlockFrequencyData kShortBasicBlockFrequencyData;
176 :
177 : FunctionSet function_entries;
178 : FunctionSet function_exits;
179 : ModuleSet process_attaches;
180 : ModuleSet process_detaches;
181 : ModuleSet thread_attaches;
182 : ModuleSet thread_detaches;
183 : size_t basic_block_frequencies;
184 :
185 : const void* expected_data;
186 : };
187 :
188 : const DWORD ParseEngineUnitTest::kProcessId = 0xAAAAAAAA;
189 :
190 : const DWORD ParseEngineUnitTest::kThreadId = 0xBBBBBBBB;
191 :
192 E : const ModuleInformation ParseEngineUnitTest::kExeInfo = {
193 E : 0x11111111, 0x22222222, 0x33333333, 0x44444444, L"file_name.exe" };
194 :
195 E : const ModuleInformation ParseEngineUnitTest::kDllInfo = {
196 E : 0x55555555, 0x66666666, 0x77777777, 0x88888888, L"file_name.dll" };
197 :
198 : const TraceModuleData ParseEngineUnitTest::kModuleData = {
199 : reinterpret_cast<ModuleAddr>(0x99999999),
200 : 0x11111111,
201 : 0x22222222,
202 : 0x33333333,
203 : L"module",
204 : L"executable" };
205 :
206 : const TraceBasicBlockFrequencyData
207 : ParseEngineUnitTest::kBasicBlockFrequencyData = {
208 : reinterpret_cast<ModuleAddr>(0x11111111),
209 : 0x22222222,
210 : 0x33333333,
211 : 0x44444444,
212 : 1,
213 : 1,
214 : 0 };
215 :
216 : // This basic-block frequency struct does not contain enough data for its
217 : // implicitly encoded length.
218 : const TraceBasicBlockFrequencyData
219 : ParseEngineUnitTest::kShortBasicBlockFrequencyData = {
220 : reinterpret_cast<ModuleAddr>(0x11111111),
221 : 0x22222222,
222 : 0x33333333,
223 : 0x44444444,
224 : 4,
225 : 10,
226 : 0 };
227 :
228 : // A test function to show up in the trace events.
229 i : void TestFunc1() {
230 i : ::Sleep(100);
231 i : }
232 :
233 : // Another test function to show up in the trace events.
234 i : void TestFunc2() {
235 i : ::time(NULL);
236 i : }
237 :
238 E : TEST_F(ParseEngineUnitTest, ModuleInfo) {
239 E : const ModuleInformation* module_info = NULL;
240 :
241 : // Insert the module information.
242 E : ASSERT_TRUE(AddModuleInformation(kProcessId, kExeInfo));
243 E : ASSERT_TRUE(AddModuleInformation(kProcessId, kDllInfo));
244 E : ASSERT_EQ(1, processes_.size());
245 E : ASSERT_EQ(2, processes_[kProcessId].size());
246 :
247 : // Multiple identical insertions should be ok.
248 E : ASSERT_TRUE(AddModuleInformation(kProcessId, kDllInfo));
249 E : ASSERT_EQ(2, processes_[kProcessId].size());
250 :
251 : // Intersecting but not identical insertions should fail if disallowed.
252 E : ModuleInformation bad_dll_info(kDllInfo);
253 E : bad_dll_info.base_address += 100;
254 E : ASSERT_TRUE(fail_on_module_conflict_);
255 E : ASSERT_FALSE(AddModuleInformation(kProcessId, bad_dll_info));
256 E : ASSERT_EQ(2, processes_[kProcessId].size());
257 :
258 : // If conflicting module info is non-fatal, insertions should appear to
259 : // succeed but not actually happen.
260 E : fail_on_module_conflict_ = false;
261 E : ASSERT_TRUE(AddModuleInformation(kProcessId, bad_dll_info));
262 E : ASSERT_EQ(2, processes_[kProcessId].size());
263 E : fail_on_module_conflict_ = true;
264 :
265 : // Search for unknown process.
266 E : module_info = GetModuleInformation(kProcessId + 1, kExeInfo.base_address);
267 E : ASSERT_TRUE(module_info == NULL);
268 :
269 : // Search before exe start address
270 E : const int kBeforeOffset = -1;
271 : module_info = GetModuleInformation(kProcessId,
272 E : kExeInfo.base_address + kBeforeOffset);
273 E : ASSERT_TRUE(module_info == NULL);
274 :
275 : // Search after exe end address.
276 E : const size_t kAfterOffset = kExeInfo.module_size;
277 : module_info = GetModuleInformation(kProcessId,
278 E : kExeInfo.base_address + kAfterOffset);
279 E : ASSERT_TRUE(module_info == NULL);
280 :
281 : // Get exe module by start address.
282 E : const size_t kStartOffset = 0;
283 : module_info = GetModuleInformation(kProcessId,
284 E : kExeInfo.base_address + kStartOffset);
285 E : ASSERT_TRUE(module_info != NULL);
286 E : ASSERT_TRUE(*module_info == kExeInfo);
287 :
288 : // Get exe module by address somewhere in the middle.
289 E : const size_t kMiddleOffset = kExeInfo.module_size / 2;
290 : module_info = GetModuleInformation(kProcessId,
291 E : kExeInfo.base_address + kMiddleOffset);
292 E : ASSERT_TRUE(module_info != NULL);
293 E : ASSERT_TRUE(*module_info == kExeInfo);
294 :
295 : // Get exe module by address at the end.
296 E : const size_t kEndOffset = kExeInfo.module_size - 1;
297 : module_info = GetModuleInformation(kProcessId,
298 E : kExeInfo.base_address + kEndOffset);
299 E : ASSERT_TRUE(module_info != NULL);
300 E : ASSERT_TRUE(*module_info == kExeInfo);
301 :
302 : // We only remove modules from a given process if a conflicting module is
303 : // loaded after the module has been marked as dirty. This is because (1) we
304 : // don't guarantee temporal order of all events in a process, so you
305 : // might parse a function event after seeing the module get unloaded
306 : // if the buffers are flushed in that order; and (2) because process ids may
307 : // be reused (but not concurrently) so we do want to drop stale module info
308 : // when the process has been replaced.
309 :
310 : // Get dll module by address somewhere in the middle, then remove it and
311 : // see that it's STILL found by that address.
312 E : const size_t kDllOffset = kDllInfo.module_size / 2;
313 : module_info = GetModuleInformation(kProcessId,
314 E : kDllInfo.base_address + kDllOffset);
315 E : ASSERT_TRUE(module_info != NULL);
316 E : ASSERT_TRUE(*module_info == kDllInfo);
317 E : ASSERT_TRUE(RemoveModuleInformation(kProcessId, kDllInfo));
318 E : ASSERT_EQ(2, processes_[kProcessId].size());
319 : module_info = GetModuleInformation(kProcessId,
320 E : kDllInfo.base_address + kDllOffset);
321 E : ASSERT_TRUE(module_info != NULL);
322 E : ASSERT_TRUE(*module_info == kDllInfo);
323 :
324 : // Add conflicting module information and see that the old module is gone.
325 E : ModuleInformation new_dll_info = kDllInfo;
326 E : new_dll_info.base_address += 4;
327 E : ASSERT_TRUE(AddModuleInformation(kProcessId, new_dll_info));
328 E : ASSERT_EQ(2, processes_[kProcessId].size());
329 E : module_info = GetModuleInformation(kProcessId, kDllInfo.base_address);
330 E : ASSERT_TRUE(module_info == NULL);
331 E : module_info = GetModuleInformation(kProcessId, new_dll_info.base_address);
332 E : ASSERT_TRUE(module_info != NULL);
333 E : ASSERT_TRUE(*module_info == new_dll_info);
334 E : }
335 :
336 E : TEST_F(ParseEngineUnitTest, UnhandledEvent) {
337 E : EVENT_TRACE event_record = {};
338 E : ASSERT_FALSE(DispatchEvent(&event_record));
339 :
340 E : event_record.Header.ProcessId = kProcessId;
341 E : event_record.Header.ThreadId = kThreadId;
342 E : event_record.Header.Guid = kCallTraceEventClass;
343 E : event_record.Header.Class.Type = 0xFF; // Invalid value.
344 E : ASSERT_TRUE(DispatchEvent(&event_record));
345 E : ASSERT_TRUE(error_occurred());
346 E : }
347 :
348 E : TEST_F(ParseEngineUnitTest, FunctionEntryEvents) {
349 E : TraceEnterEventData event_data = {};
350 E : event_data.function = &TestFunc1;
351 E : expected_data = &event_data;
352 :
353 E : EVENT_TRACE event_record = {};
354 E : event_record.Header.ProcessId = kProcessId;
355 E : event_record.Header.ThreadId = kThreadId;
356 E : event_record.Header.Guid = kCallTraceEventClass;
357 E : event_record.Header.Class.Type = TRACE_ENTER_EVENT;
358 E : event_record.MofData = &event_data;
359 E : event_record.MofLength = sizeof(event_data);
360 :
361 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
362 E : ASSERT_FALSE(error_occurred());
363 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
364 E : ASSERT_FALSE(error_occurred());
365 E : ASSERT_EQ(function_entries.size(), 2);
366 E : ASSERT_EQ(function_entries.count(&TestFunc1), 2);
367 :
368 : // Check for short event header.
369 E : event_record.MofLength = FIELD_OFFSET(TraceEnterEventData, function);
370 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
371 E : ASSERT_TRUE(error_occurred());
372 :
373 : // Check for short event tail.
374 E : set_error_occurred(false);
375 E : event_data.num_traces = 20;
376 E : event_record.MofLength = FIELD_OFFSET(TraceEnterEventData, traces);
377 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
378 E : ASSERT_TRUE(error_occurred());
379 E : }
380 :
381 E : TEST_F(ParseEngineUnitTest, FunctionExitEvents) {
382 E : TraceExitEventData event_data = {};
383 E : event_data.function = &TestFunc2;
384 E : expected_data = &event_data;
385 :
386 E : EVENT_TRACE event_record = {};
387 E : event_record.Header.ProcessId = kProcessId;
388 E : event_record.Header.ThreadId = kThreadId;
389 E : event_record.Header.Guid = kCallTraceEventClass;
390 E : event_record.Header.Class.Type = TRACE_EXIT_EVENT;
391 E : event_record.MofData = &event_data;
392 E : event_record.MofLength = sizeof(event_data);
393 :
394 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
395 E : ASSERT_FALSE(error_occurred());
396 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
397 E : ASSERT_FALSE(error_occurred());
398 E : ASSERT_EQ(function_exits.size(), 2);
399 E : ASSERT_EQ(function_exits.count(&TestFunc2), 2);
400 :
401 : // Check for short event header.
402 E : event_record.MofLength = FIELD_OFFSET(TraceEnterEventData, function);
403 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
404 E : ASSERT_TRUE(error_occurred());
405 :
406 : // Check for short event tail.
407 E : set_error_occurred(false);
408 E : event_data.num_traces = 20;
409 E : event_record.MofLength = FIELD_OFFSET(TraceExitEventData, traces);
410 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
411 E : ASSERT_TRUE(error_occurred());
412 E : }
413 :
414 E : TEST_F(ParseEngineUnitTest, BatchFunctionEntry) {
415 E : uint8 raw_data[sizeof(TraceBatchEnterData) + 4 * sizeof(FuncCall)] = {};
416 : TraceBatchEnterData& event_data =
417 E : *reinterpret_cast<TraceBatchEnterData*>(&raw_data);
418 E : event_data.thread_id = kThreadId;
419 E : event_data.num_calls = 5;
420 E : event_data.calls[0].function = &TestFunc1;
421 E : event_data.calls[1].function = &TestFunc2;
422 E : event_data.calls[2].function = &TestFunc1;
423 E : event_data.calls[3].function = &TestFunc2;
424 E : event_data.calls[4].function = NULL;
425 E : expected_data = &raw_data;
426 :
427 E : EVENT_TRACE event_record = {};
428 E : event_record.Header.ProcessId = kProcessId;
429 E : event_record.Header.ThreadId = kThreadId;
430 E : event_record.Header.Guid = kCallTraceEventClass;
431 E : event_record.Header.Class.Type = TRACE_BATCH_ENTER;
432 E : event_record.MofData = &raw_data;
433 E : event_record.MofLength = sizeof(raw_data);
434 :
435 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
436 E : ASSERT_FALSE(error_occurred());
437 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
438 E : ASSERT_FALSE(error_occurred());
439 E : ASSERT_EQ(function_entries.size(), 8);
440 E : ASSERT_EQ(function_entries.count(&TestFunc1), 4);
441 E : ASSERT_EQ(function_entries.count(&TestFunc2), 4);
442 :
443 : // Check for short event header.
444 E : event_record.MofLength = FIELD_OFFSET(TraceBatchEnterData, num_calls);
445 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
446 E : ASSERT_TRUE(error_occurred());
447 :
448 : // Check for short event tail (remove the empty record + one byte).
449 E : set_error_occurred(false);
450 E : event_record.MofLength = sizeof(raw_data) - sizeof(FuncCall) - 1;
451 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
452 E : ASSERT_TRUE(error_occurred());
453 E : }
454 :
455 E : TEST_F(ParseEngineUnitTest, ProcessAttachIncomplete) {
456 E : TraceModuleData incomplete(kModuleData);
457 E : incomplete.module_base_addr = NULL;
458 :
459 E : EVENT_TRACE event_record = {};
460 E : event_record.Header.ProcessId = kProcessId;
461 E : event_record.Header.ThreadId = kThreadId;
462 E : event_record.Header.Guid = kCallTraceEventClass;
463 E : event_record.Header.Class.Type = TRACE_PROCESS_ATTACH_EVENT;
464 E : event_record.MofData = const_cast<TraceModuleData*>(&incomplete);
465 E : event_record.MofLength = sizeof(incomplete);
466 E : expected_data = &kModuleData;
467 :
468 : // No error should be reported for NULL module addr, instead the record
469 : // should be ignored.
470 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
471 E : ASSERT_FALSE(error_occurred());
472 E : ASSERT_EQ(process_attaches.size(), 0);
473 E : }
474 :
475 E : TEST_F(ParseEngineUnitTest, ProcessAttach) {
476 E : EVENT_TRACE event_record = {};
477 E : event_record.Header.ProcessId = kProcessId;
478 E : event_record.Header.ThreadId = kThreadId;
479 E : event_record.Header.Guid = kCallTraceEventClass;
480 E : event_record.Header.Class.Type = TRACE_PROCESS_ATTACH_EVENT;
481 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
482 E : event_record.MofLength = sizeof(kModuleData);
483 E : expected_data = &kModuleData;
484 :
485 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
486 E : ASSERT_FALSE(error_occurred());
487 E : ASSERT_EQ(process_attaches.size(), 1);
488 :
489 : // Check for short module event.
490 E : event_record.MofLength -= 1;
491 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
492 E : ASSERT_TRUE(error_occurred());
493 E : }
494 :
495 E : TEST_F(ParseEngineUnitTest, ProcessDetach) {
496 E : EVENT_TRACE event_record = {};
497 E : event_record.Header.ProcessId = kProcessId;
498 E : event_record.Header.ThreadId = kThreadId;
499 E : event_record.Header.Guid = kCallTraceEventClass;
500 E : event_record.Header.Class.Type = TRACE_PROCESS_DETACH_EVENT;
501 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
502 E : event_record.MofLength = sizeof(kModuleData);
503 E : expected_data = &kModuleData;
504 :
505 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
506 E : ASSERT_FALSE(error_occurred());
507 E : ASSERT_EQ(process_detaches.size(), 1);
508 :
509 : // Check for short module event.
510 E : event_record.MofLength -= 1;
511 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
512 E : ASSERT_TRUE(error_occurred());
513 E : }
514 :
515 E : TEST_F(ParseEngineUnitTest, ThreadAttach) {
516 E : EVENT_TRACE event_record = {};
517 E : event_record.Header.ProcessId = kProcessId;
518 E : event_record.Header.ThreadId = kThreadId;
519 E : event_record.Header.Guid = kCallTraceEventClass;
520 E : event_record.Header.Class.Type = TRACE_THREAD_ATTACH_EVENT;
521 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
522 E : event_record.MofLength = sizeof(kModuleData);
523 E : expected_data = &kModuleData;
524 :
525 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
526 E : ASSERT_FALSE(error_occurred());
527 E : ASSERT_EQ(thread_attaches.size(), 1);
528 :
529 : // Check for short module event.
530 E : event_record.MofLength -= 1;
531 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
532 E : ASSERT_TRUE(error_occurred());
533 E : }
534 :
535 E : TEST_F(ParseEngineUnitTest, ThreadDetach) {
536 E : EVENT_TRACE event_record = {};
537 E : event_record.Header.ProcessId = kProcessId;
538 E : event_record.Header.ThreadId = kThreadId;
539 E : event_record.Header.Guid = kCallTraceEventClass;
540 E : event_record.Header.Class.Type = TRACE_THREAD_DETACH_EVENT;
541 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
542 E : event_record.MofLength = sizeof(kModuleData);
543 E : expected_data = &kModuleData;
544 :
545 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
546 E : ASSERT_FALSE(error_occurred());
547 E : ASSERT_EQ(thread_detaches.size(), 1);
548 :
549 : // Check for short module event.
550 E : event_record.MofLength -= 1;
551 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
552 E : ASSERT_TRUE(error_occurred());
553 E : }
554 :
555 E : TEST_F(ParseEngineUnitTest, BasicBlockFrequencyTooSmallForHeader) {
556 E : EVENT_TRACE event_record = {};
557 E : event_record.Header.ProcessId = kProcessId;
558 E : event_record.Header.ThreadId = kThreadId;
559 E : event_record.Header.Guid = kCallTraceEventClass;
560 E : event_record.Header.Class.Type = TRACE_BASIC_BLOCK_FREQUENCY;
561 : event_record.MofData = const_cast<TraceBasicBlockFrequencyData*>(
562 E : &kBasicBlockFrequencyData);
563 E : event_record.MofLength = sizeof(kBasicBlockFrequencyData) - 1;
564 :
565 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
566 E : ASSERT_TRUE(error_occurred());
567 E : ASSERT_EQ(basic_block_frequencies, 0);
568 E : }
569 :
570 E : TEST_F(ParseEngineUnitTest, BasicBlockFrequencyTooSmallForContents) {
571 E : EVENT_TRACE event_record = {};
572 E : event_record.Header.ProcessId = kProcessId;
573 E : event_record.Header.ThreadId = kThreadId;
574 E : event_record.Header.Guid = kCallTraceEventClass;
575 E : event_record.Header.Class.Type = TRACE_BASIC_BLOCK_FREQUENCY;
576 : event_record.MofData = const_cast<TraceBasicBlockFrequencyData*>(
577 E : &kShortBasicBlockFrequencyData);
578 E : event_record.MofLength = sizeof(kShortBasicBlockFrequencyData);
579 :
580 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
581 E : ASSERT_TRUE(error_occurred());
582 E : ASSERT_EQ(basic_block_frequencies, 0);
583 E : }
584 :
585 E : TEST_F(ParseEngineUnitTest, BasicBlockFrequency) {
586 E : EVENT_TRACE event_record = {};
587 E : event_record.Header.ProcessId = kProcessId;
588 E : event_record.Header.ThreadId = kThreadId;
589 E : event_record.Header.Guid = kCallTraceEventClass;
590 E : event_record.Header.Class.Type = TRACE_BASIC_BLOCK_FREQUENCY;
591 : event_record.MofData = const_cast<TraceBasicBlockFrequencyData*>(
592 E : &kBasicBlockFrequencyData);
593 E : event_record.MofLength = sizeof(kBasicBlockFrequencyData);
594 E : expected_data = &kBasicBlockFrequencyData;
595 :
596 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
597 E : ASSERT_FALSE(error_occurred());
598 E : ASSERT_EQ(basic_block_frequencies, 1);
599 E : }
600 :
601 : } // namespace
|