blob: fc248e11c3526c32d04d3219b8ebba6fea65a456 [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]16908f172011-11-10 16:26:2313#include "base/memory/singleton.h"
[email protected]5b4926e2011-08-09 15:16:2514#include "base/process_util.h"
[email protected]366ae242011-05-10 02:23:5815#include "base/stringprintf.h"
16#include "base/synchronization/waitable_event.h"
[email protected]16908f172011-11-10 16:26:2317#include "base/threading/platform_thread.h"
[email protected]366ae242011-05-10 02:23:5818#include "base/threading/thread.h"
19#include "base/values.h"
20#include "testing/gmock/include/gmock/gmock.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23namespace base {
24namespace debug {
25
26namespace {
27
[email protected]434b02a2011-09-12 22:03:4128enum CompareOp {
29 IS_EQUAL,
30 IS_NOT_EQUAL,
31};
32
[email protected]73e5f8152011-05-13 23:30:3533struct JsonKeyValue {
34 const char* key;
35 const char* value;
[email protected]434b02a2011-09-12 22:03:4136 CompareOp op;
[email protected]73e5f8152011-05-13 23:30:3537};
38
[email protected]366ae242011-05-10 02:23:5839class TraceEventTestFixture : public testing::Test {
40 public:
[email protected]d1f03512011-07-21 12:28:5941 // This fixture does not use SetUp() because the fixture must be manually set
42 // up multiple times when testing AtExit. Use ManualTestSetUp for this.
[email protected]366ae242011-05-10 02:23:5843 void ManualTestSetUp();
[email protected]6a341fb2011-06-26 16:22:5044 void OnTraceDataCollected(
[email protected]91ea63432011-10-24 16:34:0845 scoped_refptr<TraceLog::RefCountedString> events_str);
[email protected]73e5f8152011-05-13 23:30:3546 bool FindMatchingTraceEntry(const JsonKeyValue* key_values);
47 bool FindNamePhase(const char* name, const char* phase);
[email protected]434b02a2011-09-12 22:03:4148 bool FindMatchingValue(const char* key,
49 const char* value);
50 bool FindNonMatchingValue(const char* key,
51 const char* value);
52 void Clear() {
[email protected]434b02a2011-09-12 22:03:4153 trace_parsed_.Clear();
[email protected]91ea63432011-10-24 16:34:0854 json_output_.json_output.clear();
[email protected]434b02a2011-09-12 22:03:4155 }
[email protected]366ae242011-05-10 02:23:5856
[email protected]16908f172011-11-10 16:26:2357 virtual void SetUp() {
58 old_thread_name_ = PlatformThread::GetName();
59 }
60 virtual void TearDown() {
61 PlatformThread::SetName(old_thread_name_ ? old_thread_name_ : "");
62 }
63
64 const char* old_thread_name_;
[email protected]366ae242011-05-10 02:23:5865 ListValue trace_parsed_;
[email protected]91ea63432011-10-24 16:34:0866 base::debug::TraceResultBuffer trace_buffer_;
67 base::debug::TraceResultBuffer::SimpleOutput json_output_;
[email protected]366ae242011-05-10 02:23:5868
69 private:
70 // We want our singleton torn down after each test.
71 ShadowingAtExitManager at_exit_manager_;
[email protected]19d8a902011-10-03 17:51:2572 Lock lock_;
[email protected]366ae242011-05-10 02:23:5873};
74
75void TraceEventTestFixture::ManualTestSetUp() {
[email protected]19d8a902011-10-03 17:51:2576 TraceLog::DeleteForTesting();
[email protected]366ae242011-05-10 02:23:5877 TraceLog::Resurrect();
78 TraceLog* tracelog = TraceLog::GetInstance();
79 ASSERT_TRUE(tracelog);
80 ASSERT_FALSE(tracelog->IsEnabled());
81 tracelog->SetOutputCallback(
[email protected]19d8a902011-10-03 17:51:2582 base::Bind(&TraceEventTestFixture::OnTraceDataCollected,
83 base::Unretained(this)));
[email protected]91ea63432011-10-24 16:34:0884 trace_buffer_.SetOutputCallback(json_output_.GetCallback());
[email protected]366ae242011-05-10 02:23:5885}
86
87void TraceEventTestFixture::OnTraceDataCollected(
[email protected]91ea63432011-10-24 16:34:0888 scoped_refptr<TraceLog::RefCountedString> events_str) {
[email protected]19d8a902011-10-03 17:51:2589 AutoLock lock(lock_);
[email protected]91ea63432011-10-24 16:34:0890 json_output_.json_output.clear();
91 trace_buffer_.Start();
92 trace_buffer_.AddFragment(events_str->data);
93 trace_buffer_.Finish();
[email protected]366ae242011-05-10 02:23:5894
95 scoped_ptr<Value> root;
[email protected]91ea63432011-10-24 16:34:0896 root.reset(base::JSONReader::Read(json_output_.json_output, false));
[email protected]366ae242011-05-10 02:23:5897
98 ListValue* root_list = NULL;
99 ASSERT_TRUE(root.get());
100 ASSERT_TRUE(root->GetAsList(&root_list));
101
102 // Move items into our aggregate collection
103 while (root_list->GetSize()) {
104 Value* item = NULL;
105 root_list->Remove(0, &item);
106 trace_parsed_.Append(item);
107 }
108}
109
[email protected]434b02a2011-09-12 22:03:41110static bool CompareJsonValues(const std::string& lhs,
111 const std::string& rhs,
112 CompareOp op) {
113 switch (op) {
114 case IS_EQUAL:
115 return lhs == rhs;
116 case IS_NOT_EQUAL:
117 return lhs != rhs;
118 default:
119 CHECK(0);
120 }
121 return false;
122}
123
[email protected]73e5f8152011-05-13 23:30:35124static bool IsKeyValueInDict(const JsonKeyValue* key_value,
125 DictionaryValue* dict) {
126 Value* value = NULL;
127 std::string value_str;
128 if (dict->Get(key_value->key, &value) &&
129 value->GetAsString(&value_str) &&
[email protected]434b02a2011-09-12 22:03:41130 CompareJsonValues(value_str, key_value->value, key_value->op))
[email protected]73e5f8152011-05-13 23:30:35131 return true;
132
133 // Recurse to test arguments
134 DictionaryValue* args_dict = NULL;
135 dict->GetDictionary("args", &args_dict);
136 if (args_dict)
137 return IsKeyValueInDict(key_value, args_dict);
138
139 return false;
140}
141
142static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
143 DictionaryValue* dict) {
144 // Scan all key_values, they must all be present and equal.
145 while (key_values && key_values->key) {
146 if (!IsKeyValueInDict(key_values, dict))
147 return false;
148 ++key_values;
149 }
150 return true;
151}
152
153bool TraceEventTestFixture::FindMatchingTraceEntry(
154 const JsonKeyValue* key_values) {
155 // Scan all items
156 size_t trace_parsed_count = trace_parsed_.GetSize();
157 for (size_t i = 0; i < trace_parsed_count; i++) {
158 Value* value = NULL;
159 trace_parsed_.Get(i, &value);
160 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
161 continue;
162 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
163
164 if (IsAllKeyValueInDict(key_values, dict))
165 return true;
166 }
167 return false;
168}
169
170bool TraceEventTestFixture::FindNamePhase(const char* name, const char* phase) {
171 JsonKeyValue key_values[] = {
[email protected]434b02a2011-09-12 22:03:41172 {"name", name, IS_EQUAL},
173 {"ph", phase, IS_EQUAL},
174 {0, 0, IS_EQUAL}
175 };
176 return FindMatchingTraceEntry(key_values);
177}
178
179bool TraceEventTestFixture::FindMatchingValue(const char* key,
180 const char* value) {
181 JsonKeyValue key_values[] = {
182 {key, value, IS_EQUAL},
183 {0, 0, IS_EQUAL}
184 };
185 return FindMatchingTraceEntry(key_values);
186}
187
188bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
189 const char* value) {
190 JsonKeyValue key_values[] = {
191 {key, value, IS_NOT_EQUAL},
192 {0, 0, IS_EQUAL}
[email protected]73e5f8152011-05-13 23:30:35193 };
194 return FindMatchingTraceEntry(key_values);
195}
196
[email protected]366ae242011-05-10 02:23:58197bool IsStringInDict(const char* string_to_match, DictionaryValue* dict) {
198 for (DictionaryValue::key_iterator ikey = dict->begin_keys();
199 ikey != dict->end_keys(); ++ikey) {
200 Value* child = NULL;
201 if (!dict->GetWithoutPathExpansion(*ikey, &child))
202 continue;
203
204 if ((*ikey).find(string_to_match) != std::string::npos)
205 return true;
206
207 std::string value_str;
208 child->GetAsString(&value_str);
209 if (value_str.find(string_to_match) != std::string::npos)
210 return true;
211 }
212
213 // Recurse to test arguments
214 DictionaryValue* args_dict = NULL;
215 dict->GetDictionary("args", &args_dict);
216 if (args_dict)
217 return IsStringInDict(string_to_match, args_dict);
218
219 return false;
220}
221
222DictionaryValue* FindTraceEntry(const ListValue& trace_parsed,
[email protected]5b4926e2011-08-09 15:16:25223 const char* string_to_match,
[email protected]366ae242011-05-10 02:23:58224 DictionaryValue* match_after_this_item = NULL) {
225 // Scan all items
226 size_t trace_parsed_count = trace_parsed.GetSize();
227 for (size_t i = 0; i < trace_parsed_count; i++) {
228 Value* value = NULL;
229 trace_parsed.Get(i, &value);
230 if (match_after_this_item) {
231 if (value == match_after_this_item)
232 match_after_this_item = NULL;
233 continue;
234 }
235 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
236 continue;
237 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
238
239 if (IsStringInDict(string_to_match, dict))
240 return dict;
241 }
242 return NULL;
243}
244
[email protected]5b4926e2011-08-09 15:16:25245std::vector<DictionaryValue*> FindTraceEntries(
246 const ListValue& trace_parsed,
247 const char* string_to_match) {
248 std::vector<DictionaryValue*> hits;
249 size_t trace_parsed_count = trace_parsed.GetSize();
250 for (size_t i = 0; i < trace_parsed_count; i++) {
251 Value* value = NULL;
252 trace_parsed.Get(i, &value);
253 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
254 continue;
255 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
256
257 if (IsStringInDict(string_to_match, dict))
258 hits.push_back(dict);
259 }
260 return hits;
261}
262
263void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
[email protected]366ae242011-05-10 02:23:58264 {
265 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW call", 1122, "extrastring1");
266 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW call", 3344, "extrastring2");
267 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW call",
268 5566, "extrastring3");
269
270 TRACE_EVENT0("all", "TRACE_EVENT0 call");
271 TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
272 TRACE_EVENT2("all", "TRACE_EVENT2 call",
[email protected]b3c8a152011-09-07 00:43:11273 "name1", "\"value1\"",
274 "name2", "value\\2");
[email protected]366ae242011-05-10 02:23:58275
276 TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call");
277 TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call", "name1", "value1");
278 TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
279 "name1", "value1",
280 "name2", "value2");
281
282 TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
283 TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
284 TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
285 "name1", "value1",
286 "name2", "value2");
287
288 TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
289 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
290 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
291 "name1", "value1",
292 "name2", "value2");
293 } // Scope close causes TRACE_EVENT0 etc to send their END events.
294
295 if (task_complete_event)
296 task_complete_event->Signal();
297}
298
[email protected]91ea63432011-10-24 16:34:08299void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) {
[email protected]366ae242011-05-10 02:23:58300 DictionaryValue* item = NULL;
301
302#define EXPECT_FIND_(string) \
[email protected]19d8a902011-10-03 17:51:25303 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string)));
[email protected]366ae242011-05-10 02:23:58304#define EXPECT_NOT_FIND_(string) \
[email protected]19d8a902011-10-03 17:51:25305 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string)));
[email protected]366ae242011-05-10 02:23:58306#define EXPECT_SUB_FIND_(string) \
[email protected]19d8a902011-10-03 17:51:25307 if (item) EXPECT_TRUE((IsStringInDict(string, item)));
[email protected]366ae242011-05-10 02:23:58308
309 EXPECT_FIND_("ETW Trace Event");
310 EXPECT_FIND_("all");
311 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW call");
312 {
313 int int_val = 0;
314 EXPECT_TRUE(item && item->GetInteger("args.id", &int_val));
315 EXPECT_EQ(1122, int_val);
316 }
317 EXPECT_SUB_FIND_("extrastring1");
318 EXPECT_FIND_("TRACE_EVENT_END_ETW call");
319 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW call");
320 EXPECT_FIND_("TRACE_EVENT0 call");
321 {
322 std::string ph_begin;
323 std::string ph_end;
324 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
325 EXPECT_TRUE((item && item->GetString("ph", &ph_begin)));
326 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call",
327 item)));
328 EXPECT_TRUE((item && item->GetString("ph", &ph_end)));
329 EXPECT_EQ("B", ph_begin);
330 EXPECT_EQ("E", ph_end);
331 }
332 EXPECT_FIND_("TRACE_EVENT1 call");
333 EXPECT_FIND_("TRACE_EVENT2 call");
334 EXPECT_SUB_FIND_("name1");
[email protected]b3c8a152011-09-07 00:43:11335 EXPECT_SUB_FIND_("\"value1\"");
[email protected]366ae242011-05-10 02:23:58336 EXPECT_SUB_FIND_("name2");
[email protected]b3c8a152011-09-07 00:43:11337 EXPECT_SUB_FIND_("value\\2");
[email protected]366ae242011-05-10 02:23:58338 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
339 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
340 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
341 EXPECT_SUB_FIND_("name1");
342 EXPECT_SUB_FIND_("value1");
343 EXPECT_SUB_FIND_("name2");
344 EXPECT_SUB_FIND_("value2");
345 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
346 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
347 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
348 EXPECT_SUB_FIND_("name1");
349 EXPECT_SUB_FIND_("value1");
350 EXPECT_SUB_FIND_("name2");
351 EXPECT_SUB_FIND_("value2");
352 EXPECT_FIND_("TRACE_EVENT_END0 call");
353 EXPECT_FIND_("TRACE_EVENT_END1 call");
354 EXPECT_FIND_("TRACE_EVENT_END2 call");
355 EXPECT_SUB_FIND_("name1");
356 EXPECT_SUB_FIND_("value1");
357 EXPECT_SUB_FIND_("name2");
358 EXPECT_SUB_FIND_("value2");
359}
360
[email protected]5b4926e2011-08-09 15:16:25361void TraceManyInstantEvents(int thread_id, int num_events,
[email protected]91ea63432011-10-24 16:34:08362 WaitableEvent* task_complete_event) {
[email protected]5b4926e2011-08-09 15:16:25363 for (int i = 0; i < num_events; i++) {
364 TRACE_EVENT_INSTANT2("all", "multi thread event",
365 "thread", thread_id,
366 "event", i);
367 }
368
369 if (task_complete_event)
370 task_complete_event->Signal();
371}
372
373void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed,
[email protected]91ea63432011-10-24 16:34:08374 int num_threads,
375 int num_events) {
[email protected]5b4926e2011-08-09 15:16:25376 std::map<int, std::map<int, bool> > results;
377
378 size_t trace_parsed_count = trace_parsed.GetSize();
379 for (size_t i = 0; i < trace_parsed_count; i++) {
380 Value* value = NULL;
381 trace_parsed.Get(i, &value);
382 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
383 continue;
384 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
385 std::string name;
386 dict->GetString("name", &name);
387 if (name != "multi thread event")
388 continue;
389
390 int thread = 0;
391 int event = 0;
392 EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
393 EXPECT_TRUE(dict->GetInteger("args.event", &event));
394 results[thread][event] = true;
395 }
396
397 EXPECT_FALSE(results[-1][-1]);
398 for (int thread = 0; thread < num_threads; thread++) {
399 for (int event = 0; event < num_events; event++) {
400 EXPECT_TRUE(results[thread][event]);
401 }
402 }
403}
404
405void TraceCallsWithCachedCategoryPointersPointers(const char* name_str) {
406 TRACE_EVENT0("category name1", name_str);
407 TRACE_EVENT_INSTANT0("category name2", name_str);
408 TRACE_EVENT_BEGIN0("category name3", name_str);
409 TRACE_EVENT_END0("category name4", name_str);
410}
411
[email protected]366ae242011-05-10 02:23:58412} // namespace
413
414// Simple Test for emitting data and validating it was received.
415TEST_F(TraceEventTestFixture, DataCaptured) {
416 ManualTestSetUp();
417 TraceLog::GetInstance()->SetEnabled(true);
418
[email protected]5b4926e2011-08-09 15:16:25419 TraceWithAllMacroVariants(NULL);
[email protected]366ae242011-05-10 02:23:58420
421 TraceLog::GetInstance()->SetEnabled(false);
422
[email protected]91ea63432011-10-24 16:34:08423 ValidateAllTraceMacrosCreatedData(trace_parsed_);
[email protected]366ae242011-05-10 02:23:58424}
425
[email protected]434b02a2011-09-12 22:03:41426// Test that categories work.
427TEST_F(TraceEventTestFixture, Categories) {
428 ManualTestSetUp();
429
430 // Test that categories that are used can be retrieved whether trace was
431 // enabled or disabled when the trace event was encountered.
432 TRACE_EVENT_INSTANT0("c1", "name");
433 TRACE_EVENT_INSTANT0("c2", "name");
434 TraceLog::GetInstance()->SetEnabled(true);
435 TRACE_EVENT_INSTANT0("c3", "name");
436 TRACE_EVENT_INSTANT0("c4", "name");
437 TraceLog::GetInstance()->SetEnabled(false);
438 std::vector<std::string> cats;
439 TraceLog::GetInstance()->GetKnownCategories(&cats);
440 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c1") != cats.end());
441 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c2") != cats.end());
442 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c3") != cats.end());
443 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c4") != cats.end());
444
445 const std::vector<std::string> empty_categories;
446 std::vector<std::string> included_categories;
447 std::vector<std::string> excluded_categories;
448
449 // Test that category filtering works.
450
451 // Include nonexistent category -> no events
452 Clear();
453 included_categories.clear();
454 included_categories.push_back("not_found823564786");
455 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
456 TRACE_EVENT_INSTANT0("cat1", "name");
457 TRACE_EVENT_INSTANT0("cat2", "name");
458 TraceLog::GetInstance()->SetDisabled();
459 EXPECT_TRUE(trace_parsed_.empty());
460
461 // Include existent category -> only events of that category
462 Clear();
463 included_categories.clear();
464 included_categories.push_back("inc");
465 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
466 TRACE_EVENT_INSTANT0("inc", "name");
467 TRACE_EVENT_INSTANT0("inc2", "name");
468 TraceLog::GetInstance()->SetDisabled();
469 EXPECT_TRUE(FindMatchingValue("cat", "inc"));
470 EXPECT_FALSE(FindNonMatchingValue("cat", "inc"));
471
472 // Include existent wildcard -> all categories matching wildcard
473 Clear();
474 included_categories.clear();
475 included_categories.push_back("inc_wildcard_*");
476 included_categories.push_back("inc_wildchar_?_end");
477 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
478 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "included");
479 TRACE_EVENT_INSTANT0("inc_wildcard_", "included");
480 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "included");
481 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "not_inc");
482 TRACE_EVENT_INSTANT0("cat1", "not_inc");
483 TRACE_EVENT_INSTANT0("cat2", "not_inc");
484 TraceLog::GetInstance()->SetDisabled();
485 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_abc"));
486 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_"));
487 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_x_end"));
488 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
489
490 included_categories.clear();
491
492 // Exclude nonexistent category -> all events
493 Clear();
494 excluded_categories.clear();
495 excluded_categories.push_back("not_found823564786");
496 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
497 TRACE_EVENT_INSTANT0("cat1", "name");
498 TRACE_EVENT_INSTANT0("cat2", "name");
499 TraceLog::GetInstance()->SetDisabled();
500 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
501 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
502
503 // Exclude existent category -> only events of other categories
504 Clear();
505 excluded_categories.clear();
506 excluded_categories.push_back("inc");
507 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
508 TRACE_EVENT_INSTANT0("inc", "name");
509 TRACE_EVENT_INSTANT0("inc2", "name");
510 TraceLog::GetInstance()->SetDisabled();
511 EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
512 EXPECT_FALSE(FindMatchingValue("cat", "inc"));
513
514 // Exclude existent wildcard -> all categories not matching wildcard
515 Clear();
516 excluded_categories.clear();
517 excluded_categories.push_back("inc_wildcard_*");
518 excluded_categories.push_back("inc_wildchar_?_end");
519 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
520 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "not_inc");
521 TRACE_EVENT_INSTANT0("inc_wildcard_", "not_inc");
522 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "not_inc");
523 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "included");
524 TRACE_EVENT_INSTANT0("cat1", "included");
525 TRACE_EVENT_INSTANT0("cat2", "included");
526 TraceLog::GetInstance()->SetDisabled();
527 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_bla_end"));
528 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
529 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
530 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
531}
532
[email protected]73e5f8152011-05-13 23:30:35533// Simple Test for time threshold events.
534TEST_F(TraceEventTestFixture, DataCapturedThreshold) {
535 ManualTestSetUp();
536 TraceLog::GetInstance()->SetEnabled(true);
537
538 // Test that events at the same level are properly filtered by threshold.
539 {
540 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "threshold 100");
541 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "threshold 1000");
542 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "threshold 10000");
543 // 100+ seconds to avoid flakiness.
544 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "threshold long1");
545 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "threshold long2");
546 base::PlatformThread::Sleep(20); // 20000 us
547 }
548
549 // Test that a normal nested event remains after it's parent event is dropped.
550 {
551 TRACE_EVENT_IF_LONGER_THAN0(1000000, "time", "2threshold10000");
552 {
553 TRACE_EVENT0("time", "nonthreshold1");
554 }
555 }
556
557 // Test that parent thresholded events are dropped while some nested events
558 // remain.
559 {
560 TRACE_EVENT0("time", "nonthreshold3");
561 {
562 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "3thresholdlong2");
563 {
564 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "3thresholdlong1");
565 {
566 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "3threshold10000");
567 {
568 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "3threshold1000");
569 {
570 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "3threshold100");
571 base::PlatformThread::Sleep(20);
572 }
573 }
574 }
575 }
576 }
577 }
578
579 // Test that child thresholded events are dropped while some parent events
580 // remain.
581 {
582 TRACE_EVENT0("time", "nonthreshold4");
583 {
584 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "4threshold100");
585 {
586 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "4threshold1000");
587 {
588 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "4threshold10000");
589 {
590 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time",
591 "4thresholdlong1");
592 {
593 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time",
594 "4thresholdlong2");
595 base::PlatformThread::Sleep(20);
596 }
597 }
598 }
599 }
600 }
601 }
602
603 TraceLog::GetInstance()->SetEnabled(false);
604
605#define EXPECT_FIND_BE_(str) \
606 EXPECT_TRUE(FindNamePhase(str, "B")); \
607 EXPECT_TRUE(FindNamePhase(str, "E"))
608#define EXPECT_NOT_FIND_BE_(str) \
609 EXPECT_FALSE(FindNamePhase(str, "B")); \
610 EXPECT_FALSE(FindNamePhase(str, "E"))
611
612 EXPECT_FIND_BE_("threshold 100");
613 EXPECT_FIND_BE_("threshold 1000");
614 EXPECT_FIND_BE_("threshold 10000");
615 EXPECT_NOT_FIND_BE_("threshold long1");
616 EXPECT_NOT_FIND_BE_("threshold long2");
617
618 EXPECT_NOT_FIND_BE_("2threshold10000");
619 EXPECT_FIND_BE_("nonthreshold1");
620
621 EXPECT_FIND_BE_("nonthreshold3");
622 EXPECT_FIND_BE_("3threshold100");
623 EXPECT_FIND_BE_("3threshold1000");
624 EXPECT_FIND_BE_("3threshold10000");
625 EXPECT_NOT_FIND_BE_("3thresholdlong1");
626 EXPECT_NOT_FIND_BE_("3thresholdlong2");
627
628 EXPECT_FIND_BE_("nonthreshold4");
629 EXPECT_FIND_BE_("4threshold100");
630 EXPECT_FIND_BE_("4threshold1000");
631 EXPECT_FIND_BE_("4threshold10000");
632 EXPECT_NOT_FIND_BE_("4thresholdlong1");
633 EXPECT_NOT_FIND_BE_("4thresholdlong2");
634}
635
[email protected]63bb0892011-09-06 17:56:24636// Test that static strings are not copied.
637TEST_F(TraceEventTestFixture, StaticStringVsString) {
638 ManualTestSetUp();
639 TraceLog* tracer = TraceLog::GetInstance();
640 // Make sure old events are flushed:
641 tracer->SetEnabled(false);
642 EXPECT_EQ(0u, tracer->GetEventsSize());
643
644 {
645 tracer->SetEnabled(true);
646 // Test that string arguments are copied.
647 TRACE_EVENT2("cat", "name1",
648 "arg1", std::string("argval"), "arg2", std::string("argval"));
649 // Test that static TRACE_STR_COPY string arguments are copied.
650 TRACE_EVENT2("cat", "name2",
651 "arg1", TRACE_STR_COPY("argval"),
652 "arg2", TRACE_STR_COPY("argval"));
653 size_t num_events = tracer->GetEventsSize();
654 EXPECT_GT(num_events, 1u);
655 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
656 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
657 EXPECT_STREQ("name1", event1.name());
658 EXPECT_STREQ("name2", event2.name());
659 EXPECT_TRUE(event1.parameter_copy_storage() != NULL);
660 EXPECT_TRUE(event2.parameter_copy_storage() != NULL);
661 EXPECT_GT(event1.parameter_copy_storage()->size(), 0u);
662 EXPECT_GT(event2.parameter_copy_storage()->size(), 0u);
663 tracer->SetEnabled(false);
664 }
665
666 {
667 tracer->SetEnabled(true);
668 // Test that static literal string arguments are not copied.
669 TRACE_EVENT2("cat", "name1",
670 "arg1", "argval", "arg2", "argval");
671 // Test that static TRACE_STR_COPY NULL string arguments are not copied.
672 const char* str1 = NULL;
673 const char* str2 = NULL;
674 TRACE_EVENT2("cat", "name2",
675 "arg1", TRACE_STR_COPY(str1),
676 "arg2", TRACE_STR_COPY(str2));
677 size_t num_events = tracer->GetEventsSize();
678 EXPECT_GT(num_events, 1u);
679 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
680 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
681 EXPECT_STREQ("name1", event1.name());
682 EXPECT_STREQ("name2", event2.name());
683 EXPECT_TRUE(event1.parameter_copy_storage() == NULL);
684 EXPECT_TRUE(event2.parameter_copy_storage() == NULL);
685 tracer->SetEnabled(false);
686 }
687}
688
[email protected]366ae242011-05-10 02:23:58689// Test that data sent from other threads is gathered
690TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
691 ManualTestSetUp();
692 TraceLog::GetInstance()->SetEnabled(true);
693
694 Thread thread("1");
695 WaitableEvent task_complete_event(false, false);
696 thread.Start();
697
698 thread.message_loop()->PostTask(
[email protected]f4412a882011-10-05 16:58:20699 FROM_HERE, base::Bind(&TraceWithAllMacroVariants, &task_complete_event));
[email protected]366ae242011-05-10 02:23:58700 task_complete_event.Wait();
[email protected]19d8a902011-10-03 17:51:25701 thread.Stop();
[email protected]366ae242011-05-10 02:23:58702
703 TraceLog::GetInstance()->SetEnabled(false);
[email protected]91ea63432011-10-24 16:34:08704 ValidateAllTraceMacrosCreatedData(trace_parsed_);
[email protected]366ae242011-05-10 02:23:58705}
706
[email protected]366ae242011-05-10 02:23:58707// Test that data sent from multiple threads is gathered
708TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
709 ManualTestSetUp();
710 TraceLog::GetInstance()->SetEnabled(true);
711
712 const int num_threads = 4;
713 const int num_events = 4000;
714 Thread* threads[num_threads];
715 WaitableEvent* task_complete_events[num_threads];
716 for (int i = 0; i < num_threads; i++) {
717 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
718 task_complete_events[i] = new WaitableEvent(false, false);
719 threads[i]->Start();
720 threads[i]->message_loop()->PostTask(
[email protected]f4412a882011-10-05 16:58:20721 FROM_HERE, base::Bind(&TraceManyInstantEvents,
722 i, num_events, task_complete_events[i]));
[email protected]366ae242011-05-10 02:23:58723 }
724
725 for (int i = 0; i < num_threads; i++) {
726 task_complete_events[i]->Wait();
727 }
728
[email protected]366ae242011-05-10 02:23:58729 for (int i = 0; i < num_threads; i++) {
730 threads[i]->Stop();
731 delete threads[i];
732 delete task_complete_events[i];
733 }
734
[email protected]19d8a902011-10-03 17:51:25735 TraceLog::GetInstance()->SetEnabled(false);
736
[email protected]91ea63432011-10-24 16:34:08737 ValidateInstantEventPresentOnEveryThread(trace_parsed_,
[email protected]5b4926e2011-08-09 15:16:25738 num_threads, num_events);
[email protected]366ae242011-05-10 02:23:58739}
740
[email protected]5b4926e2011-08-09 15:16:25741// Test that thread and process names show up in the trace
742TEST_F(TraceEventTestFixture, ThreadNames) {
743 ManualTestSetUp();
744
745 // Create threads before we enable tracing to make sure
746 // that tracelog still captures them.
747 const int num_threads = 4;
748 const int num_events = 10;
749 Thread* threads[num_threads];
750 PlatformThreadId thread_ids[num_threads];
751 for (int i = 0; i < num_threads; i++)
752 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
753
754 // Enable tracing.
755 TraceLog::GetInstance()->SetEnabled(true);
756
757 // Now run some trace code on these threads.
758 WaitableEvent* task_complete_events[num_threads];
759 for (int i = 0; i < num_threads; i++) {
760 task_complete_events[i] = new WaitableEvent(false, false);
761 threads[i]->Start();
762 thread_ids[i] = threads[i]->thread_id();
763 threads[i]->message_loop()->PostTask(
[email protected]f4412a882011-10-05 16:58:20764 FROM_HERE, base::Bind(&TraceManyInstantEvents,
765 i, num_events, task_complete_events[i]));
[email protected]5b4926e2011-08-09 15:16:25766 }
767 for (int i = 0; i < num_threads; i++) {
768 task_complete_events[i]->Wait();
769 }
770
771 // Shut things down.
[email protected]5b4926e2011-08-09 15:16:25772 for (int i = 0; i < num_threads; i++) {
773 threads[i]->Stop();
774 delete threads[i];
775 delete task_complete_events[i];
776 }
777
[email protected]19d8a902011-10-03 17:51:25778 TraceLog::GetInstance()->SetEnabled(false);
779
[email protected]5b4926e2011-08-09 15:16:25780 std::string tmp;
781 int tmp_int;
782 DictionaryValue* item;
783
784 // Make sure we get thread name metadata.
785 // Note, the test suite may have created a ton of threads.
786 // So, we'll have thread names for threads we didn't create.
787 std::vector<DictionaryValue*> items =
788 FindTraceEntries(trace_parsed_, "thread_name");
789 for (int i = 0; i < static_cast<int>(items.size()); i++) {
790 item = items[i];
[email protected]16908f172011-11-10 16:26:23791 ASSERT_TRUE(item);
[email protected]5b4926e2011-08-09 15:16:25792 EXPECT_TRUE(item->GetInteger("tid", &tmp_int));
793
794 // See if this thread name is one of the threads we just created
795 for (int j = 0; j < num_threads; j++) {
796 if(static_cast<int>(thread_ids[j]) != tmp_int)
797 continue;
798
799 std::string expected_name = StringPrintf("Thread %d", j).c_str();
800 EXPECT_TRUE(item->GetString("ph", &tmp) && tmp == "M");
801 EXPECT_TRUE(item->GetInteger("pid", &tmp_int) &&
802 tmp_int == static_cast<int>(base::GetCurrentProcId()));
803 EXPECT_TRUE(item->GetString("args.name", &tmp) &&
804 tmp == expected_name);
805 }
806 }
[email protected]366ae242011-05-10 02:23:58807}
808
[email protected]16908f172011-11-10 16:26:23809TEST_F(TraceEventTestFixture, ThreadNameChanges) {
810 ManualTestSetUp();
811
812 TraceLog::GetInstance()->SetEnabled(true);
813
814 PlatformThread::SetName("");
815 TRACE_EVENT_INSTANT0("drink", "water");
816
817 PlatformThread::SetName("cafe");
818 TRACE_EVENT_INSTANT0("drink", "coffee");
819
820 PlatformThread::SetName("shop");
821 // No event here, so won't appear in combined name.
822
823 PlatformThread::SetName("pub");
824 TRACE_EVENT_INSTANT0("drink", "beer");
825 TRACE_EVENT_INSTANT0("drink", "wine");
826
827 PlatformThread::SetName(" bar");
828 TRACE_EVENT_INSTANT0("drink", "whisky");
829
830 TraceLog::GetInstance()->SetEnabled(false);
831
832 std::vector<DictionaryValue*> items =
833 FindTraceEntries(trace_parsed_, "thread_name");
834 EXPECT_EQ(1u, items.size());
835 ASSERT_GT(items.size(), 0u);
836 DictionaryValue* item = items[0];
837 ASSERT_TRUE(item);
838 int tid;
839 EXPECT_TRUE(item->GetInteger("tid", &tid));
840 EXPECT_EQ(PlatformThread::CurrentId(), static_cast<PlatformThreadId>(tid));
841
842 std::string expected_name = "cafe,pub, bar";
843 std::string tmp;
844 EXPECT_TRUE(item->GetString("args.name", &tmp));
845 EXPECT_EQ(expected_name, tmp);
846}
[email protected]5b4926e2011-08-09 15:16:25847
[email protected]366ae242011-05-10 02:23:58848// Test trace calls made after tracing singleton shut down.
849//
850// The singleton is destroyed by our base::AtExitManager, but there can be
851// code still executing as the C++ static objects are destroyed. This test
852// forces the singleton to destroy early, and intentinally makes trace calls
853// afterwards.
854TEST_F(TraceEventTestFixture, AtExit) {
855 // Repeat this test a few times. Besides just showing robustness, it also
856 // allows us to test that events at shutdown do not appear with valid events
857 // recorded after the system is started again.
858 for (int i = 0; i < 4; i++) {
859 // Scope to contain the then destroy the TraceLog singleton.
860 {
861 base::ShadowingAtExitManager exit_manager_will_destroy_singletons;
862
863 // Setup TraceLog singleton inside this test's exit manager scope
864 // so that it will be destroyed when this scope closes.
865 ManualTestSetUp();
866
867 TRACE_EVENT_INSTANT0("all", "not recorded; system not enabled");
868
869 TraceLog::GetInstance()->SetEnabled(true);
870
871 TRACE_EVENT_INSTANT0("all", "is recorded 1; system has been enabled");
872 // Trace calls that will cache pointers to categories; they're valid here
873 TraceCallsWithCachedCategoryPointersPointers(
874 "is recorded 2; system has been enabled");
875
876 TraceLog::GetInstance()->SetEnabled(false);
877 } // scope to destroy singleton
878 ASSERT_FALSE(TraceLog::GetInstance());
879
880 // Now that singleton is destroyed, check what trace events were recorded
881 DictionaryValue* item = NULL;
882 ListValue& trace_parsed = trace_parsed_;
883 EXPECT_FIND_("is recorded 1");
884 EXPECT_FIND_("is recorded 2");
885 EXPECT_NOT_FIND_("not recorded");
886
887 // Make additional trace event calls on the shutdown system. They should
888 // all pass cleanly, but the data not be recorded. We'll verify that next
889 // time around the loop (the only way to flush the trace buffers).
890 TRACE_EVENT_BEGIN_ETW("not recorded; system shutdown", 0, NULL);
891 TRACE_EVENT_END_ETW("not recorded; system shutdown", 0, NULL);
892 TRACE_EVENT_INSTANT_ETW("not recorded; system shutdown", 0, NULL);
893 TRACE_EVENT0("all", "not recorded; system shutdown");
894 TRACE_EVENT_INSTANT0("all", "not recorded; system shutdown");
895 TRACE_EVENT_BEGIN0("all", "not recorded; system shutdown");
896 TRACE_EVENT_END0("all", "not recorded; system shutdown");
897
898 TRACE_EVENT0("new category 0!", "not recorded; system shutdown");
899 TRACE_EVENT_INSTANT0("new category 1!", "not recorded; system shutdown");
900 TRACE_EVENT_BEGIN0("new category 2!", "not recorded; system shutdown");
901 TRACE_EVENT_END0("new category 3!", "not recorded; system shutdown");
902
903 // Cached categories should be safe to check, and still disable traces
904 TraceCallsWithCachedCategoryPointersPointers(
905 "not recorded; system shutdown");
906 }
907}
908
[email protected]d1f03512011-07-21 12:28:59909TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
910 // Test that the TRACE_EVENT macros do not deep-copy their string. If they
911 // do so it may indicate a performance regression, but more-over it would
912 // make the DEEP_COPY overloads redundant.
913 ManualTestSetUp();
914
915 std::string name_string("event name");
916
917 TraceLog::GetInstance()->SetEnabled(true);
918 TRACE_EVENT_INSTANT0("category", name_string.c_str());
919
920 // Modify the string in place (a wholesale reassignment may leave the old
921 // string intact on the heap).
922 name_string[0] = '@';
923
924 TraceLog::GetInstance()->SetEnabled(false);
925
926 EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
927 EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
928}
929
930TEST_F(TraceEventTestFixture, DeepCopy) {
931 ManualTestSetUp();
932
933 static const char kOriginalName1[] = "name1";
934 static const char kOriginalName2[] = "name2";
935 static const char kOriginalName3[] = "name3";
936 std::string name1(kOriginalName1);
937 std::string name2(kOriginalName2);
938 std::string name3(kOriginalName3);
939 std::string arg1("arg1");
940 std::string arg2("arg2");
941 std::string val1("val1");
942 std::string val2("val2");
943
944 TraceLog::GetInstance()->SetEnabled(true);
945 TRACE_EVENT_COPY_INSTANT0("category", name1.c_str());
946 TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
947 arg1.c_str(), 5);
948 TRACE_EVENT_COPY_END2("category", name3.c_str(),
[email protected]63bb0892011-09-06 17:56:24949 arg1.c_str(), val1,
950 arg2.c_str(), val2);
[email protected]d1f03512011-07-21 12:28:59951
952 // As per NormallyNoDeepCopy, modify the strings in place.
953 name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
954
955 TraceLog::GetInstance()->SetEnabled(false);
956
957 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
958 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
959 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
960
961 DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
962 DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
963 DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
964 ASSERT_TRUE(entry1);
965 ASSERT_TRUE(entry2);
966 ASSERT_TRUE(entry3);
967
968 int i;
969 EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
970 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
971 EXPECT_EQ(5, i);
972
973 std::string s;
974 EXPECT_TRUE(entry3->GetString("args.arg1", &s));
975 EXPECT_EQ("val1", s);
976 EXPECT_TRUE(entry3->GetString("args.arg2", &s));
977 EXPECT_EQ("val2", s);
978}
979
[email protected]91ea63432011-10-24 16:34:08980// Test that TraceResultBuffer outputs the correct result whether it is added
981// in chunks or added all at once.
982TEST_F(TraceEventTestFixture, TraceResultBuffer) {
983 ManualTestSetUp();
984
985 Clear();
986
987 trace_buffer_.Start();
988 trace_buffer_.AddFragment("bla1");
989 trace_buffer_.AddFragment("bla2");
990 trace_buffer_.AddFragment("bla3,bla4");
991 trace_buffer_.Finish();
992 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
993
994 Clear();
995
996 trace_buffer_.Start();
997 trace_buffer_.AddFragment("bla1,bla2,bla3,bla4");
998 trace_buffer_.Finish();
999 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1000}
1001
[email protected]366ae242011-05-10 02:23:581002} // namespace debug
1003} // namespace base