blob: befd4e8b2473829f8f8756b5415135471953452c [file] [log] [blame]
jbates@chromium.org59c27602012-01-13 12:12:44 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
scheib@chromium.org603f46e2011-05-10 11:23:58 +09002// 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(
husky@chromium.org3b366292012-02-24 13:17:06 +090045 const scoped_refptr<base::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() {
nduca@chromium.org6a7360c2012-02-20 15:35:15 +090065 if (TraceLog::GetInstance())
66 EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled());
joth@chromium.org088ae012011-11-11 01:26:23 +090067 PlatformThread::SetName(old_thread_name_ ? old_thread_name_ : "");
68 }
69
70 const char* old_thread_name_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090071 ListValue trace_parsed_;
jbates@chromium.org6a092d72011-10-25 01:34:08 +090072 base::debug::TraceResultBuffer trace_buffer_;
73 base::debug::TraceResultBuffer::SimpleOutput json_output_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090074
75 private:
76 // We want our singleton torn down after each test.
77 ShadowingAtExitManager at_exit_manager_;
jbates@chromium.orgb84db522011-10-04 02:51:25 +090078 Lock lock_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090079};
80
81void TraceEventTestFixture::ManualTestSetUp() {
jbates@chromium.orgb84db522011-10-04 02:51:25 +090082 TraceLog::DeleteForTesting();
scheib@chromium.org603f46e2011-05-10 11:23:58 +090083 TraceLog::Resurrect();
84 TraceLog* tracelog = TraceLog::GetInstance();
85 ASSERT_TRUE(tracelog);
86 ASSERT_FALSE(tracelog->IsEnabled());
87 tracelog->SetOutputCallback(
jbates@chromium.orgb84db522011-10-04 02:51:25 +090088 base::Bind(&TraceEventTestFixture::OnTraceDataCollected,
89 base::Unretained(this)));
jbates@chromium.org6a092d72011-10-25 01:34:08 +090090 trace_buffer_.SetOutputCallback(json_output_.GetCallback());
scheib@chromium.org603f46e2011-05-10 11:23:58 +090091}
92
93void TraceEventTestFixture::OnTraceDataCollected(
husky@chromium.org3b366292012-02-24 13:17:06 +090094 const scoped_refptr<base::RefCountedString>& events_str) {
jbates@chromium.orgb84db522011-10-04 02:51:25 +090095 AutoLock lock(lock_);
jbates@chromium.org6a092d72011-10-25 01:34:08 +090096 json_output_.json_output.clear();
97 trace_buffer_.Start();
husky@chromium.org3b366292012-02-24 13:17:06 +090098 trace_buffer_.AddFragment(events_str->data());
jbates@chromium.org6a092d72011-10-25 01:34:08 +090099 trace_buffer_.Finish();
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900100
101 scoped_ptr<Value> root;
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900102 root.reset(base::JSONReader::Read(json_output_.json_output, false));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900103
jbates@chromium.org59c27602012-01-13 12:12:44 +0900104 if (!root.get()) {
105 LOG(ERROR) << json_output_.json_output;
106 }
107
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900108 ListValue* root_list = NULL;
109 ASSERT_TRUE(root.get());
110 ASSERT_TRUE(root->GetAsList(&root_list));
111
112 // Move items into our aggregate collection
113 while (root_list->GetSize()) {
114 Value* item = NULL;
115 root_list->Remove(0, &item);
116 trace_parsed_.Append(item);
117 }
118}
119
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900120static bool CompareJsonValues(const std::string& lhs,
121 const std::string& rhs,
122 CompareOp op) {
123 switch (op) {
124 case IS_EQUAL:
125 return lhs == rhs;
126 case IS_NOT_EQUAL:
127 return lhs != rhs;
128 default:
129 CHECK(0);
130 }
131 return false;
132}
133
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900134static bool IsKeyValueInDict(const JsonKeyValue* key_value,
135 DictionaryValue* dict) {
136 Value* value = NULL;
137 std::string value_str;
138 if (dict->Get(key_value->key, &value) &&
139 value->GetAsString(&value_str) &&
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900140 CompareJsonValues(value_str, key_value->value, key_value->op))
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900141 return true;
142
143 // Recurse to test arguments
144 DictionaryValue* args_dict = NULL;
145 dict->GetDictionary("args", &args_dict);
146 if (args_dict)
147 return IsKeyValueInDict(key_value, args_dict);
148
149 return false;
150}
151
152static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
153 DictionaryValue* dict) {
154 // Scan all key_values, they must all be present and equal.
155 while (key_values && key_values->key) {
156 if (!IsKeyValueInDict(key_values, dict))
157 return false;
158 ++key_values;
159 }
160 return true;
161}
162
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900163DictionaryValue* TraceEventTestFixture::FindMatchingTraceEntry(
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900164 const JsonKeyValue* key_values) {
165 // Scan all items
166 size_t trace_parsed_count = trace_parsed_.GetSize();
167 for (size_t i = 0; i < trace_parsed_count; i++) {
168 Value* value = NULL;
169 trace_parsed_.Get(i, &value);
170 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
171 continue;
172 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
173
174 if (IsAllKeyValueInDict(key_values, dict))
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900175 return dict;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900176 }
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900177 return NULL;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900178}
179
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900180DictionaryValue* TraceEventTestFixture::FindNamePhase(const char* name,
181 const char* phase) {
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900182 JsonKeyValue key_values[] = {
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900183 {"name", name, IS_EQUAL},
184 {"ph", phase, IS_EQUAL},
185 {0, 0, IS_EQUAL}
186 };
187 return FindMatchingTraceEntry(key_values);
188}
189
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900190DictionaryValue* TraceEventTestFixture::FindNamePhaseKeyValue(
191 const char* name,
192 const char* phase,
193 const char* key,
194 const char* value) {
195 JsonKeyValue key_values[] = {
196 {"name", name, IS_EQUAL},
197 {"ph", phase, IS_EQUAL},
198 {key, value, IS_EQUAL},
199 {0, 0, IS_EQUAL}
200 };
201 return FindMatchingTraceEntry(key_values);
202}
203
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900204bool TraceEventTestFixture::FindMatchingValue(const char* key,
205 const char* value) {
206 JsonKeyValue key_values[] = {
207 {key, value, IS_EQUAL},
208 {0, 0, IS_EQUAL}
209 };
210 return FindMatchingTraceEntry(key_values);
211}
212
213bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
214 const char* value) {
215 JsonKeyValue key_values[] = {
216 {key, value, IS_NOT_EQUAL},
217 {0, 0, IS_EQUAL}
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900218 };
219 return FindMatchingTraceEntry(key_values);
220}
221
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900222bool IsStringInDict(const char* string_to_match, DictionaryValue* dict) {
223 for (DictionaryValue::key_iterator ikey = dict->begin_keys();
224 ikey != dict->end_keys(); ++ikey) {
225 Value* child = NULL;
226 if (!dict->GetWithoutPathExpansion(*ikey, &child))
227 continue;
228
229 if ((*ikey).find(string_to_match) != std::string::npos)
230 return true;
231
232 std::string value_str;
233 child->GetAsString(&value_str);
234 if (value_str.find(string_to_match) != std::string::npos)
235 return true;
236 }
237
238 // Recurse to test arguments
239 DictionaryValue* args_dict = NULL;
240 dict->GetDictionary("args", &args_dict);
241 if (args_dict)
242 return IsStringInDict(string_to_match, args_dict);
243
244 return false;
245}
246
247DictionaryValue* FindTraceEntry(const ListValue& trace_parsed,
nduca@chromium.org6d048772011-08-10 00:16:25 +0900248 const char* string_to_match,
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900249 DictionaryValue* match_after_this_item = NULL) {
250 // Scan all items
251 size_t trace_parsed_count = trace_parsed.GetSize();
252 for (size_t i = 0; i < trace_parsed_count; i++) {
253 Value* value = NULL;
254 trace_parsed.Get(i, &value);
255 if (match_after_this_item) {
256 if (value == match_after_this_item)
257 match_after_this_item = NULL;
258 continue;
259 }
260 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
261 continue;
262 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
263
264 if (IsStringInDict(string_to_match, dict))
265 return dict;
266 }
267 return NULL;
268}
269
nduca@chromium.org6d048772011-08-10 00:16:25 +0900270std::vector<DictionaryValue*> FindTraceEntries(
271 const ListValue& trace_parsed,
272 const char* string_to_match) {
273 std::vector<DictionaryValue*> hits;
274 size_t trace_parsed_count = trace_parsed.GetSize();
275 for (size_t i = 0; i < trace_parsed_count; i++) {
276 Value* value = NULL;
277 trace_parsed.Get(i, &value);
278 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
279 continue;
280 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
281
282 if (IsStringInDict(string_to_match, dict))
283 hits.push_back(dict);
284 }
285 return hits;
286}
287
288void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900289 {
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900290 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW call", 0x1122, "extrastring1");
291 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW call", 0x3344, "extrastring2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900292 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW call",
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900293 0x5566, "extrastring3");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900294
295 TRACE_EVENT0("all", "TRACE_EVENT0 call");
296 TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
297 TRACE_EVENT2("all", "TRACE_EVENT2 call",
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900298 "name1", "\"value1\"",
299 "name2", "value\\2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900300
301 TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call");
302 TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call", "name1", "value1");
303 TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
304 "name1", "value1",
305 "name2", "value2");
306
307 TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
308 TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
309 TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
310 "name1", "value1",
311 "name2", "value2");
312
313 TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
314 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
315 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
316 "name1", "value1",
317 "name2", "value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900318
jbates@chromium.org59c27602012-01-13 12:12:44 +0900319 TRACE_EVENT_IF_LONGER_THAN0(0, "all", "TRACE_EVENT_IF_LONGER_THAN0 call");
320 TRACE_EVENT_IF_LONGER_THAN1(0, "all", "TRACE_EVENT_IF_LONGER_THAN1 call",
321 "name1", "value1");
322 TRACE_EVENT_IF_LONGER_THAN2(0, "all", "TRACE_EVENT_IF_LONGER_THAN2 call",
323 "name1", "value1",
324 "name2", "value2");
325
326 TRACE_EVENT_START0("all", "TRACE_EVENT_START0 call", 5);
327 TRACE_EVENT_START1("all", "TRACE_EVENT_START1 call", 5,
328 "name1", "value1");
329 TRACE_EVENT_START2("all", "TRACE_EVENT_START2 call", 5,
330 "name1", "value1",
331 "name2", "value2");
332
333 TRACE_EVENT_FINISH0("all", "TRACE_EVENT_FINISH0 call", 5);
334 TRACE_EVENT_FINISH1("all", "TRACE_EVENT_FINISH1 call", 5,
335 "name1", "value1");
336 TRACE_EVENT_FINISH2("all", "TRACE_EVENT_FINISH2 call", 5,
337 "name1", "value1",
338 "name2", "value2");
339
340 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW0 call", 5, NULL);
341 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW1 call", 5, "value");
342 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW0 call", 5, NULL);
343 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW1 call", 5, "value");
344 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW0 call", 5, NULL);
345 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW1 call", 5, "value");
346
nduca@chromium.org62210b02011-11-18 18:36:36 +0900347 TRACE_COUNTER1("all", "TRACE_COUNTER1 call", 31415);
348 TRACE_COUNTER2("all", "TRACE_COUNTER2 call",
349 "a", 30000,
350 "b", 1415);
piman@chromium.org902b2952011-12-16 10:19:06 +0900351
352 TRACE_COUNTER_ID1("all", "TRACE_COUNTER_ID1 call", 0x319009, 31415);
353 TRACE_COUNTER_ID2("all", "TRACE_COUNTER_ID2 call", 0x319009,
354 "a", 30000, "b", 1415);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900355 } // Scope close causes TRACE_EVENT0 etc to send their END events.
356
357 if (task_complete_event)
358 task_complete_event->Signal();
359}
360
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900361void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900362 DictionaryValue* item = NULL;
363
364#define EXPECT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900365 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900366#define EXPECT_NOT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900367 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900368#define EXPECT_SUB_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900369 if (item) EXPECT_TRUE((IsStringInDict(string, item)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900370
371 EXPECT_FIND_("ETW Trace Event");
372 EXPECT_FIND_("all");
373 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW call");
374 {
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900375 std::string str_val;
376 EXPECT_TRUE(item && item->GetString("args.id", &str_val));
377 EXPECT_STREQ("1122", str_val.c_str());
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900378 }
379 EXPECT_SUB_FIND_("extrastring1");
380 EXPECT_FIND_("TRACE_EVENT_END_ETW call");
381 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW call");
382 EXPECT_FIND_("TRACE_EVENT0 call");
383 {
384 std::string ph_begin;
385 std::string ph_end;
386 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
387 EXPECT_TRUE((item && item->GetString("ph", &ph_begin)));
388 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call",
389 item)));
390 EXPECT_TRUE((item && item->GetString("ph", &ph_end)));
391 EXPECT_EQ("B", ph_begin);
392 EXPECT_EQ("E", ph_end);
393 }
394 EXPECT_FIND_("TRACE_EVENT1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900395 EXPECT_SUB_FIND_("name1");
396 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900397 EXPECT_FIND_("TRACE_EVENT2 call");
398 EXPECT_SUB_FIND_("name1");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900399 EXPECT_SUB_FIND_("\"value1\"");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900400 EXPECT_SUB_FIND_("name2");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900401 EXPECT_SUB_FIND_("value\\2");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900402
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900403 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
404 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900405 EXPECT_SUB_FIND_("name1");
406 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900407 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
408 EXPECT_SUB_FIND_("name1");
409 EXPECT_SUB_FIND_("value1");
410 EXPECT_SUB_FIND_("name2");
411 EXPECT_SUB_FIND_("value2");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900412
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900413 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
414 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900415 EXPECT_SUB_FIND_("name1");
416 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900417 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
418 EXPECT_SUB_FIND_("name1");
419 EXPECT_SUB_FIND_("value1");
420 EXPECT_SUB_FIND_("name2");
421 EXPECT_SUB_FIND_("value2");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900422
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900423 EXPECT_FIND_("TRACE_EVENT_END0 call");
424 EXPECT_FIND_("TRACE_EVENT_END1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900425 EXPECT_SUB_FIND_("name1");
426 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900427 EXPECT_FIND_("TRACE_EVENT_END2 call");
428 EXPECT_SUB_FIND_("name1");
429 EXPECT_SUB_FIND_("value1");
430 EXPECT_SUB_FIND_("name2");
431 EXPECT_SUB_FIND_("value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900432
jbates@chromium.org59c27602012-01-13 12:12:44 +0900433 EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN0 call");
434 EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN1 call");
435 EXPECT_SUB_FIND_("name1");
436 EXPECT_SUB_FIND_("value1");
437 EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN2 call");
438 EXPECT_SUB_FIND_("name1");
439 EXPECT_SUB_FIND_("value1");
440 EXPECT_SUB_FIND_("name2");
441 EXPECT_SUB_FIND_("value2");
442
443 EXPECT_FIND_("TRACE_EVENT_START0 call");
444 EXPECT_SUB_FIND_("id");
445 EXPECT_SUB_FIND_("5");
446 EXPECT_FIND_("TRACE_EVENT_START1 call");
447 EXPECT_SUB_FIND_("id");
448 EXPECT_SUB_FIND_("5");
449 EXPECT_SUB_FIND_("name1");
450 EXPECT_SUB_FIND_("value1");
451 EXPECT_FIND_("TRACE_EVENT_START2 call");
452 EXPECT_SUB_FIND_("id");
453 EXPECT_SUB_FIND_("5");
454 EXPECT_SUB_FIND_("name1");
455 EXPECT_SUB_FIND_("value1");
456 EXPECT_SUB_FIND_("name2");
457 EXPECT_SUB_FIND_("value2");
458
459 EXPECT_FIND_("TRACE_EVENT_FINISH0 call");
460 EXPECT_SUB_FIND_("id");
461 EXPECT_SUB_FIND_("5");
462 EXPECT_FIND_("TRACE_EVENT_FINISH1 call");
463 EXPECT_SUB_FIND_("id");
464 EXPECT_SUB_FIND_("5");
465 EXPECT_SUB_FIND_("name1");
466 EXPECT_SUB_FIND_("value1");
467 EXPECT_FIND_("TRACE_EVENT_FINISH2 call");
468 EXPECT_SUB_FIND_("id");
469 EXPECT_SUB_FIND_("5");
470 EXPECT_SUB_FIND_("name1");
471 EXPECT_SUB_FIND_("value1");
472 EXPECT_SUB_FIND_("name2");
473 EXPECT_SUB_FIND_("value2");
474
475 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW0 call");
476 EXPECT_SUB_FIND_("id");
477 EXPECT_SUB_FIND_("5");
478 EXPECT_SUB_FIND_("extra");
479 EXPECT_SUB_FIND_("NULL");
480 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW1 call");
481 EXPECT_SUB_FIND_("id");
482 EXPECT_SUB_FIND_("5");
483 EXPECT_SUB_FIND_("extra");
484 EXPECT_SUB_FIND_("value");
485 EXPECT_FIND_("TRACE_EVENT_END_ETW0 call");
486 EXPECT_SUB_FIND_("id");
487 EXPECT_SUB_FIND_("5");
488 EXPECT_SUB_FIND_("extra");
489 EXPECT_SUB_FIND_("NULL");
490 EXPECT_FIND_("TRACE_EVENT_END_ETW1 call");
491 EXPECT_SUB_FIND_("id");
492 EXPECT_SUB_FIND_("5");
493 EXPECT_SUB_FIND_("extra");
494 EXPECT_SUB_FIND_("value");
495 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW0 call");
496 EXPECT_SUB_FIND_("id");
497 EXPECT_SUB_FIND_("5");
498 EXPECT_SUB_FIND_("extra");
499 EXPECT_SUB_FIND_("NULL");
500 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW1 call");
501 EXPECT_SUB_FIND_("id");
502 EXPECT_SUB_FIND_("5");
503 EXPECT_SUB_FIND_("extra");
504 EXPECT_SUB_FIND_("value");
505
nduca@chromium.org62210b02011-11-18 18:36:36 +0900506 EXPECT_FIND_("TRACE_COUNTER1 call");
507 {
508 std::string ph;
509 EXPECT_TRUE((item && item->GetString("ph", &ph)));
510 EXPECT_EQ("C", ph);
511
512 int value;
513 EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
514 EXPECT_EQ(31415, value);
515 }
516
517 EXPECT_FIND_("TRACE_COUNTER2 call");
518 {
519 std::string ph;
520 EXPECT_TRUE((item && item->GetString("ph", &ph)));
521 EXPECT_EQ("C", ph);
522
523 int value;
524 EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
525 EXPECT_EQ(30000, value);
526
527 EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
528 EXPECT_EQ(1415, value);
529 }
530
piman@chromium.org902b2952011-12-16 10:19:06 +0900531 EXPECT_FIND_("TRACE_COUNTER_ID1 call");
532 {
533 std::string id;
534 EXPECT_TRUE((item && item->GetString("id", &id)));
535 EXPECT_EQ("319009", id);
536
537 std::string ph;
538 EXPECT_TRUE((item && item->GetString("ph", &ph)));
539 EXPECT_EQ("C", ph);
540
541 int value;
542 EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
543 EXPECT_EQ(31415, value);
544 }
545
546 EXPECT_FIND_("TRACE_COUNTER_ID2 call");
547 {
548 std::string id;
549 EXPECT_TRUE((item && item->GetString("id", &id)));
550 EXPECT_EQ("319009", id);
551
552 std::string ph;
553 EXPECT_TRUE((item && item->GetString("ph", &ph)));
554 EXPECT_EQ("C", ph);
555
556 int value;
557 EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
558 EXPECT_EQ(30000, value);
559
560 EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
561 EXPECT_EQ(1415, value);
562 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900563}
564
nduca@chromium.org6d048772011-08-10 00:16:25 +0900565void TraceManyInstantEvents(int thread_id, int num_events,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900566 WaitableEvent* task_complete_event) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900567 for (int i = 0; i < num_events; i++) {
568 TRACE_EVENT_INSTANT2("all", "multi thread event",
569 "thread", thread_id,
570 "event", i);
571 }
572
573 if (task_complete_event)
574 task_complete_event->Signal();
575}
576
577void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900578 int num_threads,
579 int num_events) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900580 std::map<int, std::map<int, bool> > results;
581
582 size_t trace_parsed_count = trace_parsed.GetSize();
583 for (size_t i = 0; i < trace_parsed_count; i++) {
584 Value* value = NULL;
585 trace_parsed.Get(i, &value);
586 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
587 continue;
588 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
589 std::string name;
590 dict->GetString("name", &name);
591 if (name != "multi thread event")
592 continue;
593
594 int thread = 0;
595 int event = 0;
596 EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
597 EXPECT_TRUE(dict->GetInteger("args.event", &event));
598 results[thread][event] = true;
599 }
600
601 EXPECT_FALSE(results[-1][-1]);
602 for (int thread = 0; thread < num_threads; thread++) {
603 for (int event = 0; event < num_events; event++) {
604 EXPECT_TRUE(results[thread][event]);
605 }
606 }
607}
608
609void TraceCallsWithCachedCategoryPointersPointers(const char* name_str) {
610 TRACE_EVENT0("category name1", name_str);
611 TRACE_EVENT_INSTANT0("category name2", name_str);
612 TRACE_EVENT_BEGIN0("category name3", name_str);
613 TRACE_EVENT_END0("category name4", name_str);
614}
615
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900616} // namespace
617
618// Simple Test for emitting data and validating it was received.
619TEST_F(TraceEventTestFixture, DataCaptured) {
620 ManualTestSetUp();
621 TraceLog::GetInstance()->SetEnabled(true);
622
nduca@chromium.org6d048772011-08-10 00:16:25 +0900623 TraceWithAllMacroVariants(NULL);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900624
625 TraceLog::GetInstance()->SetEnabled(false);
626
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900627 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900628}
629
nduca@chromium.org6a7360c2012-02-20 15:35:15 +0900630class MockEnabledStateChangedObserver :
631 public base::debug::TraceLog::EnabledStateChangedObserver {
632 public:
633 MOCK_METHOD0(OnTraceLogWillEnable, void());
634 MOCK_METHOD0(OnTraceLogWillDisable, void());
635};
636
637TEST_F(TraceEventTestFixture, EnabledObserverFiresOnEnable) {
638 ManualTestSetUp();
639
640 MockEnabledStateChangedObserver observer;
641 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
642
643 EXPECT_CALL(observer, OnTraceLogWillEnable())
644 .Times(1);
645 TraceLog::GetInstance()->SetEnabled(true);
646 testing::Mock::VerifyAndClear(&observer);
647
648 // Cleanup.
649 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
650 TraceLog::GetInstance()->SetEnabled(false);
651}
652
653TEST_F(TraceEventTestFixture, EnabledObserverDoesntFireOnSecondEnable) {
654 ManualTestSetUp();
655
656 TraceLog::GetInstance()->SetEnabled(true);
657
658 testing::StrictMock<MockEnabledStateChangedObserver> observer;
659 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
660
661 EXPECT_CALL(observer, OnTraceLogWillEnable())
662 .Times(0);
663 EXPECT_CALL(observer, OnTraceLogWillDisable())
664 .Times(0);
665 TraceLog::GetInstance()->SetEnabled(true);
666 testing::Mock::VerifyAndClear(&observer);
667
668 // Cleanup.
669 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
670 TraceLog::GetInstance()->SetEnabled(false);
671}
672
673TEST_F(TraceEventTestFixture, EnabledObserverDoesntFireOnUselessDisable) {
674 ManualTestSetUp();
675
676
677 testing::StrictMock<MockEnabledStateChangedObserver> observer;
678 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
679
680 EXPECT_CALL(observer, OnTraceLogWillEnable())
681 .Times(0);
682 EXPECT_CALL(observer, OnTraceLogWillDisable())
683 .Times(0);
684 TraceLog::GetInstance()->SetEnabled(false);
685 testing::Mock::VerifyAndClear(&observer);
686
687 // Cleanup.
688 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
689}
690
691TEST_F(TraceEventTestFixture, EnabledObserverFiresOnDisable) {
692 ManualTestSetUp();
693
694 TraceLog::GetInstance()->SetEnabled(true);
695
696 MockEnabledStateChangedObserver observer;
697 TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
698
699 EXPECT_CALL(observer, OnTraceLogWillDisable())
700 .Times(1);
701 TraceLog::GetInstance()->SetEnabled(false);
702 testing::Mock::VerifyAndClear(&observer);
703
704 // Cleanup.
705 TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
706}
707
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900708// Test that categories work.
709TEST_F(TraceEventTestFixture, Categories) {
710 ManualTestSetUp();
711
712 // Test that categories that are used can be retrieved whether trace was
713 // enabled or disabled when the trace event was encountered.
714 TRACE_EVENT_INSTANT0("c1", "name");
715 TRACE_EVENT_INSTANT0("c2", "name");
716 TraceLog::GetInstance()->SetEnabled(true);
717 TRACE_EVENT_INSTANT0("c3", "name");
718 TRACE_EVENT_INSTANT0("c4", "name");
719 TraceLog::GetInstance()->SetEnabled(false);
720 std::vector<std::string> cats;
721 TraceLog::GetInstance()->GetKnownCategories(&cats);
722 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c1") != cats.end());
723 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c2") != cats.end());
724 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c3") != cats.end());
725 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c4") != cats.end());
726
727 const std::vector<std::string> empty_categories;
728 std::vector<std::string> included_categories;
729 std::vector<std::string> excluded_categories;
730
731 // Test that category filtering works.
732
733 // Include nonexistent category -> no events
734 Clear();
735 included_categories.clear();
736 included_categories.push_back("not_found823564786");
737 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
738 TRACE_EVENT_INSTANT0("cat1", "name");
739 TRACE_EVENT_INSTANT0("cat2", "name");
740 TraceLog::GetInstance()->SetDisabled();
741 EXPECT_TRUE(trace_parsed_.empty());
742
743 // Include existent category -> only events of that category
744 Clear();
745 included_categories.clear();
746 included_categories.push_back("inc");
747 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
748 TRACE_EVENT_INSTANT0("inc", "name");
749 TRACE_EVENT_INSTANT0("inc2", "name");
750 TraceLog::GetInstance()->SetDisabled();
751 EXPECT_TRUE(FindMatchingValue("cat", "inc"));
752 EXPECT_FALSE(FindNonMatchingValue("cat", "inc"));
753
754 // Include existent wildcard -> all categories matching wildcard
755 Clear();
756 included_categories.clear();
757 included_categories.push_back("inc_wildcard_*");
758 included_categories.push_back("inc_wildchar_?_end");
759 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
760 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "included");
761 TRACE_EVENT_INSTANT0("inc_wildcard_", "included");
762 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "included");
763 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "not_inc");
764 TRACE_EVENT_INSTANT0("cat1", "not_inc");
765 TRACE_EVENT_INSTANT0("cat2", "not_inc");
766 TraceLog::GetInstance()->SetDisabled();
767 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_abc"));
768 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_"));
769 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_x_end"));
770 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
771
772 included_categories.clear();
773
774 // Exclude nonexistent category -> all events
775 Clear();
776 excluded_categories.clear();
777 excluded_categories.push_back("not_found823564786");
778 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
779 TRACE_EVENT_INSTANT0("cat1", "name");
780 TRACE_EVENT_INSTANT0("cat2", "name");
781 TraceLog::GetInstance()->SetDisabled();
782 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
783 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
784
785 // Exclude existent category -> only events of other categories
786 Clear();
787 excluded_categories.clear();
788 excluded_categories.push_back("inc");
789 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
790 TRACE_EVENT_INSTANT0("inc", "name");
791 TRACE_EVENT_INSTANT0("inc2", "name");
792 TraceLog::GetInstance()->SetDisabled();
793 EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
794 EXPECT_FALSE(FindMatchingValue("cat", "inc"));
795
796 // Exclude existent wildcard -> all categories not matching wildcard
797 Clear();
798 excluded_categories.clear();
799 excluded_categories.push_back("inc_wildcard_*");
800 excluded_categories.push_back("inc_wildchar_?_end");
801 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
802 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "not_inc");
803 TRACE_EVENT_INSTANT0("inc_wildcard_", "not_inc");
804 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "not_inc");
805 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "included");
806 TRACE_EVENT_INSTANT0("cat1", "included");
807 TRACE_EVENT_INSTANT0("cat2", "included");
808 TraceLog::GetInstance()->SetDisabled();
809 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_bla_end"));
810 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
811 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
812 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
813}
814
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900815// Simple Test for time threshold events.
816TEST_F(TraceEventTestFixture, DataCapturedThreshold) {
817 ManualTestSetUp();
818 TraceLog::GetInstance()->SetEnabled(true);
819
820 // Test that events at the same level are properly filtered by threshold.
821 {
822 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "threshold 100");
823 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "threshold 1000");
824 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "threshold 10000");
825 // 100+ seconds to avoid flakiness.
826 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "threshold long1");
827 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "threshold long2");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900828 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900829 }
830
831 // Test that a normal nested event remains after it's parent event is dropped.
832 {
833 TRACE_EVENT_IF_LONGER_THAN0(1000000, "time", "2threshold10000");
834 {
835 TRACE_EVENT0("time", "nonthreshold1");
836 }
837 }
838
839 // Test that parent thresholded events are dropped while some nested events
840 // remain.
841 {
842 TRACE_EVENT0("time", "nonthreshold3");
843 {
844 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "3thresholdlong2");
845 {
846 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "3thresholdlong1");
847 {
848 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "3threshold10000");
849 {
850 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "3threshold1000");
851 {
852 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "3threshold100");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900853 base::PlatformThread::Sleep(
854 base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900855 }
856 }
857 }
858 }
859 }
860 }
861
862 // Test that child thresholded events are dropped while some parent events
863 // remain.
864 {
865 TRACE_EVENT0("time", "nonthreshold4");
866 {
867 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "4threshold100");
868 {
869 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "4threshold1000");
870 {
871 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "4threshold10000");
872 {
873 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time",
874 "4thresholdlong1");
875 {
876 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time",
877 "4thresholdlong2");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900878 base::PlatformThread::Sleep(
879 base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900880 }
881 }
882 }
883 }
884 }
885 }
886
887 TraceLog::GetInstance()->SetEnabled(false);
888
889#define EXPECT_FIND_BE_(str) \
890 EXPECT_TRUE(FindNamePhase(str, "B")); \
891 EXPECT_TRUE(FindNamePhase(str, "E"))
892#define EXPECT_NOT_FIND_BE_(str) \
893 EXPECT_FALSE(FindNamePhase(str, "B")); \
894 EXPECT_FALSE(FindNamePhase(str, "E"))
895
896 EXPECT_FIND_BE_("threshold 100");
897 EXPECT_FIND_BE_("threshold 1000");
898 EXPECT_FIND_BE_("threshold 10000");
899 EXPECT_NOT_FIND_BE_("threshold long1");
900 EXPECT_NOT_FIND_BE_("threshold long2");
901
902 EXPECT_NOT_FIND_BE_("2threshold10000");
903 EXPECT_FIND_BE_("nonthreshold1");
904
905 EXPECT_FIND_BE_("nonthreshold3");
906 EXPECT_FIND_BE_("3threshold100");
907 EXPECT_FIND_BE_("3threshold1000");
908 EXPECT_FIND_BE_("3threshold10000");
909 EXPECT_NOT_FIND_BE_("3thresholdlong1");
910 EXPECT_NOT_FIND_BE_("3thresholdlong2");
911
912 EXPECT_FIND_BE_("nonthreshold4");
913 EXPECT_FIND_BE_("4threshold100");
914 EXPECT_FIND_BE_("4threshold1000");
915 EXPECT_FIND_BE_("4threshold10000");
916 EXPECT_NOT_FIND_BE_("4thresholdlong1");
917 EXPECT_NOT_FIND_BE_("4thresholdlong2");
918}
919
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900920// Test Start/Finish events
921TEST_F(TraceEventTestFixture, StartFinishEvents) {
922 ManualTestSetUp();
923 TraceLog::GetInstance()->SetEnabled(true);
924
925 unsigned long long id = 0xfeedbeeffeedbeefull;
926 TRACE_EVENT_START0( "cat", "name1", id);
927 TRACE_EVENT_FINISH0("cat", "name1", id);
928 TRACE_EVENT_BEGIN0( "cat", "name2");
929 TRACE_EVENT_START0( "cat", "name3", 0);
930
931 TraceLog::GetInstance()->SetEnabled(false);
932
933 EXPECT_TRUE(FindNamePhase("name1", "S"));
934 EXPECT_TRUE(FindNamePhase("name1", "F"));
935
936 std::string id_str;
937 StringAppendF(&id_str, "%llx", id);
938
939 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "S", "id", id_str.c_str()));
940 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "F", "id", id_str.c_str()));
941 EXPECT_TRUE(FindNamePhaseKeyValue("name3", "S", "id", "0"));
942
943 // BEGIN events should not have id
944 EXPECT_FALSE(FindNamePhaseKeyValue("name2", "B", "id", "0"));
945}
946
947// Test Start/Finish events
948TEST_F(TraceEventTestFixture, StartFinishPointerMangling) {
949 ManualTestSetUp();
950
951 void* ptr = this;
952
953 TraceLog::GetInstance()->SetProcessID(100);
954 TraceLog::GetInstance()->SetEnabled(true);
955 TRACE_EVENT_START0( "cat", "name1", ptr);
956 TRACE_EVENT_START0( "cat", "name2", ptr);
957 TraceLog::GetInstance()->SetEnabled(false);
958
959 TraceLog::GetInstance()->SetProcessID(200);
960 TraceLog::GetInstance()->SetEnabled(true);
961 TRACE_EVENT_FINISH0( "cat", "name1", ptr);
962 TraceLog::GetInstance()->SetEnabled(false);
963
964 DictionaryValue* start = FindNamePhase("name1", "S");
965 DictionaryValue* start2 = FindNamePhase("name2", "S");
966 DictionaryValue* finish = FindNamePhase("name1", "F");
967 EXPECT_TRUE(start);
968 EXPECT_TRUE(start2);
969 EXPECT_TRUE(finish);
970
971 Value* value = NULL;
972 std::string start_id_str;
973 std::string start2_id_str;
974 std::string finish_id_str;
975 ASSERT_TRUE(start->Get("id", &value));
976 ASSERT_TRUE(value->GetAsString(&start_id_str));
977 ASSERT_TRUE(start2->Get("id", &value));
978 ASSERT_TRUE(value->GetAsString(&start2_id_str));
979 ASSERT_TRUE(finish->Get("id", &value));
980 ASSERT_TRUE(value->GetAsString(&finish_id_str));
981
982 EXPECT_STREQ(start_id_str.c_str(), start2_id_str.c_str());
983 EXPECT_STRNE(start_id_str.c_str(), finish_id_str.c_str());
984}
985
jbates@chromium.org1f18e462011-09-07 02:56:24 +0900986// Test that static strings are not copied.
987TEST_F(TraceEventTestFixture, StaticStringVsString) {
988 ManualTestSetUp();
989 TraceLog* tracer = TraceLog::GetInstance();
990 // Make sure old events are flushed:
991 tracer->SetEnabled(false);
992 EXPECT_EQ(0u, tracer->GetEventsSize());
993
994 {
995 tracer->SetEnabled(true);
996 // Test that string arguments are copied.
997 TRACE_EVENT2("cat", "name1",
998 "arg1", std::string("argval"), "arg2", std::string("argval"));
999 // Test that static TRACE_STR_COPY string arguments are copied.
1000 TRACE_EVENT2("cat", "name2",
1001 "arg1", TRACE_STR_COPY("argval"),
1002 "arg2", TRACE_STR_COPY("argval"));
1003 size_t num_events = tracer->GetEventsSize();
1004 EXPECT_GT(num_events, 1u);
1005 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
1006 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
1007 EXPECT_STREQ("name1", event1.name());
1008 EXPECT_STREQ("name2", event2.name());
1009 EXPECT_TRUE(event1.parameter_copy_storage() != NULL);
1010 EXPECT_TRUE(event2.parameter_copy_storage() != NULL);
1011 EXPECT_GT(event1.parameter_copy_storage()->size(), 0u);
1012 EXPECT_GT(event2.parameter_copy_storage()->size(), 0u);
1013 tracer->SetEnabled(false);
1014 }
1015
1016 {
1017 tracer->SetEnabled(true);
1018 // Test that static literal string arguments are not copied.
1019 TRACE_EVENT2("cat", "name1",
1020 "arg1", "argval", "arg2", "argval");
1021 // Test that static TRACE_STR_COPY NULL string arguments are not copied.
1022 const char* str1 = NULL;
1023 const char* str2 = NULL;
1024 TRACE_EVENT2("cat", "name2",
1025 "arg1", TRACE_STR_COPY(str1),
1026 "arg2", TRACE_STR_COPY(str2));
1027 size_t num_events = tracer->GetEventsSize();
1028 EXPECT_GT(num_events, 1u);
1029 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
1030 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
1031 EXPECT_STREQ("name1", event1.name());
1032 EXPECT_STREQ("name2", event2.name());
1033 EXPECT_TRUE(event1.parameter_copy_storage() == NULL);
1034 EXPECT_TRUE(event2.parameter_copy_storage() == NULL);
1035 tracer->SetEnabled(false);
1036 }
1037}
1038
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001039// Test that data sent from other threads is gathered
1040TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
1041 ManualTestSetUp();
1042 TraceLog::GetInstance()->SetEnabled(true);
1043
1044 Thread thread("1");
1045 WaitableEvent task_complete_event(false, false);
1046 thread.Start();
1047
1048 thread.message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +09001049 FROM_HERE, base::Bind(&TraceWithAllMacroVariants, &task_complete_event));
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001050 task_complete_event.Wait();
jbates@chromium.orgb84db522011-10-04 02:51:25 +09001051 thread.Stop();
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001052
1053 TraceLog::GetInstance()->SetEnabled(false);
jbates@chromium.org6a092d72011-10-25 01:34:08 +09001054 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001055}
1056
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001057// Test that data sent from multiple threads is gathered
1058TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
1059 ManualTestSetUp();
1060 TraceLog::GetInstance()->SetEnabled(true);
1061
1062 const int num_threads = 4;
1063 const int num_events = 4000;
1064 Thread* threads[num_threads];
1065 WaitableEvent* task_complete_events[num_threads];
1066 for (int i = 0; i < num_threads; i++) {
1067 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
1068 task_complete_events[i] = new WaitableEvent(false, false);
1069 threads[i]->Start();
1070 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +09001071 FROM_HERE, base::Bind(&TraceManyInstantEvents,
1072 i, num_events, task_complete_events[i]));
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001073 }
1074
1075 for (int i = 0; i < num_threads; i++) {
1076 task_complete_events[i]->Wait();
1077 }
1078
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001079 for (int i = 0; i < num_threads; i++) {
1080 threads[i]->Stop();
1081 delete threads[i];
1082 delete task_complete_events[i];
1083 }
1084
jbates@chromium.orgb84db522011-10-04 02:51:25 +09001085 TraceLog::GetInstance()->SetEnabled(false);
1086
jbates@chromium.org6a092d72011-10-25 01:34:08 +09001087 ValidateInstantEventPresentOnEveryThread(trace_parsed_,
nduca@chromium.org6d048772011-08-10 00:16:25 +09001088 num_threads, num_events);
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001089}
1090
nduca@chromium.org6d048772011-08-10 00:16:25 +09001091// Test that thread and process names show up in the trace
1092TEST_F(TraceEventTestFixture, ThreadNames) {
1093 ManualTestSetUp();
1094
1095 // Create threads before we enable tracing to make sure
1096 // that tracelog still captures them.
1097 const int num_threads = 4;
1098 const int num_events = 10;
1099 Thread* threads[num_threads];
1100 PlatformThreadId thread_ids[num_threads];
1101 for (int i = 0; i < num_threads; i++)
1102 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
1103
1104 // Enable tracing.
1105 TraceLog::GetInstance()->SetEnabled(true);
1106
1107 // Now run some trace code on these threads.
1108 WaitableEvent* task_complete_events[num_threads];
1109 for (int i = 0; i < num_threads; i++) {
1110 task_complete_events[i] = new WaitableEvent(false, false);
1111 threads[i]->Start();
1112 thread_ids[i] = threads[i]->thread_id();
1113 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +09001114 FROM_HERE, base::Bind(&TraceManyInstantEvents,
1115 i, num_events, task_complete_events[i]));
nduca@chromium.org6d048772011-08-10 00:16:25 +09001116 }
1117 for (int i = 0; i < num_threads; i++) {
1118 task_complete_events[i]->Wait();
1119 }
1120
1121 // Shut things down.
nduca@chromium.org6d048772011-08-10 00:16:25 +09001122 for (int i = 0; i < num_threads; i++) {
1123 threads[i]->Stop();
1124 delete threads[i];
1125 delete task_complete_events[i];
1126 }
1127
jbates@chromium.orgb84db522011-10-04 02:51:25 +09001128 TraceLog::GetInstance()->SetEnabled(false);
1129
nduca@chromium.org6d048772011-08-10 00:16:25 +09001130 std::string tmp;
1131 int tmp_int;
1132 DictionaryValue* item;
1133
1134 // Make sure we get thread name metadata.
1135 // Note, the test suite may have created a ton of threads.
1136 // So, we'll have thread names for threads we didn't create.
1137 std::vector<DictionaryValue*> items =
1138 FindTraceEntries(trace_parsed_, "thread_name");
1139 for (int i = 0; i < static_cast<int>(items.size()); i++) {
1140 item = items[i];
joth@chromium.org088ae012011-11-11 01:26:23 +09001141 ASSERT_TRUE(item);
nduca@chromium.org6d048772011-08-10 00:16:25 +09001142 EXPECT_TRUE(item->GetInteger("tid", &tmp_int));
1143
1144 // See if this thread name is one of the threads we just created
1145 for (int j = 0; j < num_threads; j++) {
1146 if(static_cast<int>(thread_ids[j]) != tmp_int)
1147 continue;
1148
jbates@chromium.org62a16662012-02-04 08:18:06 +09001149 std::string expected_name = StringPrintf("Thread %d", j);
nduca@chromium.org6d048772011-08-10 00:16:25 +09001150 EXPECT_TRUE(item->GetString("ph", &tmp) && tmp == "M");
1151 EXPECT_TRUE(item->GetInteger("pid", &tmp_int) &&
1152 tmp_int == static_cast<int>(base::GetCurrentProcId()));
jbates@chromium.org62a16662012-02-04 08:18:06 +09001153 // If the thread name changes or the tid gets reused, the name will be
1154 // a comma-separated list of thread names, so look for a substring.
nduca@chromium.org6d048772011-08-10 00:16:25 +09001155 EXPECT_TRUE(item->GetString("args.name", &tmp) &&
jbates@chromium.org62a16662012-02-04 08:18:06 +09001156 tmp.find(expected_name) != std::string::npos);
nduca@chromium.org6d048772011-08-10 00:16:25 +09001157 }
1158 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001159}
1160
joth@chromium.org088ae012011-11-11 01:26:23 +09001161TEST_F(TraceEventTestFixture, ThreadNameChanges) {
1162 ManualTestSetUp();
1163
1164 TraceLog::GetInstance()->SetEnabled(true);
1165
1166 PlatformThread::SetName("");
1167 TRACE_EVENT_INSTANT0("drink", "water");
1168
1169 PlatformThread::SetName("cafe");
1170 TRACE_EVENT_INSTANT0("drink", "coffee");
1171
1172 PlatformThread::SetName("shop");
1173 // No event here, so won't appear in combined name.
1174
1175 PlatformThread::SetName("pub");
1176 TRACE_EVENT_INSTANT0("drink", "beer");
1177 TRACE_EVENT_INSTANT0("drink", "wine");
1178
1179 PlatformThread::SetName(" bar");
1180 TRACE_EVENT_INSTANT0("drink", "whisky");
1181
1182 TraceLog::GetInstance()->SetEnabled(false);
1183
1184 std::vector<DictionaryValue*> items =
1185 FindTraceEntries(trace_parsed_, "thread_name");
1186 EXPECT_EQ(1u, items.size());
1187 ASSERT_GT(items.size(), 0u);
1188 DictionaryValue* item = items[0];
1189 ASSERT_TRUE(item);
1190 int tid;
1191 EXPECT_TRUE(item->GetInteger("tid", &tid));
1192 EXPECT_EQ(PlatformThread::CurrentId(), static_cast<PlatformThreadId>(tid));
1193
1194 std::string expected_name = "cafe,pub, bar";
1195 std::string tmp;
1196 EXPECT_TRUE(item->GetString("args.name", &tmp));
1197 EXPECT_EQ(expected_name, tmp);
1198}
nduca@chromium.org6d048772011-08-10 00:16:25 +09001199
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001200// Test trace calls made after tracing singleton shut down.
1201//
1202// The singleton is destroyed by our base::AtExitManager, but there can be
1203// code still executing as the C++ static objects are destroyed. This test
1204// forces the singleton to destroy early, and intentinally makes trace calls
1205// afterwards.
1206TEST_F(TraceEventTestFixture, AtExit) {
1207 // Repeat this test a few times. Besides just showing robustness, it also
1208 // allows us to test that events at shutdown do not appear with valid events
1209 // recorded after the system is started again.
1210 for (int i = 0; i < 4; i++) {
1211 // Scope to contain the then destroy the TraceLog singleton.
1212 {
1213 base::ShadowingAtExitManager exit_manager_will_destroy_singletons;
1214
1215 // Setup TraceLog singleton inside this test's exit manager scope
1216 // so that it will be destroyed when this scope closes.
1217 ManualTestSetUp();
1218
1219 TRACE_EVENT_INSTANT0("all", "not recorded; system not enabled");
1220
1221 TraceLog::GetInstance()->SetEnabled(true);
1222
1223 TRACE_EVENT_INSTANT0("all", "is recorded 1; system has been enabled");
1224 // Trace calls that will cache pointers to categories; they're valid here
1225 TraceCallsWithCachedCategoryPointersPointers(
1226 "is recorded 2; system has been enabled");
1227
1228 TraceLog::GetInstance()->SetEnabled(false);
1229 } // scope to destroy singleton
1230 ASSERT_FALSE(TraceLog::GetInstance());
1231
1232 // Now that singleton is destroyed, check what trace events were recorded
1233 DictionaryValue* item = NULL;
1234 ListValue& trace_parsed = trace_parsed_;
1235 EXPECT_FIND_("is recorded 1");
1236 EXPECT_FIND_("is recorded 2");
1237 EXPECT_NOT_FIND_("not recorded");
1238
1239 // Make additional trace event calls on the shutdown system. They should
1240 // all pass cleanly, but the data not be recorded. We'll verify that next
1241 // time around the loop (the only way to flush the trace buffers).
1242 TRACE_EVENT_BEGIN_ETW("not recorded; system shutdown", 0, NULL);
1243 TRACE_EVENT_END_ETW("not recorded; system shutdown", 0, NULL);
1244 TRACE_EVENT_INSTANT_ETW("not recorded; system shutdown", 0, NULL);
1245 TRACE_EVENT0("all", "not recorded; system shutdown");
1246 TRACE_EVENT_INSTANT0("all", "not recorded; system shutdown");
1247 TRACE_EVENT_BEGIN0("all", "not recorded; system shutdown");
1248 TRACE_EVENT_END0("all", "not recorded; system shutdown");
1249
1250 TRACE_EVENT0("new category 0!", "not recorded; system shutdown");
1251 TRACE_EVENT_INSTANT0("new category 1!", "not recorded; system shutdown");
1252 TRACE_EVENT_BEGIN0("new category 2!", "not recorded; system shutdown");
1253 TRACE_EVENT_END0("new category 3!", "not recorded; system shutdown");
1254
1255 // Cached categories should be safe to check, and still disable traces
1256 TraceCallsWithCachedCategoryPointersPointers(
1257 "not recorded; system shutdown");
1258 }
1259}
1260
joth@chromium.org113de992011-07-21 21:28:59 +09001261TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
1262 // Test that the TRACE_EVENT macros do not deep-copy their string. If they
1263 // do so it may indicate a performance regression, but more-over it would
1264 // make the DEEP_COPY overloads redundant.
1265 ManualTestSetUp();
1266
1267 std::string name_string("event name");
1268
1269 TraceLog::GetInstance()->SetEnabled(true);
1270 TRACE_EVENT_INSTANT0("category", name_string.c_str());
1271
1272 // Modify the string in place (a wholesale reassignment may leave the old
1273 // string intact on the heap).
1274 name_string[0] = '@';
1275
1276 TraceLog::GetInstance()->SetEnabled(false);
1277
1278 EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
1279 EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
1280}
1281
1282TEST_F(TraceEventTestFixture, DeepCopy) {
1283 ManualTestSetUp();
1284
1285 static const char kOriginalName1[] = "name1";
1286 static const char kOriginalName2[] = "name2";
1287 static const char kOriginalName3[] = "name3";
1288 std::string name1(kOriginalName1);
1289 std::string name2(kOriginalName2);
1290 std::string name3(kOriginalName3);
1291 std::string arg1("arg1");
1292 std::string arg2("arg2");
1293 std::string val1("val1");
1294 std::string val2("val2");
1295
1296 TraceLog::GetInstance()->SetEnabled(true);
1297 TRACE_EVENT_COPY_INSTANT0("category", name1.c_str());
1298 TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
1299 arg1.c_str(), 5);
1300 TRACE_EVENT_COPY_END2("category", name3.c_str(),
jbates@chromium.org1f18e462011-09-07 02:56:24 +09001301 arg1.c_str(), val1,
1302 arg2.c_str(), val2);
joth@chromium.org113de992011-07-21 21:28:59 +09001303
1304 // As per NormallyNoDeepCopy, modify the strings in place.
1305 name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
1306
1307 TraceLog::GetInstance()->SetEnabled(false);
1308
1309 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
1310 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
1311 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
1312
1313 DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
1314 DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
1315 DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
1316 ASSERT_TRUE(entry1);
1317 ASSERT_TRUE(entry2);
1318 ASSERT_TRUE(entry3);
1319
1320 int i;
1321 EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
1322 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
1323 EXPECT_EQ(5, i);
1324
1325 std::string s;
1326 EXPECT_TRUE(entry3->GetString("args.arg1", &s));
1327 EXPECT_EQ("val1", s);
1328 EXPECT_TRUE(entry3->GetString("args.arg2", &s));
1329 EXPECT_EQ("val2", s);
1330}
1331
jbates@chromium.org6a092d72011-10-25 01:34:08 +09001332// Test that TraceResultBuffer outputs the correct result whether it is added
1333// in chunks or added all at once.
1334TEST_F(TraceEventTestFixture, TraceResultBuffer) {
1335 ManualTestSetUp();
1336
1337 Clear();
1338
1339 trace_buffer_.Start();
1340 trace_buffer_.AddFragment("bla1");
1341 trace_buffer_.AddFragment("bla2");
1342 trace_buffer_.AddFragment("bla3,bla4");
1343 trace_buffer_.Finish();
1344 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1345
1346 Clear();
1347
1348 trace_buffer_.Start();
1349 trace_buffer_.AddFragment("bla1,bla2,bla3,bla4");
1350 trace_buffer_.Finish();
1351 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1352}
1353
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001354} // namespace debug
1355} // namespace base