blob: cb77feecc65b5e3cde1bf16b3964036a228e8fb3 [file] [log] [blame]
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001// 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"
jbates@chromium.org1f18e462011-09-07 02:56:24 +090011#include "base/memory/ref_counted_memory.h"
scheib@chromium.org603f46e2011-05-10 11:23:58 +090012#include "base/memory/scoped_ptr.h"
joth@chromium.org088ae012011-11-11 01:26:23 +090013#include "base/memory/singleton.h"
nduca@chromium.org6d048772011-08-10 00:16:25 +090014#include "base/process_util.h"
scheib@chromium.org603f46e2011-05-10 11:23:58 +090015#include "base/stringprintf.h"
16#include "base/synchronization/waitable_event.h"
joth@chromium.org088ae012011-11-11 01:26:23 +090017#include "base/threading/platform_thread.h"
scheib@chromium.org603f46e2011-05-10 11:23:58 +090018#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
jbates@chromium.org11d4c362011-09-13 07:03:41 +090028enum CompareOp {
29 IS_EQUAL,
30 IS_NOT_EQUAL,
31};
32
jbates@chromium.orgb3cab862011-05-14 08:30:35 +090033struct JsonKeyValue {
34 const char* key;
35 const char* value;
jbates@chromium.org11d4c362011-09-13 07:03:41 +090036 CompareOp op;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +090037};
38
scheib@chromium.org603f46e2011-05-10 11:23:58 +090039class TraceEventTestFixture : public testing::Test {
40 public:
joth@chromium.org113de992011-07-21 21:28:59 +090041 // This fixture does not use SetUp() because the fixture must be manually set
42 // up multiple times when testing AtExit. Use ManualTestSetUp for this.
scheib@chromium.org603f46e2011-05-10 11:23:58 +090043 void ManualTestSetUp();
ajwong@chromium.orgec1750a2011-06-27 01:22:50 +090044 void OnTraceDataCollected(
ajwong@chromium.orgabd70002011-12-20 09:10:04 +090045 const scoped_refptr<TraceLog::RefCountedString>& events_str);
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +090046 DictionaryValue* FindMatchingTraceEntry(const JsonKeyValue* key_values);
47 DictionaryValue* FindNamePhase(const char* name, const char* phase);
48 DictionaryValue* FindNamePhaseKeyValue(const char* name,
49 const char* phase,
50 const char* key,
51 const char* value);
jbates@chromium.org11d4c362011-09-13 07:03:41 +090052 bool FindMatchingValue(const char* key,
53 const char* value);
54 bool FindNonMatchingValue(const char* key,
55 const char* value);
56 void Clear() {
jbates@chromium.org11d4c362011-09-13 07:03:41 +090057 trace_parsed_.Clear();
jbates@chromium.org6a092d72011-10-25 01:34:08 +090058 json_output_.json_output.clear();
jbates@chromium.org11d4c362011-09-13 07:03:41 +090059 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +090060
joth@chromium.org088ae012011-11-11 01:26:23 +090061 virtual void SetUp() {
62 old_thread_name_ = PlatformThread::GetName();
63 }
64 virtual void TearDown() {
65 PlatformThread::SetName(old_thread_name_ ? old_thread_name_ : "");
66 }
67
68 const char* old_thread_name_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090069 ListValue trace_parsed_;
jbates@chromium.org6a092d72011-10-25 01:34:08 +090070 base::debug::TraceResultBuffer trace_buffer_;
71 base::debug::TraceResultBuffer::SimpleOutput json_output_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090072
73 private:
74 // We want our singleton torn down after each test.
75 ShadowingAtExitManager at_exit_manager_;
jbates@chromium.orgb84db522011-10-04 02:51:25 +090076 Lock lock_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090077};
78
79void TraceEventTestFixture::ManualTestSetUp() {
jbates@chromium.orgb84db522011-10-04 02:51:25 +090080 TraceLog::DeleteForTesting();
scheib@chromium.org603f46e2011-05-10 11:23:58 +090081 TraceLog::Resurrect();
82 TraceLog* tracelog = TraceLog::GetInstance();
83 ASSERT_TRUE(tracelog);
84 ASSERT_FALSE(tracelog->IsEnabled());
85 tracelog->SetOutputCallback(
jbates@chromium.orgb84db522011-10-04 02:51:25 +090086 base::Bind(&TraceEventTestFixture::OnTraceDataCollected,
87 base::Unretained(this)));
jbates@chromium.org6a092d72011-10-25 01:34:08 +090088 trace_buffer_.SetOutputCallback(json_output_.GetCallback());
scheib@chromium.org603f46e2011-05-10 11:23:58 +090089}
90
91void TraceEventTestFixture::OnTraceDataCollected(
ajwong@chromium.orgabd70002011-12-20 09:10:04 +090092 const scoped_refptr<TraceLog::RefCountedString>& events_str) {
jbates@chromium.orgb84db522011-10-04 02:51:25 +090093 AutoLock lock(lock_);
jbates@chromium.org6a092d72011-10-25 01:34:08 +090094 json_output_.json_output.clear();
95 trace_buffer_.Start();
96 trace_buffer_.AddFragment(events_str->data);
97 trace_buffer_.Finish();
scheib@chromium.org603f46e2011-05-10 11:23:58 +090098
99 scoped_ptr<Value> root;
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900100 root.reset(base::JSONReader::Read(json_output_.json_output, false));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900101
102 ListValue* root_list = NULL;
103 ASSERT_TRUE(root.get());
104 ASSERT_TRUE(root->GetAsList(&root_list));
105
106 // Move items into our aggregate collection
107 while (root_list->GetSize()) {
108 Value* item = NULL;
109 root_list->Remove(0, &item);
110 trace_parsed_.Append(item);
111 }
112}
113
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900114static bool CompareJsonValues(const std::string& lhs,
115 const std::string& rhs,
116 CompareOp op) {
117 switch (op) {
118 case IS_EQUAL:
119 return lhs == rhs;
120 case IS_NOT_EQUAL:
121 return lhs != rhs;
122 default:
123 CHECK(0);
124 }
125 return false;
126}
127
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900128static bool IsKeyValueInDict(const JsonKeyValue* key_value,
129 DictionaryValue* dict) {
130 Value* value = NULL;
131 std::string value_str;
132 if (dict->Get(key_value->key, &value) &&
133 value->GetAsString(&value_str) &&
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900134 CompareJsonValues(value_str, key_value->value, key_value->op))
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900135 return true;
136
137 // Recurse to test arguments
138 DictionaryValue* args_dict = NULL;
139 dict->GetDictionary("args", &args_dict);
140 if (args_dict)
141 return IsKeyValueInDict(key_value, args_dict);
142
143 return false;
144}
145
146static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
147 DictionaryValue* dict) {
148 // Scan all key_values, they must all be present and equal.
149 while (key_values && key_values->key) {
150 if (!IsKeyValueInDict(key_values, dict))
151 return false;
152 ++key_values;
153 }
154 return true;
155}
156
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900157DictionaryValue* TraceEventTestFixture::FindMatchingTraceEntry(
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900158 const JsonKeyValue* key_values) {
159 // Scan all items
160 size_t trace_parsed_count = trace_parsed_.GetSize();
161 for (size_t i = 0; i < trace_parsed_count; i++) {
162 Value* value = NULL;
163 trace_parsed_.Get(i, &value);
164 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
165 continue;
166 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
167
168 if (IsAllKeyValueInDict(key_values, dict))
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900169 return dict;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900170 }
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900171 return NULL;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900172}
173
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900174DictionaryValue* TraceEventTestFixture::FindNamePhase(const char* name,
175 const char* phase) {
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900176 JsonKeyValue key_values[] = {
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900177 {"name", name, IS_EQUAL},
178 {"ph", phase, IS_EQUAL},
179 {0, 0, IS_EQUAL}
180 };
181 return FindMatchingTraceEntry(key_values);
182}
183
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900184DictionaryValue* TraceEventTestFixture::FindNamePhaseKeyValue(
185 const char* name,
186 const char* phase,
187 const char* key,
188 const char* value) {
189 JsonKeyValue key_values[] = {
190 {"name", name, IS_EQUAL},
191 {"ph", phase, IS_EQUAL},
192 {key, value, IS_EQUAL},
193 {0, 0, IS_EQUAL}
194 };
195 return FindMatchingTraceEntry(key_values);
196}
197
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900198bool TraceEventTestFixture::FindMatchingValue(const char* key,
199 const char* value) {
200 JsonKeyValue key_values[] = {
201 {key, value, IS_EQUAL},
202 {0, 0, IS_EQUAL}
203 };
204 return FindMatchingTraceEntry(key_values);
205}
206
207bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
208 const char* value) {
209 JsonKeyValue key_values[] = {
210 {key, value, IS_NOT_EQUAL},
211 {0, 0, IS_EQUAL}
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900212 };
213 return FindMatchingTraceEntry(key_values);
214}
215
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900216bool IsStringInDict(const char* string_to_match, DictionaryValue* dict) {
217 for (DictionaryValue::key_iterator ikey = dict->begin_keys();
218 ikey != dict->end_keys(); ++ikey) {
219 Value* child = NULL;
220 if (!dict->GetWithoutPathExpansion(*ikey, &child))
221 continue;
222
223 if ((*ikey).find(string_to_match) != std::string::npos)
224 return true;
225
226 std::string value_str;
227 child->GetAsString(&value_str);
228 if (value_str.find(string_to_match) != std::string::npos)
229 return true;
230 }
231
232 // Recurse to test arguments
233 DictionaryValue* args_dict = NULL;
234 dict->GetDictionary("args", &args_dict);
235 if (args_dict)
236 return IsStringInDict(string_to_match, args_dict);
237
238 return false;
239}
240
241DictionaryValue* FindTraceEntry(const ListValue& trace_parsed,
nduca@chromium.org6d048772011-08-10 00:16:25 +0900242 const char* string_to_match,
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900243 DictionaryValue* match_after_this_item = NULL) {
244 // Scan all items
245 size_t trace_parsed_count = trace_parsed.GetSize();
246 for (size_t i = 0; i < trace_parsed_count; i++) {
247 Value* value = NULL;
248 trace_parsed.Get(i, &value);
249 if (match_after_this_item) {
250 if (value == match_after_this_item)
251 match_after_this_item = NULL;
252 continue;
253 }
254 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
255 continue;
256 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
257
258 if (IsStringInDict(string_to_match, dict))
259 return dict;
260 }
261 return NULL;
262}
263
nduca@chromium.org6d048772011-08-10 00:16:25 +0900264std::vector<DictionaryValue*> FindTraceEntries(
265 const ListValue& trace_parsed,
266 const char* string_to_match) {
267 std::vector<DictionaryValue*> hits;
268 size_t trace_parsed_count = trace_parsed.GetSize();
269 for (size_t i = 0; i < trace_parsed_count; i++) {
270 Value* value = NULL;
271 trace_parsed.Get(i, &value);
272 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
273 continue;
274 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
275
276 if (IsStringInDict(string_to_match, dict))
277 hits.push_back(dict);
278 }
279 return hits;
280}
281
282void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900283 {
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900284 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW call", 0x1122, "extrastring1");
285 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW call", 0x3344, "extrastring2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900286 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW call",
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900287 0x5566, "extrastring3");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900288
289 TRACE_EVENT0("all", "TRACE_EVENT0 call");
290 TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
291 TRACE_EVENT2("all", "TRACE_EVENT2 call",
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900292 "name1", "\"value1\"",
293 "name2", "value\\2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900294
295 TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call");
296 TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call", "name1", "value1");
297 TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
298 "name1", "value1",
299 "name2", "value2");
300
301 TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
302 TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
303 TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
304 "name1", "value1",
305 "name2", "value2");
306
307 TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
308 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
309 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
310 "name1", "value1",
311 "name2", "value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900312
313 TRACE_COUNTER1("all", "TRACE_COUNTER1 call", 31415);
314 TRACE_COUNTER2("all", "TRACE_COUNTER2 call",
315 "a", 30000,
316 "b", 1415);
piman@chromium.org902b2952011-12-16 10:19:06 +0900317
318 TRACE_COUNTER_ID1("all", "TRACE_COUNTER_ID1 call", 0x319009, 31415);
319 TRACE_COUNTER_ID2("all", "TRACE_COUNTER_ID2 call", 0x319009,
320 "a", 30000, "b", 1415);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900321 } // Scope close causes TRACE_EVENT0 etc to send their END events.
322
323 if (task_complete_event)
324 task_complete_event->Signal();
325}
326
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900327void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900328 DictionaryValue* item = NULL;
329
330#define EXPECT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900331 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900332#define EXPECT_NOT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900333 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900334#define EXPECT_SUB_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900335 if (item) EXPECT_TRUE((IsStringInDict(string, item)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900336
337 EXPECT_FIND_("ETW Trace Event");
338 EXPECT_FIND_("all");
339 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW call");
340 {
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900341 std::string str_val;
342 EXPECT_TRUE(item && item->GetString("args.id", &str_val));
343 EXPECT_STREQ("1122", str_val.c_str());
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900344 }
345 EXPECT_SUB_FIND_("extrastring1");
346 EXPECT_FIND_("TRACE_EVENT_END_ETW call");
347 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW call");
348 EXPECT_FIND_("TRACE_EVENT0 call");
349 {
350 std::string ph_begin;
351 std::string ph_end;
352 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
353 EXPECT_TRUE((item && item->GetString("ph", &ph_begin)));
354 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call",
355 item)));
356 EXPECT_TRUE((item && item->GetString("ph", &ph_end)));
357 EXPECT_EQ("B", ph_begin);
358 EXPECT_EQ("E", ph_end);
359 }
360 EXPECT_FIND_("TRACE_EVENT1 call");
361 EXPECT_FIND_("TRACE_EVENT2 call");
362 EXPECT_SUB_FIND_("name1");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900363 EXPECT_SUB_FIND_("\"value1\"");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900364 EXPECT_SUB_FIND_("name2");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900365 EXPECT_SUB_FIND_("value\\2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900366 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
367 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
368 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
369 EXPECT_SUB_FIND_("name1");
370 EXPECT_SUB_FIND_("value1");
371 EXPECT_SUB_FIND_("name2");
372 EXPECT_SUB_FIND_("value2");
373 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
374 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
375 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
376 EXPECT_SUB_FIND_("name1");
377 EXPECT_SUB_FIND_("value1");
378 EXPECT_SUB_FIND_("name2");
379 EXPECT_SUB_FIND_("value2");
380 EXPECT_FIND_("TRACE_EVENT_END0 call");
381 EXPECT_FIND_("TRACE_EVENT_END1 call");
382 EXPECT_FIND_("TRACE_EVENT_END2 call");
383 EXPECT_SUB_FIND_("name1");
384 EXPECT_SUB_FIND_("value1");
385 EXPECT_SUB_FIND_("name2");
386 EXPECT_SUB_FIND_("value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900387
388 EXPECT_FIND_("TRACE_COUNTER1 call");
389 {
390 std::string ph;
391 EXPECT_TRUE((item && item->GetString("ph", &ph)));
392 EXPECT_EQ("C", ph);
393
394 int value;
395 EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
396 EXPECT_EQ(31415, value);
397 }
398
399 EXPECT_FIND_("TRACE_COUNTER2 call");
400 {
401 std::string ph;
402 EXPECT_TRUE((item && item->GetString("ph", &ph)));
403 EXPECT_EQ("C", ph);
404
405 int value;
406 EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
407 EXPECT_EQ(30000, value);
408
409 EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
410 EXPECT_EQ(1415, value);
411 }
412
piman@chromium.org902b2952011-12-16 10:19:06 +0900413 EXPECT_FIND_("TRACE_COUNTER_ID1 call");
414 {
415 std::string id;
416 EXPECT_TRUE((item && item->GetString("id", &id)));
417 EXPECT_EQ("319009", id);
418
419 std::string ph;
420 EXPECT_TRUE((item && item->GetString("ph", &ph)));
421 EXPECT_EQ("C", ph);
422
423 int value;
424 EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
425 EXPECT_EQ(31415, value);
426 }
427
428 EXPECT_FIND_("TRACE_COUNTER_ID2 call");
429 {
430 std::string id;
431 EXPECT_TRUE((item && item->GetString("id", &id)));
432 EXPECT_EQ("319009", id);
433
434 std::string ph;
435 EXPECT_TRUE((item && item->GetString("ph", &ph)));
436 EXPECT_EQ("C", ph);
437
438 int value;
439 EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
440 EXPECT_EQ(30000, value);
441
442 EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
443 EXPECT_EQ(1415, value);
444 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900445}
446
nduca@chromium.org6d048772011-08-10 00:16:25 +0900447void TraceManyInstantEvents(int thread_id, int num_events,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900448 WaitableEvent* task_complete_event) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900449 for (int i = 0; i < num_events; i++) {
450 TRACE_EVENT_INSTANT2("all", "multi thread event",
451 "thread", thread_id,
452 "event", i);
453 }
454
455 if (task_complete_event)
456 task_complete_event->Signal();
457}
458
459void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900460 int num_threads,
461 int num_events) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900462 std::map<int, std::map<int, bool> > results;
463
464 size_t trace_parsed_count = trace_parsed.GetSize();
465 for (size_t i = 0; i < trace_parsed_count; i++) {
466 Value* value = NULL;
467 trace_parsed.Get(i, &value);
468 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
469 continue;
470 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
471 std::string name;
472 dict->GetString("name", &name);
473 if (name != "multi thread event")
474 continue;
475
476 int thread = 0;
477 int event = 0;
478 EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
479 EXPECT_TRUE(dict->GetInteger("args.event", &event));
480 results[thread][event] = true;
481 }
482
483 EXPECT_FALSE(results[-1][-1]);
484 for (int thread = 0; thread < num_threads; thread++) {
485 for (int event = 0; event < num_events; event++) {
486 EXPECT_TRUE(results[thread][event]);
487 }
488 }
489}
490
491void TraceCallsWithCachedCategoryPointersPointers(const char* name_str) {
492 TRACE_EVENT0("category name1", name_str);
493 TRACE_EVENT_INSTANT0("category name2", name_str);
494 TRACE_EVENT_BEGIN0("category name3", name_str);
495 TRACE_EVENT_END0("category name4", name_str);
496}
497
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900498} // namespace
499
500// Simple Test for emitting data and validating it was received.
501TEST_F(TraceEventTestFixture, DataCaptured) {
502 ManualTestSetUp();
503 TraceLog::GetInstance()->SetEnabled(true);
504
nduca@chromium.org6d048772011-08-10 00:16:25 +0900505 TraceWithAllMacroVariants(NULL);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900506
507 TraceLog::GetInstance()->SetEnabled(false);
508
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900509 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900510}
511
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900512// Test that categories work.
513TEST_F(TraceEventTestFixture, Categories) {
514 ManualTestSetUp();
515
516 // Test that categories that are used can be retrieved whether trace was
517 // enabled or disabled when the trace event was encountered.
518 TRACE_EVENT_INSTANT0("c1", "name");
519 TRACE_EVENT_INSTANT0("c2", "name");
520 TraceLog::GetInstance()->SetEnabled(true);
521 TRACE_EVENT_INSTANT0("c3", "name");
522 TRACE_EVENT_INSTANT0("c4", "name");
523 TraceLog::GetInstance()->SetEnabled(false);
524 std::vector<std::string> cats;
525 TraceLog::GetInstance()->GetKnownCategories(&cats);
526 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c1") != cats.end());
527 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c2") != cats.end());
528 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c3") != cats.end());
529 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c4") != cats.end());
530
531 const std::vector<std::string> empty_categories;
532 std::vector<std::string> included_categories;
533 std::vector<std::string> excluded_categories;
534
535 // Test that category filtering works.
536
537 // Include nonexistent category -> no events
538 Clear();
539 included_categories.clear();
540 included_categories.push_back("not_found823564786");
541 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
542 TRACE_EVENT_INSTANT0("cat1", "name");
543 TRACE_EVENT_INSTANT0("cat2", "name");
544 TraceLog::GetInstance()->SetDisabled();
545 EXPECT_TRUE(trace_parsed_.empty());
546
547 // Include existent category -> only events of that category
548 Clear();
549 included_categories.clear();
550 included_categories.push_back("inc");
551 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
552 TRACE_EVENT_INSTANT0("inc", "name");
553 TRACE_EVENT_INSTANT0("inc2", "name");
554 TraceLog::GetInstance()->SetDisabled();
555 EXPECT_TRUE(FindMatchingValue("cat", "inc"));
556 EXPECT_FALSE(FindNonMatchingValue("cat", "inc"));
557
558 // Include existent wildcard -> all categories matching wildcard
559 Clear();
560 included_categories.clear();
561 included_categories.push_back("inc_wildcard_*");
562 included_categories.push_back("inc_wildchar_?_end");
563 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
564 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "included");
565 TRACE_EVENT_INSTANT0("inc_wildcard_", "included");
566 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "included");
567 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "not_inc");
568 TRACE_EVENT_INSTANT0("cat1", "not_inc");
569 TRACE_EVENT_INSTANT0("cat2", "not_inc");
570 TraceLog::GetInstance()->SetDisabled();
571 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_abc"));
572 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_"));
573 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_x_end"));
574 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
575
576 included_categories.clear();
577
578 // Exclude nonexistent category -> all events
579 Clear();
580 excluded_categories.clear();
581 excluded_categories.push_back("not_found823564786");
582 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
583 TRACE_EVENT_INSTANT0("cat1", "name");
584 TRACE_EVENT_INSTANT0("cat2", "name");
585 TraceLog::GetInstance()->SetDisabled();
586 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
587 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
588
589 // Exclude existent category -> only events of other categories
590 Clear();
591 excluded_categories.clear();
592 excluded_categories.push_back("inc");
593 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
594 TRACE_EVENT_INSTANT0("inc", "name");
595 TRACE_EVENT_INSTANT0("inc2", "name");
596 TraceLog::GetInstance()->SetDisabled();
597 EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
598 EXPECT_FALSE(FindMatchingValue("cat", "inc"));
599
600 // Exclude existent wildcard -> all categories not matching wildcard
601 Clear();
602 excluded_categories.clear();
603 excluded_categories.push_back("inc_wildcard_*");
604 excluded_categories.push_back("inc_wildchar_?_end");
605 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
606 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "not_inc");
607 TRACE_EVENT_INSTANT0("inc_wildcard_", "not_inc");
608 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "not_inc");
609 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "included");
610 TRACE_EVENT_INSTANT0("cat1", "included");
611 TRACE_EVENT_INSTANT0("cat2", "included");
612 TraceLog::GetInstance()->SetDisabled();
613 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_bla_end"));
614 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
615 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
616 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
617}
618
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900619// Simple Test for time threshold events.
620TEST_F(TraceEventTestFixture, DataCapturedThreshold) {
621 ManualTestSetUp();
622 TraceLog::GetInstance()->SetEnabled(true);
623
624 // Test that events at the same level are properly filtered by threshold.
625 {
626 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "threshold 100");
627 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "threshold 1000");
628 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "threshold 10000");
629 // 100+ seconds to avoid flakiness.
630 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "threshold long1");
631 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "threshold long2");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900632 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900633 }
634
635 // Test that a normal nested event remains after it's parent event is dropped.
636 {
637 TRACE_EVENT_IF_LONGER_THAN0(1000000, "time", "2threshold10000");
638 {
639 TRACE_EVENT0("time", "nonthreshold1");
640 }
641 }
642
643 // Test that parent thresholded events are dropped while some nested events
644 // remain.
645 {
646 TRACE_EVENT0("time", "nonthreshold3");
647 {
648 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "3thresholdlong2");
649 {
650 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "3thresholdlong1");
651 {
652 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "3threshold10000");
653 {
654 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "3threshold1000");
655 {
656 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "3threshold100");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900657 base::PlatformThread::Sleep(
658 base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900659 }
660 }
661 }
662 }
663 }
664 }
665
666 // Test that child thresholded events are dropped while some parent events
667 // remain.
668 {
669 TRACE_EVENT0("time", "nonthreshold4");
670 {
671 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "4threshold100");
672 {
673 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "4threshold1000");
674 {
675 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "4threshold10000");
676 {
677 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time",
678 "4thresholdlong1");
679 {
680 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time",
681 "4thresholdlong2");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900682 base::PlatformThread::Sleep(
683 base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900684 }
685 }
686 }
687 }
688 }
689 }
690
691 TraceLog::GetInstance()->SetEnabled(false);
692
693#define EXPECT_FIND_BE_(str) \
694 EXPECT_TRUE(FindNamePhase(str, "B")); \
695 EXPECT_TRUE(FindNamePhase(str, "E"))
696#define EXPECT_NOT_FIND_BE_(str) \
697 EXPECT_FALSE(FindNamePhase(str, "B")); \
698 EXPECT_FALSE(FindNamePhase(str, "E"))
699
700 EXPECT_FIND_BE_("threshold 100");
701 EXPECT_FIND_BE_("threshold 1000");
702 EXPECT_FIND_BE_("threshold 10000");
703 EXPECT_NOT_FIND_BE_("threshold long1");
704 EXPECT_NOT_FIND_BE_("threshold long2");
705
706 EXPECT_NOT_FIND_BE_("2threshold10000");
707 EXPECT_FIND_BE_("nonthreshold1");
708
709 EXPECT_FIND_BE_("nonthreshold3");
710 EXPECT_FIND_BE_("3threshold100");
711 EXPECT_FIND_BE_("3threshold1000");
712 EXPECT_FIND_BE_("3threshold10000");
713 EXPECT_NOT_FIND_BE_("3thresholdlong1");
714 EXPECT_NOT_FIND_BE_("3thresholdlong2");
715
716 EXPECT_FIND_BE_("nonthreshold4");
717 EXPECT_FIND_BE_("4threshold100");
718 EXPECT_FIND_BE_("4threshold1000");
719 EXPECT_FIND_BE_("4threshold10000");
720 EXPECT_NOT_FIND_BE_("4thresholdlong1");
721 EXPECT_NOT_FIND_BE_("4thresholdlong2");
722}
723
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900724// Test Start/Finish events
725TEST_F(TraceEventTestFixture, StartFinishEvents) {
726 ManualTestSetUp();
727 TraceLog::GetInstance()->SetEnabled(true);
728
729 unsigned long long id = 0xfeedbeeffeedbeefull;
730 TRACE_EVENT_START0( "cat", "name1", id);
731 TRACE_EVENT_FINISH0("cat", "name1", id);
732 TRACE_EVENT_BEGIN0( "cat", "name2");
733 TRACE_EVENT_START0( "cat", "name3", 0);
734
735 TraceLog::GetInstance()->SetEnabled(false);
736
737 EXPECT_TRUE(FindNamePhase("name1", "S"));
738 EXPECT_TRUE(FindNamePhase("name1", "F"));
739
740 std::string id_str;
741 StringAppendF(&id_str, "%llx", id);
742
743 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "S", "id", id_str.c_str()));
744 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "F", "id", id_str.c_str()));
745 EXPECT_TRUE(FindNamePhaseKeyValue("name3", "S", "id", "0"));
746
747 // BEGIN events should not have id
748 EXPECT_FALSE(FindNamePhaseKeyValue("name2", "B", "id", "0"));
749}
750
751// Test Start/Finish events
752TEST_F(TraceEventTestFixture, StartFinishPointerMangling) {
753 ManualTestSetUp();
754
755 void* ptr = this;
756
757 TraceLog::GetInstance()->SetProcessID(100);
758 TraceLog::GetInstance()->SetEnabled(true);
759 TRACE_EVENT_START0( "cat", "name1", ptr);
760 TRACE_EVENT_START0( "cat", "name2", ptr);
761 TraceLog::GetInstance()->SetEnabled(false);
762
763 TraceLog::GetInstance()->SetProcessID(200);
764 TraceLog::GetInstance()->SetEnabled(true);
765 TRACE_EVENT_FINISH0( "cat", "name1", ptr);
766 TraceLog::GetInstance()->SetEnabled(false);
767
768 DictionaryValue* start = FindNamePhase("name1", "S");
769 DictionaryValue* start2 = FindNamePhase("name2", "S");
770 DictionaryValue* finish = FindNamePhase("name1", "F");
771 EXPECT_TRUE(start);
772 EXPECT_TRUE(start2);
773 EXPECT_TRUE(finish);
774
775 Value* value = NULL;
776 std::string start_id_str;
777 std::string start2_id_str;
778 std::string finish_id_str;
779 ASSERT_TRUE(start->Get("id", &value));
780 ASSERT_TRUE(value->GetAsString(&start_id_str));
781 ASSERT_TRUE(start2->Get("id", &value));
782 ASSERT_TRUE(value->GetAsString(&start2_id_str));
783 ASSERT_TRUE(finish->Get("id", &value));
784 ASSERT_TRUE(value->GetAsString(&finish_id_str));
785
786 EXPECT_STREQ(start_id_str.c_str(), start2_id_str.c_str());
787 EXPECT_STRNE(start_id_str.c_str(), finish_id_str.c_str());
788}
789
jbates@chromium.org1f18e462011-09-07 02:56:24 +0900790// Test that static strings are not copied.
791TEST_F(TraceEventTestFixture, StaticStringVsString) {
792 ManualTestSetUp();
793 TraceLog* tracer = TraceLog::GetInstance();
794 // Make sure old events are flushed:
795 tracer->SetEnabled(false);
796 EXPECT_EQ(0u, tracer->GetEventsSize());
797
798 {
799 tracer->SetEnabled(true);
800 // Test that string arguments are copied.
801 TRACE_EVENT2("cat", "name1",
802 "arg1", std::string("argval"), "arg2", std::string("argval"));
803 // Test that static TRACE_STR_COPY string arguments are copied.
804 TRACE_EVENT2("cat", "name2",
805 "arg1", TRACE_STR_COPY("argval"),
806 "arg2", TRACE_STR_COPY("argval"));
807 size_t num_events = tracer->GetEventsSize();
808 EXPECT_GT(num_events, 1u);
809 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
810 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
811 EXPECT_STREQ("name1", event1.name());
812 EXPECT_STREQ("name2", event2.name());
813 EXPECT_TRUE(event1.parameter_copy_storage() != NULL);
814 EXPECT_TRUE(event2.parameter_copy_storage() != NULL);
815 EXPECT_GT(event1.parameter_copy_storage()->size(), 0u);
816 EXPECT_GT(event2.parameter_copy_storage()->size(), 0u);
817 tracer->SetEnabled(false);
818 }
819
820 {
821 tracer->SetEnabled(true);
822 // Test that static literal string arguments are not copied.
823 TRACE_EVENT2("cat", "name1",
824 "arg1", "argval", "arg2", "argval");
825 // Test that static TRACE_STR_COPY NULL string arguments are not copied.
826 const char* str1 = NULL;
827 const char* str2 = NULL;
828 TRACE_EVENT2("cat", "name2",
829 "arg1", TRACE_STR_COPY(str1),
830 "arg2", TRACE_STR_COPY(str2));
831 size_t num_events = tracer->GetEventsSize();
832 EXPECT_GT(num_events, 1u);
833 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
834 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
835 EXPECT_STREQ("name1", event1.name());
836 EXPECT_STREQ("name2", event2.name());
837 EXPECT_TRUE(event1.parameter_copy_storage() == NULL);
838 EXPECT_TRUE(event2.parameter_copy_storage() == NULL);
839 tracer->SetEnabled(false);
840 }
841}
842
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900843// Test that data sent from other threads is gathered
844TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
845 ManualTestSetUp();
846 TraceLog::GetInstance()->SetEnabled(true);
847
848 Thread thread("1");
849 WaitableEvent task_complete_event(false, false);
850 thread.Start();
851
852 thread.message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900853 FROM_HERE, base::Bind(&TraceWithAllMacroVariants, &task_complete_event));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900854 task_complete_event.Wait();
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900855 thread.Stop();
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900856
857 TraceLog::GetInstance()->SetEnabled(false);
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900858 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900859}
860
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900861// Test that data sent from multiple threads is gathered
862TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
863 ManualTestSetUp();
864 TraceLog::GetInstance()->SetEnabled(true);
865
866 const int num_threads = 4;
867 const int num_events = 4000;
868 Thread* threads[num_threads];
869 WaitableEvent* task_complete_events[num_threads];
870 for (int i = 0; i < num_threads; i++) {
871 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
872 task_complete_events[i] = new WaitableEvent(false, false);
873 threads[i]->Start();
874 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900875 FROM_HERE, base::Bind(&TraceManyInstantEvents,
876 i, num_events, task_complete_events[i]));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900877 }
878
879 for (int i = 0; i < num_threads; i++) {
880 task_complete_events[i]->Wait();
881 }
882
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900883 for (int i = 0; i < num_threads; i++) {
884 threads[i]->Stop();
885 delete threads[i];
886 delete task_complete_events[i];
887 }
888
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900889 TraceLog::GetInstance()->SetEnabled(false);
890
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900891 ValidateInstantEventPresentOnEveryThread(trace_parsed_,
nduca@chromium.org6d048772011-08-10 00:16:25 +0900892 num_threads, num_events);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900893}
894
nduca@chromium.org6d048772011-08-10 00:16:25 +0900895// Test that thread and process names show up in the trace
896TEST_F(TraceEventTestFixture, ThreadNames) {
897 ManualTestSetUp();
898
899 // Create threads before we enable tracing to make sure
900 // that tracelog still captures them.
901 const int num_threads = 4;
902 const int num_events = 10;
903 Thread* threads[num_threads];
904 PlatformThreadId thread_ids[num_threads];
905 for (int i = 0; i < num_threads; i++)
906 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
907
908 // Enable tracing.
909 TraceLog::GetInstance()->SetEnabled(true);
910
911 // Now run some trace code on these threads.
912 WaitableEvent* task_complete_events[num_threads];
913 for (int i = 0; i < num_threads; i++) {
914 task_complete_events[i] = new WaitableEvent(false, false);
915 threads[i]->Start();
916 thread_ids[i] = threads[i]->thread_id();
917 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900918 FROM_HERE, base::Bind(&TraceManyInstantEvents,
919 i, num_events, task_complete_events[i]));
nduca@chromium.org6d048772011-08-10 00:16:25 +0900920 }
921 for (int i = 0; i < num_threads; i++) {
922 task_complete_events[i]->Wait();
923 }
924
925 // Shut things down.
nduca@chromium.org6d048772011-08-10 00:16:25 +0900926 for (int i = 0; i < num_threads; i++) {
927 threads[i]->Stop();
928 delete threads[i];
929 delete task_complete_events[i];
930 }
931
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900932 TraceLog::GetInstance()->SetEnabled(false);
933
nduca@chromium.org6d048772011-08-10 00:16:25 +0900934 std::string tmp;
935 int tmp_int;
936 DictionaryValue* item;
937
938 // Make sure we get thread name metadata.
939 // Note, the test suite may have created a ton of threads.
940 // So, we'll have thread names for threads we didn't create.
941 std::vector<DictionaryValue*> items =
942 FindTraceEntries(trace_parsed_, "thread_name");
943 for (int i = 0; i < static_cast<int>(items.size()); i++) {
944 item = items[i];
joth@chromium.org088ae012011-11-11 01:26:23 +0900945 ASSERT_TRUE(item);
nduca@chromium.org6d048772011-08-10 00:16:25 +0900946 EXPECT_TRUE(item->GetInteger("tid", &tmp_int));
947
948 // See if this thread name is one of the threads we just created
949 for (int j = 0; j < num_threads; j++) {
950 if(static_cast<int>(thread_ids[j]) != tmp_int)
951 continue;
952
953 std::string expected_name = StringPrintf("Thread %d", j).c_str();
954 EXPECT_TRUE(item->GetString("ph", &tmp) && tmp == "M");
955 EXPECT_TRUE(item->GetInteger("pid", &tmp_int) &&
956 tmp_int == static_cast<int>(base::GetCurrentProcId()));
957 EXPECT_TRUE(item->GetString("args.name", &tmp) &&
958 tmp == expected_name);
959 }
960 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900961}
962
joth@chromium.org088ae012011-11-11 01:26:23 +0900963TEST_F(TraceEventTestFixture, ThreadNameChanges) {
964 ManualTestSetUp();
965
966 TraceLog::GetInstance()->SetEnabled(true);
967
968 PlatformThread::SetName("");
969 TRACE_EVENT_INSTANT0("drink", "water");
970
971 PlatformThread::SetName("cafe");
972 TRACE_EVENT_INSTANT0("drink", "coffee");
973
974 PlatformThread::SetName("shop");
975 // No event here, so won't appear in combined name.
976
977 PlatformThread::SetName("pub");
978 TRACE_EVENT_INSTANT0("drink", "beer");
979 TRACE_EVENT_INSTANT0("drink", "wine");
980
981 PlatformThread::SetName(" bar");
982 TRACE_EVENT_INSTANT0("drink", "whisky");
983
984 TraceLog::GetInstance()->SetEnabled(false);
985
986 std::vector<DictionaryValue*> items =
987 FindTraceEntries(trace_parsed_, "thread_name");
988 EXPECT_EQ(1u, items.size());
989 ASSERT_GT(items.size(), 0u);
990 DictionaryValue* item = items[0];
991 ASSERT_TRUE(item);
992 int tid;
993 EXPECT_TRUE(item->GetInteger("tid", &tid));
994 EXPECT_EQ(PlatformThread::CurrentId(), static_cast<PlatformThreadId>(tid));
995
996 std::string expected_name = "cafe,pub, bar";
997 std::string tmp;
998 EXPECT_TRUE(item->GetString("args.name", &tmp));
999 EXPECT_EQ(expected_name, tmp);
1000}
nduca@chromium.org6d048772011-08-10 00:16:25 +09001001
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001002// Test trace calls made after tracing singleton shut down.
1003//
1004// The singleton is destroyed by our base::AtExitManager, but there can be
1005// code still executing as the C++ static objects are destroyed. This test
1006// forces the singleton to destroy early, and intentinally makes trace calls
1007// afterwards.
1008TEST_F(TraceEventTestFixture, AtExit) {
1009 // Repeat this test a few times. Besides just showing robustness, it also
1010 // allows us to test that events at shutdown do not appear with valid events
1011 // recorded after the system is started again.
1012 for (int i = 0; i < 4; i++) {
1013 // Scope to contain the then destroy the TraceLog singleton.
1014 {
1015 base::ShadowingAtExitManager exit_manager_will_destroy_singletons;
1016
1017 // Setup TraceLog singleton inside this test's exit manager scope
1018 // so that it will be destroyed when this scope closes.
1019 ManualTestSetUp();
1020
1021 TRACE_EVENT_INSTANT0("all", "not recorded; system not enabled");
1022
1023 TraceLog::GetInstance()->SetEnabled(true);
1024
1025 TRACE_EVENT_INSTANT0("all", "is recorded 1; system has been enabled");
1026 // Trace calls that will cache pointers to categories; they're valid here
1027 TraceCallsWithCachedCategoryPointersPointers(
1028 "is recorded 2; system has been enabled");
1029
1030 TraceLog::GetInstance()->SetEnabled(false);
1031 } // scope to destroy singleton
1032 ASSERT_FALSE(TraceLog::GetInstance());
1033
1034 // Now that singleton is destroyed, check what trace events were recorded
1035 DictionaryValue* item = NULL;
1036 ListValue& trace_parsed = trace_parsed_;
1037 EXPECT_FIND_("is recorded 1");
1038 EXPECT_FIND_("is recorded 2");
1039 EXPECT_NOT_FIND_("not recorded");
1040
1041 // Make additional trace event calls on the shutdown system. They should
1042 // all pass cleanly, but the data not be recorded. We'll verify that next
1043 // time around the loop (the only way to flush the trace buffers).
1044 TRACE_EVENT_BEGIN_ETW("not recorded; system shutdown", 0, NULL);
1045 TRACE_EVENT_END_ETW("not recorded; system shutdown", 0, NULL);
1046 TRACE_EVENT_INSTANT_ETW("not recorded; system shutdown", 0, NULL);
1047 TRACE_EVENT0("all", "not recorded; system shutdown");
1048 TRACE_EVENT_INSTANT0("all", "not recorded; system shutdown");
1049 TRACE_EVENT_BEGIN0("all", "not recorded; system shutdown");
1050 TRACE_EVENT_END0("all", "not recorded; system shutdown");
1051
1052 TRACE_EVENT0("new category 0!", "not recorded; system shutdown");
1053 TRACE_EVENT_INSTANT0("new category 1!", "not recorded; system shutdown");
1054 TRACE_EVENT_BEGIN0("new category 2!", "not recorded; system shutdown");
1055 TRACE_EVENT_END0("new category 3!", "not recorded; system shutdown");
1056
1057 // Cached categories should be safe to check, and still disable traces
1058 TraceCallsWithCachedCategoryPointersPointers(
1059 "not recorded; system shutdown");
1060 }
1061}
1062
joth@chromium.org113de992011-07-21 21:28:59 +09001063TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
1064 // Test that the TRACE_EVENT macros do not deep-copy their string. If they
1065 // do so it may indicate a performance regression, but more-over it would
1066 // make the DEEP_COPY overloads redundant.
1067 ManualTestSetUp();
1068
1069 std::string name_string("event name");
1070
1071 TraceLog::GetInstance()->SetEnabled(true);
1072 TRACE_EVENT_INSTANT0("category", name_string.c_str());
1073
1074 // Modify the string in place (a wholesale reassignment may leave the old
1075 // string intact on the heap).
1076 name_string[0] = '@';
1077
1078 TraceLog::GetInstance()->SetEnabled(false);
1079
1080 EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
1081 EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
1082}
1083
1084TEST_F(TraceEventTestFixture, DeepCopy) {
1085 ManualTestSetUp();
1086
1087 static const char kOriginalName1[] = "name1";
1088 static const char kOriginalName2[] = "name2";
1089 static const char kOriginalName3[] = "name3";
1090 std::string name1(kOriginalName1);
1091 std::string name2(kOriginalName2);
1092 std::string name3(kOriginalName3);
1093 std::string arg1("arg1");
1094 std::string arg2("arg2");
1095 std::string val1("val1");
1096 std::string val2("val2");
1097
1098 TraceLog::GetInstance()->SetEnabled(true);
1099 TRACE_EVENT_COPY_INSTANT0("category", name1.c_str());
1100 TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
1101 arg1.c_str(), 5);
1102 TRACE_EVENT_COPY_END2("category", name3.c_str(),
jbates@chromium.org1f18e462011-09-07 02:56:24 +09001103 arg1.c_str(), val1,
1104 arg2.c_str(), val2);
joth@chromium.org113de992011-07-21 21:28:59 +09001105
1106 // As per NormallyNoDeepCopy, modify the strings in place.
1107 name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
1108
1109 TraceLog::GetInstance()->SetEnabled(false);
1110
1111 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
1112 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
1113 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
1114
1115 DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
1116 DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
1117 DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
1118 ASSERT_TRUE(entry1);
1119 ASSERT_TRUE(entry2);
1120 ASSERT_TRUE(entry3);
1121
1122 int i;
1123 EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
1124 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
1125 EXPECT_EQ(5, i);
1126
1127 std::string s;
1128 EXPECT_TRUE(entry3->GetString("args.arg1", &s));
1129 EXPECT_EQ("val1", s);
1130 EXPECT_TRUE(entry3->GetString("args.arg2", &s));
1131 EXPECT_EQ("val2", s);
1132}
1133
jbates@chromium.org6a092d72011-10-25 01:34:08 +09001134// Test that TraceResultBuffer outputs the correct result whether it is added
1135// in chunks or added all at once.
1136TEST_F(TraceEventTestFixture, TraceResultBuffer) {
1137 ManualTestSetUp();
1138
1139 Clear();
1140
1141 trace_buffer_.Start();
1142 trace_buffer_.AddFragment("bla1");
1143 trace_buffer_.AddFragment("bla2");
1144 trace_buffer_.AddFragment("bla3,bla4");
1145 trace_buffer_.Finish();
1146 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1147
1148 Clear();
1149
1150 trace_buffer_.Start();
1151 trace_buffer_.AddFragment("bla1,bla2,bla3,bla4");
1152 trace_buffer_.Finish();
1153 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1154}
1155
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001156} // namespace debug
1157} // namespace base