blob: c0c938098a4c5963db00e427385a24a103504c0b [file] [log] [blame]
[email protected]366ae242011-05-10 02:23:581// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/debug/trace_event.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/json/json_reader.h"
10#include "base/json/json_writer.h"
[email protected]63bb0892011-09-06 17:56:2411#include "base/memory/ref_counted_memory.h"
[email protected]366ae242011-05-10 02:23:5812#include "base/memory/scoped_ptr.h"
[email protected]5b4926e2011-08-09 15:16:2513#include "base/process_util.h"
[email protected]366ae242011-05-10 02:23:5814#include "base/stringprintf.h"
15#include "base/synchronization/waitable_event.h"
16#include "base/threading/thread.h"
17#include "base/values.h"
18#include "testing/gmock/include/gmock/gmock.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
21namespace base {
22namespace debug {
23
24namespace {
25
[email protected]434b02a2011-09-12 22:03:4126enum CompareOp {
27 IS_EQUAL,
28 IS_NOT_EQUAL,
29};
30
[email protected]73e5f8152011-05-13 23:30:3531struct JsonKeyValue {
32 const char* key;
33 const char* value;
[email protected]434b02a2011-09-12 22:03:4134 CompareOp op;
[email protected]73e5f8152011-05-13 23:30:3535};
36
[email protected]366ae242011-05-10 02:23:5837class TraceEventTestFixture : public testing::Test {
38 public:
[email protected]d1f03512011-07-21 12:28:5939 // This fixture does not use SetUp() because the fixture must be manually set
40 // up multiple times when testing AtExit. Use ManualTestSetUp for this.
[email protected]366ae242011-05-10 02:23:5841 void ManualTestSetUp();
[email protected]6a341fb2011-06-26 16:22:5042 void OnTraceDataCollected(
43 scoped_refptr<TraceLog::RefCountedString> json_events_str);
[email protected]73e5f8152011-05-13 23:30:3544 bool FindMatchingTraceEntry(const JsonKeyValue* key_values);
45 bool FindNamePhase(const char* name, const char* phase);
[email protected]434b02a2011-09-12 22:03:4146 bool FindMatchingValue(const char* key,
47 const char* value);
48 bool FindNonMatchingValue(const char* key,
49 const char* value);
50 void Clear() {
51 trace_string_.clear();
52 trace_parsed_.Clear();
53 }
[email protected]366ae242011-05-10 02:23:5854
55 std::string trace_string_;
56 ListValue trace_parsed_;
57
58 private:
59 // We want our singleton torn down after each test.
60 ShadowingAtExitManager at_exit_manager_;
[email protected]19d8a902011-10-03 17:51:2561 Lock lock_;
[email protected]366ae242011-05-10 02:23:5862};
63
64void TraceEventTestFixture::ManualTestSetUp() {
[email protected]19d8a902011-10-03 17:51:2565 TraceLog::DeleteForTesting();
[email protected]366ae242011-05-10 02:23:5866 TraceLog::Resurrect();
67 TraceLog* tracelog = TraceLog::GetInstance();
68 ASSERT_TRUE(tracelog);
69 ASSERT_FALSE(tracelog->IsEnabled());
70 tracelog->SetOutputCallback(
[email protected]19d8a902011-10-03 17:51:2571 base::Bind(&TraceEventTestFixture::OnTraceDataCollected,
72 base::Unretained(this)));
[email protected]366ae242011-05-10 02:23:5873}
74
75void TraceEventTestFixture::OnTraceDataCollected(
[email protected]6a341fb2011-06-26 16:22:5076 scoped_refptr<TraceLog::RefCountedString> json_events_str) {
[email protected]19d8a902011-10-03 17:51:2577 AutoLock lock(lock_);
[email protected]366ae242011-05-10 02:23:5878 trace_string_ += json_events_str->data;
79
80 scoped_ptr<Value> root;
81 root.reset(base::JSONReader::Read(json_events_str->data, false));
82
83 ListValue* root_list = NULL;
84 ASSERT_TRUE(root.get());
85 ASSERT_TRUE(root->GetAsList(&root_list));
86
87 // Move items into our aggregate collection
88 while (root_list->GetSize()) {
89 Value* item = NULL;
90 root_list->Remove(0, &item);
91 trace_parsed_.Append(item);
92 }
93}
94
[email protected]434b02a2011-09-12 22:03:4195static bool CompareJsonValues(const std::string& lhs,
96 const std::string& rhs,
97 CompareOp op) {
98 switch (op) {
99 case IS_EQUAL:
100 return lhs == rhs;
101 case IS_NOT_EQUAL:
102 return lhs != rhs;
103 default:
104 CHECK(0);
105 }
106 return false;
107}
108
[email protected]73e5f8152011-05-13 23:30:35109static bool IsKeyValueInDict(const JsonKeyValue* key_value,
110 DictionaryValue* dict) {
111 Value* value = NULL;
112 std::string value_str;
113 if (dict->Get(key_value->key, &value) &&
114 value->GetAsString(&value_str) &&
[email protected]434b02a2011-09-12 22:03:41115 CompareJsonValues(value_str, key_value->value, key_value->op))
[email protected]73e5f8152011-05-13 23:30:35116 return true;
117
118 // Recurse to test arguments
119 DictionaryValue* args_dict = NULL;
120 dict->GetDictionary("args", &args_dict);
121 if (args_dict)
122 return IsKeyValueInDict(key_value, args_dict);
123
124 return false;
125}
126
127static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
128 DictionaryValue* dict) {
129 // Scan all key_values, they must all be present and equal.
130 while (key_values && key_values->key) {
131 if (!IsKeyValueInDict(key_values, dict))
132 return false;
133 ++key_values;
134 }
135 return true;
136}
137
138bool TraceEventTestFixture::FindMatchingTraceEntry(
139 const JsonKeyValue* key_values) {
140 // Scan all items
141 size_t trace_parsed_count = trace_parsed_.GetSize();
142 for (size_t i = 0; i < trace_parsed_count; i++) {
143 Value* value = NULL;
144 trace_parsed_.Get(i, &value);
145 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
146 continue;
147 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
148
149 if (IsAllKeyValueInDict(key_values, dict))
150 return true;
151 }
152 return false;
153}
154
155bool TraceEventTestFixture::FindNamePhase(const char* name, const char* phase) {
156 JsonKeyValue key_values[] = {
[email protected]434b02a2011-09-12 22:03:41157 {"name", name, IS_EQUAL},
158 {"ph", phase, IS_EQUAL},
159 {0, 0, IS_EQUAL}
160 };
161 return FindMatchingTraceEntry(key_values);
162}
163
164bool TraceEventTestFixture::FindMatchingValue(const char* key,
165 const char* value) {
166 JsonKeyValue key_values[] = {
167 {key, value, IS_EQUAL},
168 {0, 0, IS_EQUAL}
169 };
170 return FindMatchingTraceEntry(key_values);
171}
172
173bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
174 const char* value) {
175 JsonKeyValue key_values[] = {
176 {key, value, IS_NOT_EQUAL},
177 {0, 0, IS_EQUAL}
[email protected]73e5f8152011-05-13 23:30:35178 };
179 return FindMatchingTraceEntry(key_values);
180}
181
[email protected]366ae242011-05-10 02:23:58182bool IsStringInDict(const char* string_to_match, DictionaryValue* dict) {
183 for (DictionaryValue::key_iterator ikey = dict->begin_keys();
184 ikey != dict->end_keys(); ++ikey) {
185 Value* child = NULL;
186 if (!dict->GetWithoutPathExpansion(*ikey, &child))
187 continue;
188
189 if ((*ikey).find(string_to_match) != std::string::npos)
190 return true;
191
192 std::string value_str;
193 child->GetAsString(&value_str);
194 if (value_str.find(string_to_match) != std::string::npos)
195 return true;
196 }
197
198 // Recurse to test arguments
199 DictionaryValue* args_dict = NULL;
200 dict->GetDictionary("args", &args_dict);
201 if (args_dict)
202 return IsStringInDict(string_to_match, args_dict);
203
204 return false;
205}
206
207DictionaryValue* FindTraceEntry(const ListValue& trace_parsed,
[email protected]5b4926e2011-08-09 15:16:25208 const char* string_to_match,
[email protected]366ae242011-05-10 02:23:58209 DictionaryValue* match_after_this_item = NULL) {
210 // Scan all items
211 size_t trace_parsed_count = trace_parsed.GetSize();
212 for (size_t i = 0; i < trace_parsed_count; i++) {
213 Value* value = NULL;
214 trace_parsed.Get(i, &value);
215 if (match_after_this_item) {
216 if (value == match_after_this_item)
217 match_after_this_item = NULL;
218 continue;
219 }
220 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
221 continue;
222 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
223
224 if (IsStringInDict(string_to_match, dict))
225 return dict;
226 }
227 return NULL;
228}
229
[email protected]5b4926e2011-08-09 15:16:25230std::vector<DictionaryValue*> FindTraceEntries(
231 const ListValue& trace_parsed,
232 const char* string_to_match) {
233 std::vector<DictionaryValue*> hits;
234 size_t trace_parsed_count = trace_parsed.GetSize();
235 for (size_t i = 0; i < trace_parsed_count; i++) {
236 Value* value = NULL;
237 trace_parsed.Get(i, &value);
238 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
239 continue;
240 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
241
242 if (IsStringInDict(string_to_match, dict))
243 hits.push_back(dict);
244 }
245 return hits;
246}
247
248void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
[email protected]366ae242011-05-10 02:23:58249 {
250 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW call", 1122, "extrastring1");
251 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW call", 3344, "extrastring2");
252 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW call",
253 5566, "extrastring3");
254
255 TRACE_EVENT0("all", "TRACE_EVENT0 call");
256 TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
257 TRACE_EVENT2("all", "TRACE_EVENT2 call",
[email protected]b3c8a152011-09-07 00:43:11258 "name1", "\"value1\"",
259 "name2", "value\\2");
[email protected]366ae242011-05-10 02:23:58260
261 TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call");
262 TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call", "name1", "value1");
263 TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
264 "name1", "value1",
265 "name2", "value2");
266
267 TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
268 TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
269 TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
270 "name1", "value1",
271 "name2", "value2");
272
273 TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
274 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
275 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
276 "name1", "value1",
277 "name2", "value2");
278 } // Scope close causes TRACE_EVENT0 etc to send their END events.
279
280 if (task_complete_event)
281 task_complete_event->Signal();
282}
283
[email protected]5b4926e2011-08-09 15:16:25284void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed,
[email protected]366ae242011-05-10 02:23:58285 const std::string& trace_string) {
286 DictionaryValue* item = NULL;
287
288#define EXPECT_FIND_(string) \
[email protected]19d8a902011-10-03 17:51:25289 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string)));
[email protected]366ae242011-05-10 02:23:58290#define EXPECT_NOT_FIND_(string) \
[email protected]19d8a902011-10-03 17:51:25291 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string)));
[email protected]366ae242011-05-10 02:23:58292#define EXPECT_SUB_FIND_(string) \
[email protected]19d8a902011-10-03 17:51:25293 if (item) EXPECT_TRUE((IsStringInDict(string, item)));
[email protected]366ae242011-05-10 02:23:58294
295 EXPECT_FIND_("ETW Trace Event");
296 EXPECT_FIND_("all");
297 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW call");
298 {
299 int int_val = 0;
300 EXPECT_TRUE(item && item->GetInteger("args.id", &int_val));
301 EXPECT_EQ(1122, int_val);
302 }
303 EXPECT_SUB_FIND_("extrastring1");
304 EXPECT_FIND_("TRACE_EVENT_END_ETW call");
305 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW call");
306 EXPECT_FIND_("TRACE_EVENT0 call");
307 {
308 std::string ph_begin;
309 std::string ph_end;
310 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
311 EXPECT_TRUE((item && item->GetString("ph", &ph_begin)));
312 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call",
313 item)));
314 EXPECT_TRUE((item && item->GetString("ph", &ph_end)));
315 EXPECT_EQ("B", ph_begin);
316 EXPECT_EQ("E", ph_end);
317 }
318 EXPECT_FIND_("TRACE_EVENT1 call");
319 EXPECT_FIND_("TRACE_EVENT2 call");
320 EXPECT_SUB_FIND_("name1");
[email protected]b3c8a152011-09-07 00:43:11321 EXPECT_SUB_FIND_("\"value1\"");
[email protected]366ae242011-05-10 02:23:58322 EXPECT_SUB_FIND_("name2");
[email protected]b3c8a152011-09-07 00:43:11323 EXPECT_SUB_FIND_("value\\2");
[email protected]366ae242011-05-10 02:23:58324 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
325 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
326 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
327 EXPECT_SUB_FIND_("name1");
328 EXPECT_SUB_FIND_("value1");
329 EXPECT_SUB_FIND_("name2");
330 EXPECT_SUB_FIND_("value2");
331 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
332 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
333 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
334 EXPECT_SUB_FIND_("name1");
335 EXPECT_SUB_FIND_("value1");
336 EXPECT_SUB_FIND_("name2");
337 EXPECT_SUB_FIND_("value2");
338 EXPECT_FIND_("TRACE_EVENT_END0 call");
339 EXPECT_FIND_("TRACE_EVENT_END1 call");
340 EXPECT_FIND_("TRACE_EVENT_END2 call");
341 EXPECT_SUB_FIND_("name1");
342 EXPECT_SUB_FIND_("value1");
343 EXPECT_SUB_FIND_("name2");
344 EXPECT_SUB_FIND_("value2");
345}
346
[email protected]5b4926e2011-08-09 15:16:25347void TraceManyInstantEvents(int thread_id, int num_events,
348 WaitableEvent* task_complete_event) {
349 for (int i = 0; i < num_events; i++) {
350 TRACE_EVENT_INSTANT2("all", "multi thread event",
351 "thread", thread_id,
352 "event", i);
353 }
354
355 if (task_complete_event)
356 task_complete_event->Signal();
357}
358
359void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed,
360 const std::string& trace_string,
361 int num_threads, int num_events) {
362 std::map<int, std::map<int, bool> > results;
363
364 size_t trace_parsed_count = trace_parsed.GetSize();
365 for (size_t i = 0; i < trace_parsed_count; i++) {
366 Value* value = NULL;
367 trace_parsed.Get(i, &value);
368 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
369 continue;
370 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
371 std::string name;
372 dict->GetString("name", &name);
373 if (name != "multi thread event")
374 continue;
375
376 int thread = 0;
377 int event = 0;
378 EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
379 EXPECT_TRUE(dict->GetInteger("args.event", &event));
380 results[thread][event] = true;
381 }
382
383 EXPECT_FALSE(results[-1][-1]);
384 for (int thread = 0; thread < num_threads; thread++) {
385 for (int event = 0; event < num_events; event++) {
386 EXPECT_TRUE(results[thread][event]);
387 }
388 }
389}
390
391void TraceCallsWithCachedCategoryPointersPointers(const char* name_str) {
392 TRACE_EVENT0("category name1", name_str);
393 TRACE_EVENT_INSTANT0("category name2", name_str);
394 TRACE_EVENT_BEGIN0("category name3", name_str);
395 TRACE_EVENT_END0("category name4", name_str);
396}
397
[email protected]366ae242011-05-10 02:23:58398} // namespace
399
400// Simple Test for emitting data and validating it was received.
401TEST_F(TraceEventTestFixture, DataCaptured) {
402 ManualTestSetUp();
403 TraceLog::GetInstance()->SetEnabled(true);
404
[email protected]5b4926e2011-08-09 15:16:25405 TraceWithAllMacroVariants(NULL);
[email protected]366ae242011-05-10 02:23:58406
407 TraceLog::GetInstance()->SetEnabled(false);
408
[email protected]5b4926e2011-08-09 15:16:25409 ValidateAllTraceMacrosCreatedData(trace_parsed_, trace_string_);
[email protected]366ae242011-05-10 02:23:58410}
411
[email protected]434b02a2011-09-12 22:03:41412// Test that categories work.
413TEST_F(TraceEventTestFixture, Categories) {
414 ManualTestSetUp();
415
416 // Test that categories that are used can be retrieved whether trace was
417 // enabled or disabled when the trace event was encountered.
418 TRACE_EVENT_INSTANT0("c1", "name");
419 TRACE_EVENT_INSTANT0("c2", "name");
420 TraceLog::GetInstance()->SetEnabled(true);
421 TRACE_EVENT_INSTANT0("c3", "name");
422 TRACE_EVENT_INSTANT0("c4", "name");
423 TraceLog::GetInstance()->SetEnabled(false);
424 std::vector<std::string> cats;
425 TraceLog::GetInstance()->GetKnownCategories(&cats);
426 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c1") != cats.end());
427 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c2") != cats.end());
428 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c3") != cats.end());
429 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c4") != cats.end());
430
431 const std::vector<std::string> empty_categories;
432 std::vector<std::string> included_categories;
433 std::vector<std::string> excluded_categories;
434
435 // Test that category filtering works.
436
437 // Include nonexistent category -> no events
438 Clear();
439 included_categories.clear();
440 included_categories.push_back("not_found823564786");
441 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
442 TRACE_EVENT_INSTANT0("cat1", "name");
443 TRACE_EVENT_INSTANT0("cat2", "name");
444 TraceLog::GetInstance()->SetDisabled();
445 EXPECT_TRUE(trace_parsed_.empty());
446
447 // Include existent category -> only events of that category
448 Clear();
449 included_categories.clear();
450 included_categories.push_back("inc");
451 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
452 TRACE_EVENT_INSTANT0("inc", "name");
453 TRACE_EVENT_INSTANT0("inc2", "name");
454 TraceLog::GetInstance()->SetDisabled();
455 EXPECT_TRUE(FindMatchingValue("cat", "inc"));
456 EXPECT_FALSE(FindNonMatchingValue("cat", "inc"));
457
458 // Include existent wildcard -> all categories matching wildcard
459 Clear();
460 included_categories.clear();
461 included_categories.push_back("inc_wildcard_*");
462 included_categories.push_back("inc_wildchar_?_end");
463 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
464 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "included");
465 TRACE_EVENT_INSTANT0("inc_wildcard_", "included");
466 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "included");
467 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "not_inc");
468 TRACE_EVENT_INSTANT0("cat1", "not_inc");
469 TRACE_EVENT_INSTANT0("cat2", "not_inc");
470 TraceLog::GetInstance()->SetDisabled();
471 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_abc"));
472 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_"));
473 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_x_end"));
474 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
475
476 included_categories.clear();
477
478 // Exclude nonexistent category -> all events
479 Clear();
480 excluded_categories.clear();
481 excluded_categories.push_back("not_found823564786");
482 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
483 TRACE_EVENT_INSTANT0("cat1", "name");
484 TRACE_EVENT_INSTANT0("cat2", "name");
485 TraceLog::GetInstance()->SetDisabled();
486 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
487 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
488
489 // Exclude existent category -> only events of other categories
490 Clear();
491 excluded_categories.clear();
492 excluded_categories.push_back("inc");
493 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
494 TRACE_EVENT_INSTANT0("inc", "name");
495 TRACE_EVENT_INSTANT0("inc2", "name");
496 TraceLog::GetInstance()->SetDisabled();
497 EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
498 EXPECT_FALSE(FindMatchingValue("cat", "inc"));
499
500 // Exclude existent wildcard -> all categories not matching wildcard
501 Clear();
502 excluded_categories.clear();
503 excluded_categories.push_back("inc_wildcard_*");
504 excluded_categories.push_back("inc_wildchar_?_end");
505 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
506 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "not_inc");
507 TRACE_EVENT_INSTANT0("inc_wildcard_", "not_inc");
508 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "not_inc");
509 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "included");
510 TRACE_EVENT_INSTANT0("cat1", "included");
511 TRACE_EVENT_INSTANT0("cat2", "included");
512 TraceLog::GetInstance()->SetDisabled();
513 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_bla_end"));
514 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
515 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
516 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
517}
518
[email protected]73e5f8152011-05-13 23:30:35519// Simple Test for time threshold events.
520TEST_F(TraceEventTestFixture, DataCapturedThreshold) {
521 ManualTestSetUp();
522 TraceLog::GetInstance()->SetEnabled(true);
523
524 // Test that events at the same level are properly filtered by threshold.
525 {
526 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "threshold 100");
527 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "threshold 1000");
528 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "threshold 10000");
529 // 100+ seconds to avoid flakiness.
530 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "threshold long1");
531 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "threshold long2");
532 base::PlatformThread::Sleep(20); // 20000 us
533 }
534
535 // Test that a normal nested event remains after it's parent event is dropped.
536 {
537 TRACE_EVENT_IF_LONGER_THAN0(1000000, "time", "2threshold10000");
538 {
539 TRACE_EVENT0("time", "nonthreshold1");
540 }
541 }
542
543 // Test that parent thresholded events are dropped while some nested events
544 // remain.
545 {
546 TRACE_EVENT0("time", "nonthreshold3");
547 {
548 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "3thresholdlong2");
549 {
550 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "3thresholdlong1");
551 {
552 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "3threshold10000");
553 {
554 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "3threshold1000");
555 {
556 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "3threshold100");
557 base::PlatformThread::Sleep(20);
558 }
559 }
560 }
561 }
562 }
563 }
564
565 // Test that child thresholded events are dropped while some parent events
566 // remain.
567 {
568 TRACE_EVENT0("time", "nonthreshold4");
569 {
570 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "4threshold100");
571 {
572 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "4threshold1000");
573 {
574 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "4threshold10000");
575 {
576 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time",
577 "4thresholdlong1");
578 {
579 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time",
580 "4thresholdlong2");
581 base::PlatformThread::Sleep(20);
582 }
583 }
584 }
585 }
586 }
587 }
588
589 TraceLog::GetInstance()->SetEnabled(false);
590
591#define EXPECT_FIND_BE_(str) \
592 EXPECT_TRUE(FindNamePhase(str, "B")); \
593 EXPECT_TRUE(FindNamePhase(str, "E"))
594#define EXPECT_NOT_FIND_BE_(str) \
595 EXPECT_FALSE(FindNamePhase(str, "B")); \
596 EXPECT_FALSE(FindNamePhase(str, "E"))
597
598 EXPECT_FIND_BE_("threshold 100");
599 EXPECT_FIND_BE_("threshold 1000");
600 EXPECT_FIND_BE_("threshold 10000");
601 EXPECT_NOT_FIND_BE_("threshold long1");
602 EXPECT_NOT_FIND_BE_("threshold long2");
603
604 EXPECT_NOT_FIND_BE_("2threshold10000");
605 EXPECT_FIND_BE_("nonthreshold1");
606
607 EXPECT_FIND_BE_("nonthreshold3");
608 EXPECT_FIND_BE_("3threshold100");
609 EXPECT_FIND_BE_("3threshold1000");
610 EXPECT_FIND_BE_("3threshold10000");
611 EXPECT_NOT_FIND_BE_("3thresholdlong1");
612 EXPECT_NOT_FIND_BE_("3thresholdlong2");
613
614 EXPECT_FIND_BE_("nonthreshold4");
615 EXPECT_FIND_BE_("4threshold100");
616 EXPECT_FIND_BE_("4threshold1000");
617 EXPECT_FIND_BE_("4threshold10000");
618 EXPECT_NOT_FIND_BE_("4thresholdlong1");
619 EXPECT_NOT_FIND_BE_("4thresholdlong2");
620}
621
[email protected]63bb0892011-09-06 17:56:24622// Test that static strings are not copied.
623TEST_F(TraceEventTestFixture, StaticStringVsString) {
624 ManualTestSetUp();
625 TraceLog* tracer = TraceLog::GetInstance();
626 // Make sure old events are flushed:
627 tracer->SetEnabled(false);
628 EXPECT_EQ(0u, tracer->GetEventsSize());
629
630 {
631 tracer->SetEnabled(true);
632 // Test that string arguments are copied.
633 TRACE_EVENT2("cat", "name1",
634 "arg1", std::string("argval"), "arg2", std::string("argval"));
635 // Test that static TRACE_STR_COPY string arguments are copied.
636 TRACE_EVENT2("cat", "name2",
637 "arg1", TRACE_STR_COPY("argval"),
638 "arg2", TRACE_STR_COPY("argval"));
639 size_t num_events = tracer->GetEventsSize();
640 EXPECT_GT(num_events, 1u);
641 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
642 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
643 EXPECT_STREQ("name1", event1.name());
644 EXPECT_STREQ("name2", event2.name());
645 EXPECT_TRUE(event1.parameter_copy_storage() != NULL);
646 EXPECT_TRUE(event2.parameter_copy_storage() != NULL);
647 EXPECT_GT(event1.parameter_copy_storage()->size(), 0u);
648 EXPECT_GT(event2.parameter_copy_storage()->size(), 0u);
649 tracer->SetEnabled(false);
650 }
651
652 {
653 tracer->SetEnabled(true);
654 // Test that static literal string arguments are not copied.
655 TRACE_EVENT2("cat", "name1",
656 "arg1", "argval", "arg2", "argval");
657 // Test that static TRACE_STR_COPY NULL string arguments are not copied.
658 const char* str1 = NULL;
659 const char* str2 = NULL;
660 TRACE_EVENT2("cat", "name2",
661 "arg1", TRACE_STR_COPY(str1),
662 "arg2", TRACE_STR_COPY(str2));
663 size_t num_events = tracer->GetEventsSize();
664 EXPECT_GT(num_events, 1u);
665 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
666 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
667 EXPECT_STREQ("name1", event1.name());
668 EXPECT_STREQ("name2", event2.name());
669 EXPECT_TRUE(event1.parameter_copy_storage() == NULL);
670 EXPECT_TRUE(event2.parameter_copy_storage() == NULL);
671 tracer->SetEnabled(false);
672 }
673}
674
[email protected]366ae242011-05-10 02:23:58675// Test that data sent from other threads is gathered
676TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
677 ManualTestSetUp();
678 TraceLog::GetInstance()->SetEnabled(true);
679
680 Thread thread("1");
681 WaitableEvent task_complete_event(false, false);
682 thread.Start();
683
684 thread.message_loop()->PostTask(
[email protected]19d8a902011-10-03 17:51:25685 FROM_HERE, NewRunnableFunction(&TraceWithAllMacroVariants,
686 &task_complete_event));
[email protected]366ae242011-05-10 02:23:58687 task_complete_event.Wait();
[email protected]19d8a902011-10-03 17:51:25688 thread.Stop();
[email protected]366ae242011-05-10 02:23:58689
690 TraceLog::GetInstance()->SetEnabled(false);
[email protected]5b4926e2011-08-09 15:16:25691 ValidateAllTraceMacrosCreatedData(trace_parsed_, trace_string_);
[email protected]366ae242011-05-10 02:23:58692}
693
[email protected]366ae242011-05-10 02:23:58694// Test that data sent from multiple threads is gathered
695TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
696 ManualTestSetUp();
697 TraceLog::GetInstance()->SetEnabled(true);
698
699 const int num_threads = 4;
700 const int num_events = 4000;
701 Thread* threads[num_threads];
702 WaitableEvent* task_complete_events[num_threads];
703 for (int i = 0; i < num_threads; i++) {
704 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
705 task_complete_events[i] = new WaitableEvent(false, false);
706 threads[i]->Start();
707 threads[i]->message_loop()->PostTask(
[email protected]19d8a902011-10-03 17:51:25708 FROM_HERE, NewRunnableFunction(&TraceManyInstantEvents,
709 i, num_events, task_complete_events[i]));
[email protected]366ae242011-05-10 02:23:58710 }
711
712 for (int i = 0; i < num_threads; i++) {
713 task_complete_events[i]->Wait();
714 }
715
[email protected]366ae242011-05-10 02:23:58716 for (int i = 0; i < num_threads; i++) {
717 threads[i]->Stop();
718 delete threads[i];
719 delete task_complete_events[i];
720 }
721
[email protected]19d8a902011-10-03 17:51:25722 TraceLog::GetInstance()->SetEnabled(false);
723
[email protected]5b4926e2011-08-09 15:16:25724 ValidateInstantEventPresentOnEveryThread(trace_parsed_, trace_string_,
725 num_threads, num_events);
[email protected]366ae242011-05-10 02:23:58726}
727
[email protected]5b4926e2011-08-09 15:16:25728// Test that thread and process names show up in the trace
729TEST_F(TraceEventTestFixture, ThreadNames) {
730 ManualTestSetUp();
731
732 // Create threads before we enable tracing to make sure
733 // that tracelog still captures them.
734 const int num_threads = 4;
735 const int num_events = 10;
736 Thread* threads[num_threads];
737 PlatformThreadId thread_ids[num_threads];
738 for (int i = 0; i < num_threads; i++)
739 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
740
741 // Enable tracing.
742 TraceLog::GetInstance()->SetEnabled(true);
743
744 // Now run some trace code on these threads.
745 WaitableEvent* task_complete_events[num_threads];
746 for (int i = 0; i < num_threads; i++) {
747 task_complete_events[i] = new WaitableEvent(false, false);
748 threads[i]->Start();
749 thread_ids[i] = threads[i]->thread_id();
750 threads[i]->message_loop()->PostTask(
[email protected]19d8a902011-10-03 17:51:25751 FROM_HERE, NewRunnableFunction(&TraceManyInstantEvents,
752 i, num_events, task_complete_events[i]));
[email protected]5b4926e2011-08-09 15:16:25753 }
754 for (int i = 0; i < num_threads; i++) {
755 task_complete_events[i]->Wait();
756 }
757
758 // Shut things down.
[email protected]5b4926e2011-08-09 15:16:25759 for (int i = 0; i < num_threads; i++) {
760 threads[i]->Stop();
761 delete threads[i];
762 delete task_complete_events[i];
763 }
764
[email protected]19d8a902011-10-03 17:51:25765 TraceLog::GetInstance()->SetEnabled(false);
766
[email protected]5b4926e2011-08-09 15:16:25767 std::string tmp;
768 int tmp_int;
769 DictionaryValue* item;
770
771 // Make sure we get thread name metadata.
772 // Note, the test suite may have created a ton of threads.
773 // So, we'll have thread names for threads we didn't create.
774 std::vector<DictionaryValue*> items =
775 FindTraceEntries(trace_parsed_, "thread_name");
776 for (int i = 0; i < static_cast<int>(items.size()); i++) {
777 item = items[i];
778 EXPECT_TRUE(item);
779 EXPECT_TRUE(item->GetInteger("tid", &tmp_int));
780
781 // See if this thread name is one of the threads we just created
782 for (int j = 0; j < num_threads; j++) {
783 if(static_cast<int>(thread_ids[j]) != tmp_int)
784 continue;
785
786 std::string expected_name = StringPrintf("Thread %d", j).c_str();
787 EXPECT_TRUE(item->GetString("ph", &tmp) && tmp == "M");
788 EXPECT_TRUE(item->GetInteger("pid", &tmp_int) &&
789 tmp_int == static_cast<int>(base::GetCurrentProcId()));
790 EXPECT_TRUE(item->GetString("args.name", &tmp) &&
791 tmp == expected_name);
792 }
793 }
[email protected]366ae242011-05-10 02:23:58794}
795
[email protected]5b4926e2011-08-09 15:16:25796
[email protected]366ae242011-05-10 02:23:58797// Test trace calls made after tracing singleton shut down.
798//
799// The singleton is destroyed by our base::AtExitManager, but there can be
800// code still executing as the C++ static objects are destroyed. This test
801// forces the singleton to destroy early, and intentinally makes trace calls
802// afterwards.
803TEST_F(TraceEventTestFixture, AtExit) {
804 // Repeat this test a few times. Besides just showing robustness, it also
805 // allows us to test that events at shutdown do not appear with valid events
806 // recorded after the system is started again.
807 for (int i = 0; i < 4; i++) {
808 // Scope to contain the then destroy the TraceLog singleton.
809 {
810 base::ShadowingAtExitManager exit_manager_will_destroy_singletons;
811
812 // Setup TraceLog singleton inside this test's exit manager scope
813 // so that it will be destroyed when this scope closes.
814 ManualTestSetUp();
815
816 TRACE_EVENT_INSTANT0("all", "not recorded; system not enabled");
817
818 TraceLog::GetInstance()->SetEnabled(true);
819
820 TRACE_EVENT_INSTANT0("all", "is recorded 1; system has been enabled");
821 // Trace calls that will cache pointers to categories; they're valid here
822 TraceCallsWithCachedCategoryPointersPointers(
823 "is recorded 2; system has been enabled");
824
825 TraceLog::GetInstance()->SetEnabled(false);
826 } // scope to destroy singleton
827 ASSERT_FALSE(TraceLog::GetInstance());
828
829 // Now that singleton is destroyed, check what trace events were recorded
830 DictionaryValue* item = NULL;
831 ListValue& trace_parsed = trace_parsed_;
832 EXPECT_FIND_("is recorded 1");
833 EXPECT_FIND_("is recorded 2");
834 EXPECT_NOT_FIND_("not recorded");
835
836 // Make additional trace event calls on the shutdown system. They should
837 // all pass cleanly, but the data not be recorded. We'll verify that next
838 // time around the loop (the only way to flush the trace buffers).
839 TRACE_EVENT_BEGIN_ETW("not recorded; system shutdown", 0, NULL);
840 TRACE_EVENT_END_ETW("not recorded; system shutdown", 0, NULL);
841 TRACE_EVENT_INSTANT_ETW("not recorded; system shutdown", 0, NULL);
842 TRACE_EVENT0("all", "not recorded; system shutdown");
843 TRACE_EVENT_INSTANT0("all", "not recorded; system shutdown");
844 TRACE_EVENT_BEGIN0("all", "not recorded; system shutdown");
845 TRACE_EVENT_END0("all", "not recorded; system shutdown");
846
847 TRACE_EVENT0("new category 0!", "not recorded; system shutdown");
848 TRACE_EVENT_INSTANT0("new category 1!", "not recorded; system shutdown");
849 TRACE_EVENT_BEGIN0("new category 2!", "not recorded; system shutdown");
850 TRACE_EVENT_END0("new category 3!", "not recorded; system shutdown");
851
852 // Cached categories should be safe to check, and still disable traces
853 TraceCallsWithCachedCategoryPointersPointers(
854 "not recorded; system shutdown");
855 }
856}
857
[email protected]d1f03512011-07-21 12:28:59858TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
859 // Test that the TRACE_EVENT macros do not deep-copy their string. If they
860 // do so it may indicate a performance regression, but more-over it would
861 // make the DEEP_COPY overloads redundant.
862 ManualTestSetUp();
863
864 std::string name_string("event name");
865
866 TraceLog::GetInstance()->SetEnabled(true);
867 TRACE_EVENT_INSTANT0("category", name_string.c_str());
868
869 // Modify the string in place (a wholesale reassignment may leave the old
870 // string intact on the heap).
871 name_string[0] = '@';
872
873 TraceLog::GetInstance()->SetEnabled(false);
874
875 EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
876 EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
877}
878
879TEST_F(TraceEventTestFixture, DeepCopy) {
880 ManualTestSetUp();
881
882 static const char kOriginalName1[] = "name1";
883 static const char kOriginalName2[] = "name2";
884 static const char kOriginalName3[] = "name3";
885 std::string name1(kOriginalName1);
886 std::string name2(kOriginalName2);
887 std::string name3(kOriginalName3);
888 std::string arg1("arg1");
889 std::string arg2("arg2");
890 std::string val1("val1");
891 std::string val2("val2");
892
893 TraceLog::GetInstance()->SetEnabled(true);
894 TRACE_EVENT_COPY_INSTANT0("category", name1.c_str());
895 TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
896 arg1.c_str(), 5);
897 TRACE_EVENT_COPY_END2("category", name3.c_str(),
[email protected]63bb0892011-09-06 17:56:24898 arg1.c_str(), val1,
899 arg2.c_str(), val2);
[email protected]d1f03512011-07-21 12:28:59900
901 // As per NormallyNoDeepCopy, modify the strings in place.
902 name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
903
904 TraceLog::GetInstance()->SetEnabled(false);
905
906 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
907 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
908 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
909
910 DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
911 DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
912 DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
913 ASSERT_TRUE(entry1);
914 ASSERT_TRUE(entry2);
915 ASSERT_TRUE(entry3);
916
917 int i;
918 EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
919 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
920 EXPECT_EQ(5, i);
921
922 std::string s;
923 EXPECT_TRUE(entry3->GetString("args.arg1", &s));
924 EXPECT_EQ("val1", s);
925 EXPECT_TRUE(entry3->GetString("args.arg2", &s));
926 EXPECT_EQ("val2", s);
927}
928
[email protected]366ae242011-05-10 02:23:58929} // namespace debug
930} // namespace base