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 "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 i : bool IsRecognizedTraceFile(const FilePath& trace_file_path) OVERRIDE {
55 i : return true;
56 i : }
57 :
58 i : bool OpenTraceFile(const FilePath& trace_file_path) OVERRIDE {
59 i : return true;
60 i : }
61 :
62 i : virtual bool ConsumeAllEvents() {
63 i : return true;
64 i : }
65 :
66 i : virtual bool CloseAllTraceFiles() {
67 i : return true;
68 i : }
69 :
70 : // ParseEventHander methods.
71 :
72 : virtual void OnProcessStarted(base::Time time,
73 : DWORD process_id,
74 i : const TraceSystemInfo* data) {
75 i : ASSERT_EQ(process_id, kProcessId);
76 i : }
77 :
78 i : virtual void OnProcessEnded(base::Time time, DWORD process_id) {
79 i : ASSERT_EQ(process_id, kProcessId);
80 i : }
81 :
82 : virtual void OnFunctionEntry(base::Time time,
83 : DWORD process_id,
84 : DWORD thread_id,
85 E : const TraceEnterExitEventData* data) {
86 E : ASSERT_EQ(process_id, kProcessId);
87 E : ASSERT_EQ(thread_id, kThreadId);
88 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
89 E : EXPECT_TRUE(data->function != NULL);
90 E : function_entries.insert(data->function);
91 E : }
92 :
93 : virtual void OnFunctionExit(base::Time time,
94 : DWORD process_id,
95 : DWORD thread_id,
96 E : const TraceEnterExitEventData* data) {
97 E : ASSERT_EQ(process_id, kProcessId);
98 E : ASSERT_EQ(thread_id, kThreadId);
99 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
100 E : EXPECT_TRUE(data->function != NULL);
101 E : function_exits.insert(data->function);
102 E : }
103 :
104 : virtual void OnBatchFunctionEntry(base::Time time,
105 : DWORD process_id,
106 : DWORD thread_id,
107 E : const TraceBatchEnterData* data) {
108 E : ASSERT_EQ(process_id, kProcessId);
109 E : ASSERT_EQ(thread_id, kThreadId);
110 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
111 E : for (size_t i = 0; i < data->num_calls; ++i) {
112 E : function_entries.insert(data->calls[i].function);
113 E : }
114 E : }
115 :
116 : virtual void OnProcessAttach(base::Time time,
117 : DWORD process_id,
118 : DWORD thread_id,
119 E : const TraceModuleData* data) {
120 E : ASSERT_EQ(process_id, kProcessId);
121 E : ASSERT_EQ(thread_id, kThreadId);
122 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
123 E : process_attaches.push_back(*data);
124 E : }
125 :
126 : virtual void OnProcessDetach(base::Time time,
127 : DWORD process_id,
128 : DWORD thread_id,
129 E : const TraceModuleData* data) {
130 E : ASSERT_EQ(process_id, kProcessId);
131 E : ASSERT_EQ(thread_id, kThreadId);
132 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
133 E : process_detaches.push_back(*data);
134 E : }
135 :
136 : virtual void OnThreadAttach(base::Time time,
137 : DWORD process_id,
138 : DWORD thread_id,
139 E : const TraceModuleData* data) {
140 E : ASSERT_EQ(process_id, kProcessId);
141 E : ASSERT_EQ(thread_id, kThreadId);
142 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
143 E : thread_attaches.push_back(*data);
144 E : }
145 :
146 : // Issued for DLL_THREAD_DETACH on an instrumented module.
147 : virtual void OnThreadDetach(base::Time time,
148 : DWORD process_id,
149 : DWORD thread_id,
150 E : const TraceModuleData* data) {
151 E : ASSERT_EQ(process_id, kProcessId);
152 E : ASSERT_EQ(thread_id, kThreadId);
153 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
154 E : thread_detaches.push_back(*data);
155 E : }
156 :
157 : virtual void OnIndexedFrequency(
158 : base::Time time,
159 : DWORD process_id,
160 : DWORD thread_id,
161 E : const TraceIndexedFrequencyData* data) {
162 E : ASSERT_EQ(process_id, kProcessId);
163 E : ASSERT_EQ(thread_id, kThreadId);
164 E : ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
165 E : ++basic_block_frequencies;
166 E : }
167 :
168 : static const DWORD kProcessId;
169 : static const DWORD kThreadId;
170 : static const ModuleInformation kExeInfo;
171 : static const ModuleInformation kDllInfo;
172 : static const TraceModuleData kModuleData;
173 : static const TraceIndexedFrequencyData kIndexedFrequencyData;
174 : static const TraceIndexedFrequencyData kShortIndexedFrequencyData;
175 :
176 : FunctionSet function_entries;
177 : FunctionSet function_exits;
178 : ModuleSet process_attaches;
179 : ModuleSet process_detaches;
180 : ModuleSet thread_attaches;
181 : ModuleSet thread_detaches;
182 : size_t basic_block_frequencies;
183 :
184 : const void* expected_data;
185 : };
186 :
187 : const DWORD ParseEngineUnitTest::kProcessId = 0xAAAAAAAA;
188 :
189 : const DWORD ParseEngineUnitTest::kThreadId = 0xBBBBBBBB;
190 :
191 E : const ModuleInformation ParseEngineUnitTest::kExeInfo = {
192 E : 0x11111111, 0x22222222, 0x33333333, 0x44444444, L"file_name.exe" };
193 :
194 E : const ModuleInformation ParseEngineUnitTest::kDllInfo = {
195 E : 0x55555555, 0x66666666, 0x77777777, 0x88888888, L"file_name.dll" };
196 :
197 : const TraceModuleData ParseEngineUnitTest::kModuleData = {
198 : reinterpret_cast<ModuleAddr>(0x99999999),
199 : 0x11111111,
200 : 0x22222222,
201 : 0x33333333,
202 : L"module",
203 : L"executable" };
204 :
205 : const TraceIndexedFrequencyData ParseEngineUnitTest::kIndexedFrequencyData = {
206 : reinterpret_cast<ModuleAddr>(0x11111111),
207 : 0x22222222,
208 : 0x33333333,
209 : 0x44444444,
210 : 1,
211 : TraceIndexedFrequencyData::BASIC_BLOCK,
212 : 1,
213 : 0 };
214 :
215 : // This indexed frequency struct does not contain enough data for its implicitly
216 : // encoded length.
217 : const TraceIndexedFrequencyData
218 : ParseEngineUnitTest::kShortIndexedFrequencyData = {
219 : reinterpret_cast<ModuleAddr>(0x11111111),
220 : 0x22222222,
221 : 0x33333333,
222 : 0x44444444,
223 : 10,
224 : TraceIndexedFrequencyData::BASIC_BLOCK,
225 : 4,
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 data.
369 E : event_record.MofLength = sizeof(TraceEnterEventData) - 1;
370 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
371 E : ASSERT_TRUE(error_occurred());
372 E : }
373 :
374 E : TEST_F(ParseEngineUnitTest, FunctionExitEvents) {
375 E : TraceExitEventData event_data = {};
376 E : event_data.function = &TestFunc2;
377 E : expected_data = &event_data;
378 :
379 E : EVENT_TRACE event_record = {};
380 E : event_record.Header.ProcessId = kProcessId;
381 E : event_record.Header.ThreadId = kThreadId;
382 E : event_record.Header.Guid = kCallTraceEventClass;
383 E : event_record.Header.Class.Type = TRACE_EXIT_EVENT;
384 E : event_record.MofData = &event_data;
385 E : event_record.MofLength = sizeof(event_data);
386 :
387 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
388 E : ASSERT_FALSE(error_occurred());
389 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
390 E : ASSERT_FALSE(error_occurred());
391 E : ASSERT_EQ(function_exits.size(), 2);
392 E : ASSERT_EQ(function_exits.count(&TestFunc2), 2);
393 :
394 : // Check for short event data.
395 E : event_record.MofLength = sizeof(TraceEnterEventData) - 1;
396 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
397 E : ASSERT_TRUE(error_occurred());
398 E : }
399 :
400 E : TEST_F(ParseEngineUnitTest, BatchFunctionEntry) {
401 : uint8 raw_data[sizeof(TraceBatchEnterData) +
402 E : 4 * sizeof(TraceEnterEventData)] = {};
403 : TraceBatchEnterData& event_data =
404 E : *reinterpret_cast<TraceBatchEnterData*>(&raw_data);
405 E : event_data.thread_id = kThreadId;
406 E : event_data.num_calls = 5;
407 E : event_data.calls[0].function = &TestFunc1;
408 E : event_data.calls[1].function = &TestFunc2;
409 E : event_data.calls[2].function = &TestFunc1;
410 E : event_data.calls[3].function = &TestFunc2;
411 E : event_data.calls[4].function = NULL;
412 E : expected_data = &raw_data;
413 :
414 E : EVENT_TRACE event_record = {};
415 E : event_record.Header.ProcessId = kProcessId;
416 E : event_record.Header.ThreadId = kThreadId;
417 E : event_record.Header.Guid = kCallTraceEventClass;
418 E : event_record.Header.Class.Type = TRACE_BATCH_ENTER;
419 E : event_record.MofData = &raw_data;
420 E : event_record.MofLength = sizeof(raw_data);
421 :
422 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
423 E : ASSERT_FALSE(error_occurred());
424 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
425 E : ASSERT_FALSE(error_occurred());
426 E : ASSERT_EQ(function_entries.size(), 8);
427 E : ASSERT_EQ(function_entries.count(&TestFunc1), 4);
428 E : ASSERT_EQ(function_entries.count(&TestFunc2), 4);
429 :
430 : // Check for short event header.
431 E : event_record.MofLength = FIELD_OFFSET(TraceBatchEnterData, num_calls);
432 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
433 E : ASSERT_TRUE(error_occurred());
434 :
435 : // Check for short event tail (remove the empty record + one byte).
436 E : set_error_occurred(false);
437 E : event_record.MofLength = sizeof(raw_data) - sizeof(TraceEnterEventData) - 1;
438 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
439 E : ASSERT_TRUE(error_occurred());
440 E : }
441 :
442 E : TEST_F(ParseEngineUnitTest, ProcessAttachIncomplete) {
443 E : TraceModuleData incomplete(kModuleData);
444 E : incomplete.module_base_addr = NULL;
445 :
446 E : EVENT_TRACE event_record = {};
447 E : event_record.Header.ProcessId = kProcessId;
448 E : event_record.Header.ThreadId = kThreadId;
449 E : event_record.Header.Guid = kCallTraceEventClass;
450 E : event_record.Header.Class.Type = TRACE_PROCESS_ATTACH_EVENT;
451 E : event_record.MofData = const_cast<TraceModuleData*>(&incomplete);
452 E : event_record.MofLength = sizeof(incomplete);
453 E : expected_data = &kModuleData;
454 :
455 : // No error should be reported for NULL module addr, instead the record
456 : // should be ignored.
457 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
458 E : ASSERT_FALSE(error_occurred());
459 E : ASSERT_EQ(process_attaches.size(), 0);
460 E : }
461 :
462 E : TEST_F(ParseEngineUnitTest, ProcessAttach) {
463 E : EVENT_TRACE event_record = {};
464 E : event_record.Header.ProcessId = kProcessId;
465 E : event_record.Header.ThreadId = kThreadId;
466 E : event_record.Header.Guid = kCallTraceEventClass;
467 E : event_record.Header.Class.Type = TRACE_PROCESS_ATTACH_EVENT;
468 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
469 E : event_record.MofLength = sizeof(kModuleData);
470 E : expected_data = &kModuleData;
471 :
472 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
473 E : ASSERT_FALSE(error_occurred());
474 E : ASSERT_EQ(process_attaches.size(), 1);
475 :
476 : // Check for short module event.
477 E : event_record.MofLength -= 1;
478 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
479 E : ASSERT_TRUE(error_occurred());
480 E : }
481 :
482 E : TEST_F(ParseEngineUnitTest, ProcessDetach) {
483 E : EVENT_TRACE event_record = {};
484 E : event_record.Header.ProcessId = kProcessId;
485 E : event_record.Header.ThreadId = kThreadId;
486 E : event_record.Header.Guid = kCallTraceEventClass;
487 E : event_record.Header.Class.Type = TRACE_PROCESS_DETACH_EVENT;
488 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
489 E : event_record.MofLength = sizeof(kModuleData);
490 E : expected_data = &kModuleData;
491 :
492 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
493 E : ASSERT_FALSE(error_occurred());
494 E : ASSERT_EQ(process_detaches.size(), 1);
495 :
496 : // Check for short module event.
497 E : event_record.MofLength -= 1;
498 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
499 E : ASSERT_TRUE(error_occurred());
500 E : }
501 :
502 E : TEST_F(ParseEngineUnitTest, ThreadAttach) {
503 E : EVENT_TRACE event_record = {};
504 E : event_record.Header.ProcessId = kProcessId;
505 E : event_record.Header.ThreadId = kThreadId;
506 E : event_record.Header.Guid = kCallTraceEventClass;
507 E : event_record.Header.Class.Type = TRACE_THREAD_ATTACH_EVENT;
508 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
509 E : event_record.MofLength = sizeof(kModuleData);
510 E : expected_data = &kModuleData;
511 :
512 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
513 E : ASSERT_FALSE(error_occurred());
514 E : ASSERT_EQ(thread_attaches.size(), 1);
515 :
516 : // Check for short module event.
517 E : event_record.MofLength -= 1;
518 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
519 E : ASSERT_TRUE(error_occurred());
520 E : }
521 :
522 E : TEST_F(ParseEngineUnitTest, ThreadDetach) {
523 E : EVENT_TRACE event_record = {};
524 E : event_record.Header.ProcessId = kProcessId;
525 E : event_record.Header.ThreadId = kThreadId;
526 E : event_record.Header.Guid = kCallTraceEventClass;
527 E : event_record.Header.Class.Type = TRACE_THREAD_DETACH_EVENT;
528 E : event_record.MofData = const_cast<TraceModuleData*>(&kModuleData);
529 E : event_record.MofLength = sizeof(kModuleData);
530 E : expected_data = &kModuleData;
531 :
532 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
533 E : ASSERT_FALSE(error_occurred());
534 E : ASSERT_EQ(thread_detaches.size(), 1);
535 :
536 : // Check for short module event.
537 E : event_record.MofLength -= 1;
538 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
539 E : ASSERT_TRUE(error_occurred());
540 E : }
541 :
542 E : TEST_F(ParseEngineUnitTest, IndexedFrequencyTooSmallForHeader) {
543 E : EVENT_TRACE event_record = {};
544 E : event_record.Header.ProcessId = kProcessId;
545 E : event_record.Header.ThreadId = kThreadId;
546 E : event_record.Header.Guid = kCallTraceEventClass;
547 E : event_record.Header.Class.Type = TRACE_INDEXED_FREQUENCY;
548 : event_record.MofData = const_cast<TraceIndexedFrequencyData*>(
549 E : &kIndexedFrequencyData);
550 E : event_record.MofLength = sizeof(kIndexedFrequencyData) - 1;
551 :
552 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
553 E : ASSERT_TRUE(error_occurred());
554 E : ASSERT_EQ(basic_block_frequencies, 0);
555 E : }
556 :
557 E : TEST_F(ParseEngineUnitTest, IndexedFrequencyTooSmallForContents) {
558 E : EVENT_TRACE event_record = {};
559 E : event_record.Header.ProcessId = kProcessId;
560 E : event_record.Header.ThreadId = kThreadId;
561 E : event_record.Header.Guid = kCallTraceEventClass;
562 E : event_record.Header.Class.Type = TRACE_INDEXED_FREQUENCY;
563 : event_record.MofData = const_cast<TraceIndexedFrequencyData*>(
564 E : &kShortIndexedFrequencyData);
565 E : event_record.MofLength = sizeof(kShortIndexedFrequencyData);
566 :
567 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
568 E : ASSERT_TRUE(error_occurred());
569 E : ASSERT_EQ(basic_block_frequencies, 0);
570 E : }
571 :
572 E : TEST_F(ParseEngineUnitTest, IndexedFrequency) {
573 E : EVENT_TRACE event_record = {};
574 E : event_record.Header.ProcessId = kProcessId;
575 E : event_record.Header.ThreadId = kThreadId;
576 E : event_record.Header.Guid = kCallTraceEventClass;
577 E : event_record.Header.Class.Type = TRACE_INDEXED_FREQUENCY;
578 : event_record.MofData = const_cast<TraceIndexedFrequencyData*>(
579 E : &kIndexedFrequencyData);
580 E : event_record.MofLength = sizeof(kIndexedFrequencyData);
581 E : expected_data = &kIndexedFrequencyData;
582 :
583 E : ASSERT_NO_FATAL_FAILURE(ASSERT_TRUE(DispatchEvent(&event_record)));
584 E : ASSERT_FALSE(error_occurred());
585 E : ASSERT_EQ(basic_block_frequencies, 1);
586 E : }
587 :
588 : } // namespace
|