blob: 8486f90ff0e3fafce714056e051500c66266dea7 [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(
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
jbates@chromium.org59c27602012-01-13 12:12:44 +0900102 if (!root.get()) {
103 LOG(ERROR) << json_output_.json_output;
104 }
105
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900106 ListValue* root_list = NULL;
107 ASSERT_TRUE(root.get());
108 ASSERT_TRUE(root->GetAsList(&root_list));
109
110 // Move items into our aggregate collection
111 while (root_list->GetSize()) {
112 Value* item = NULL;
113 root_list->Remove(0, &item);
114 trace_parsed_.Append(item);
115 }
116}
117
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900118static bool CompareJsonValues(const std::string& lhs,
119 const std::string& rhs,
120 CompareOp op) {
121 switch (op) {
122 case IS_EQUAL:
123 return lhs == rhs;
124 case IS_NOT_EQUAL:
125 return lhs != rhs;
126 default:
127 CHECK(0);
128 }
129 return false;
130}
131
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900132static bool IsKeyValueInDict(const JsonKeyValue* key_value,
133 DictionaryValue* dict) {
134 Value* value = NULL;
135 std::string value_str;
136 if (dict->Get(key_value->key, &value) &&
137 value->GetAsString(&value_str) &&
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900138 CompareJsonValues(value_str, key_value->value, key_value->op))
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900139 return true;
140
141 // Recurse to test arguments
142 DictionaryValue* args_dict = NULL;
143 dict->GetDictionary("args", &args_dict);
144 if (args_dict)
145 return IsKeyValueInDict(key_value, args_dict);
146
147 return false;
148}
149
150static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
151 DictionaryValue* dict) {
152 // Scan all key_values, they must all be present and equal.
153 while (key_values && key_values->key) {
154 if (!IsKeyValueInDict(key_values, dict))
155 return false;
156 ++key_values;
157 }
158 return true;
159}
160
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900161DictionaryValue* TraceEventTestFixture::FindMatchingTraceEntry(
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900162 const JsonKeyValue* key_values) {
163 // Scan all items
164 size_t trace_parsed_count = trace_parsed_.GetSize();
165 for (size_t i = 0; i < trace_parsed_count; i++) {
166 Value* value = NULL;
167 trace_parsed_.Get(i, &value);
168 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
169 continue;
170 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
171
172 if (IsAllKeyValueInDict(key_values, dict))
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900173 return dict;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900174 }
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900175 return NULL;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900176}
177
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900178DictionaryValue* TraceEventTestFixture::FindNamePhase(const char* name,
179 const char* phase) {
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900180 JsonKeyValue key_values[] = {
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900181 {"name", name, IS_EQUAL},
182 {"ph", phase, IS_EQUAL},
183 {0, 0, IS_EQUAL}
184 };
185 return FindMatchingTraceEntry(key_values);
186}
187
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900188DictionaryValue* TraceEventTestFixture::FindNamePhaseKeyValue(
189 const char* name,
190 const char* phase,
191 const char* key,
192 const char* value) {
193 JsonKeyValue key_values[] = {
194 {"name", name, IS_EQUAL},
195 {"ph", phase, IS_EQUAL},
196 {key, value, IS_EQUAL},
197 {0, 0, IS_EQUAL}
198 };
199 return FindMatchingTraceEntry(key_values);
200}
201
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900202bool TraceEventTestFixture::FindMatchingValue(const char* key,
203 const char* value) {
204 JsonKeyValue key_values[] = {
205 {key, value, IS_EQUAL},
206 {0, 0, IS_EQUAL}
207 };
208 return FindMatchingTraceEntry(key_values);
209}
210
211bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
212 const char* value) {
213 JsonKeyValue key_values[] = {
214 {key, value, IS_NOT_EQUAL},
215 {0, 0, IS_EQUAL}
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900216 };
217 return FindMatchingTraceEntry(key_values);
218}
219
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900220bool IsStringInDict(const char* string_to_match, DictionaryValue* dict) {
221 for (DictionaryValue::key_iterator ikey = dict->begin_keys();
222 ikey != dict->end_keys(); ++ikey) {
223 Value* child = NULL;
224 if (!dict->GetWithoutPathExpansion(*ikey, &child))
225 continue;
226
227 if ((*ikey).find(string_to_match) != std::string::npos)
228 return true;
229
230 std::string value_str;
231 child->GetAsString(&value_str);
232 if (value_str.find(string_to_match) != std::string::npos)
233 return true;
234 }
235
236 // Recurse to test arguments
237 DictionaryValue* args_dict = NULL;
238 dict->GetDictionary("args", &args_dict);
239 if (args_dict)
240 return IsStringInDict(string_to_match, args_dict);
241
242 return false;
243}
244
245DictionaryValue* FindTraceEntry(const ListValue& trace_parsed,
nduca@chromium.org6d048772011-08-10 00:16:25 +0900246 const char* string_to_match,
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900247 DictionaryValue* match_after_this_item = NULL) {
248 // Scan all items
249 size_t trace_parsed_count = trace_parsed.GetSize();
250 for (size_t i = 0; i < trace_parsed_count; i++) {
251 Value* value = NULL;
252 trace_parsed.Get(i, &value);
253 if (match_after_this_item) {
254 if (value == match_after_this_item)
255 match_after_this_item = NULL;
256 continue;
257 }
258 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
259 continue;
260 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
261
262 if (IsStringInDict(string_to_match, dict))
263 return dict;
264 }
265 return NULL;
266}
267
nduca@chromium.org6d048772011-08-10 00:16:25 +0900268std::vector<DictionaryValue*> FindTraceEntries(
269 const ListValue& trace_parsed,
270 const char* string_to_match) {
271 std::vector<DictionaryValue*> hits;
272 size_t trace_parsed_count = trace_parsed.GetSize();
273 for (size_t i = 0; i < trace_parsed_count; i++) {
274 Value* value = NULL;
275 trace_parsed.Get(i, &value);
276 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
277 continue;
278 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
279
280 if (IsStringInDict(string_to_match, dict))
281 hits.push_back(dict);
282 }
283 return hits;
284}
285
286void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900287 {
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900288 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW call", 0x1122, "extrastring1");
289 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW call", 0x3344, "extrastring2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900290 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW call",
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900291 0x5566, "extrastring3");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900292
293 TRACE_EVENT0("all", "TRACE_EVENT0 call");
294 TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
295 TRACE_EVENT2("all", "TRACE_EVENT2 call",
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900296 "name1", "\"value1\"",
297 "name2", "value\\2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900298
299 TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call");
300 TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call", "name1", "value1");
301 TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
302 "name1", "value1",
303 "name2", "value2");
304
305 TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
306 TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
307 TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
308 "name1", "value1",
309 "name2", "value2");
310
311 TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
312 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
313 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
314 "name1", "value1",
315 "name2", "value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900316
jbates@chromium.org59c27602012-01-13 12:12:44 +0900317 TRACE_EVENT_IF_LONGER_THAN0(0, "all", "TRACE_EVENT_IF_LONGER_THAN0 call");
318 TRACE_EVENT_IF_LONGER_THAN1(0, "all", "TRACE_EVENT_IF_LONGER_THAN1 call",
319 "name1", "value1");
320 TRACE_EVENT_IF_LONGER_THAN2(0, "all", "TRACE_EVENT_IF_LONGER_THAN2 call",
321 "name1", "value1",
322 "name2", "value2");
323
324 TRACE_EVENT_START0("all", "TRACE_EVENT_START0 call", 5);
325 TRACE_EVENT_START1("all", "TRACE_EVENT_START1 call", 5,
326 "name1", "value1");
327 TRACE_EVENT_START2("all", "TRACE_EVENT_START2 call", 5,
328 "name1", "value1",
329 "name2", "value2");
330
331 TRACE_EVENT_FINISH0("all", "TRACE_EVENT_FINISH0 call", 5);
332 TRACE_EVENT_FINISH1("all", "TRACE_EVENT_FINISH1 call", 5,
333 "name1", "value1");
334 TRACE_EVENT_FINISH2("all", "TRACE_EVENT_FINISH2 call", 5,
335 "name1", "value1",
336 "name2", "value2");
337
338 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW0 call", 5, NULL);
339 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW1 call", 5, "value");
340 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW0 call", 5, NULL);
341 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW1 call", 5, "value");
342 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW0 call", 5, NULL);
343 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW1 call", 5, "value");
344
nduca@chromium.org62210b02011-11-18 18:36:36 +0900345 TRACE_COUNTER1("all", "TRACE_COUNTER1 call", 31415);
346 TRACE_COUNTER2("all", "TRACE_COUNTER2 call",
347 "a", 30000,
348 "b", 1415);
piman@chromium.org902b2952011-12-16 10:19:06 +0900349
350 TRACE_COUNTER_ID1("all", "TRACE_COUNTER_ID1 call", 0x319009, 31415);
351 TRACE_COUNTER_ID2("all", "TRACE_COUNTER_ID2 call", 0x319009,
352 "a", 30000, "b", 1415);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900353 } // Scope close causes TRACE_EVENT0 etc to send their END events.
354
355 if (task_complete_event)
356 task_complete_event->Signal();
357}
358
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900359void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900360 DictionaryValue* item = NULL;
361
362#define EXPECT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900363 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900364#define EXPECT_NOT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900365 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900366#define EXPECT_SUB_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900367 if (item) EXPECT_TRUE((IsStringInDict(string, item)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900368
369 EXPECT_FIND_("ETW Trace Event");
370 EXPECT_FIND_("all");
371 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW call");
372 {
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900373 std::string str_val;
374 EXPECT_TRUE(item && item->GetString("args.id", &str_val));
375 EXPECT_STREQ("1122", str_val.c_str());
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900376 }
377 EXPECT_SUB_FIND_("extrastring1");
378 EXPECT_FIND_("TRACE_EVENT_END_ETW call");
379 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW call");
380 EXPECT_FIND_("TRACE_EVENT0 call");
381 {
382 std::string ph_begin;
383 std::string ph_end;
384 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
385 EXPECT_TRUE((item && item->GetString("ph", &ph_begin)));
386 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call",
387 item)));
388 EXPECT_TRUE((item && item->GetString("ph", &ph_end)));
389 EXPECT_EQ("B", ph_begin);
390 EXPECT_EQ("E", ph_end);
391 }
392 EXPECT_FIND_("TRACE_EVENT1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900393 EXPECT_SUB_FIND_("name1");
394 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900395 EXPECT_FIND_("TRACE_EVENT2 call");
396 EXPECT_SUB_FIND_("name1");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900397 EXPECT_SUB_FIND_("\"value1\"");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900398 EXPECT_SUB_FIND_("name2");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900399 EXPECT_SUB_FIND_("value\\2");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900400
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900401 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
402 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900403 EXPECT_SUB_FIND_("name1");
404 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900405 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
406 EXPECT_SUB_FIND_("name1");
407 EXPECT_SUB_FIND_("value1");
408 EXPECT_SUB_FIND_("name2");
409 EXPECT_SUB_FIND_("value2");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900410
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900411 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
412 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900413 EXPECT_SUB_FIND_("name1");
414 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900415 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
416 EXPECT_SUB_FIND_("name1");
417 EXPECT_SUB_FIND_("value1");
418 EXPECT_SUB_FIND_("name2");
419 EXPECT_SUB_FIND_("value2");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900420
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900421 EXPECT_FIND_("TRACE_EVENT_END0 call");
422 EXPECT_FIND_("TRACE_EVENT_END1 call");
jbates@chromium.org59c27602012-01-13 12:12:44 +0900423 EXPECT_SUB_FIND_("name1");
424 EXPECT_SUB_FIND_("value1");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900425 EXPECT_FIND_("TRACE_EVENT_END2 call");
426 EXPECT_SUB_FIND_("name1");
427 EXPECT_SUB_FIND_("value1");
428 EXPECT_SUB_FIND_("name2");
429 EXPECT_SUB_FIND_("value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900430
jbates@chromium.org59c27602012-01-13 12:12:44 +0900431 EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN0 call");
432 EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN1 call");
433 EXPECT_SUB_FIND_("name1");
434 EXPECT_SUB_FIND_("value1");
435 EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN2 call");
436 EXPECT_SUB_FIND_("name1");
437 EXPECT_SUB_FIND_("value1");
438 EXPECT_SUB_FIND_("name2");
439 EXPECT_SUB_FIND_("value2");
440
441 EXPECT_FIND_("TRACE_EVENT_START0 call");
442 EXPECT_SUB_FIND_("id");
443 EXPECT_SUB_FIND_("5");
444 EXPECT_FIND_("TRACE_EVENT_START1 call");
445 EXPECT_SUB_FIND_("id");
446 EXPECT_SUB_FIND_("5");
447 EXPECT_SUB_FIND_("name1");
448 EXPECT_SUB_FIND_("value1");
449 EXPECT_FIND_("TRACE_EVENT_START2 call");
450 EXPECT_SUB_FIND_("id");
451 EXPECT_SUB_FIND_("5");
452 EXPECT_SUB_FIND_("name1");
453 EXPECT_SUB_FIND_("value1");
454 EXPECT_SUB_FIND_("name2");
455 EXPECT_SUB_FIND_("value2");
456
457 EXPECT_FIND_("TRACE_EVENT_FINISH0 call");
458 EXPECT_SUB_FIND_("id");
459 EXPECT_SUB_FIND_("5");
460 EXPECT_FIND_("TRACE_EVENT_FINISH1 call");
461 EXPECT_SUB_FIND_("id");
462 EXPECT_SUB_FIND_("5");
463 EXPECT_SUB_FIND_("name1");
464 EXPECT_SUB_FIND_("value1");
465 EXPECT_FIND_("TRACE_EVENT_FINISH2 call");
466 EXPECT_SUB_FIND_("id");
467 EXPECT_SUB_FIND_("5");
468 EXPECT_SUB_FIND_("name1");
469 EXPECT_SUB_FIND_("value1");
470 EXPECT_SUB_FIND_("name2");
471 EXPECT_SUB_FIND_("value2");
472
473 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW0 call");
474 EXPECT_SUB_FIND_("id");
475 EXPECT_SUB_FIND_("5");
476 EXPECT_SUB_FIND_("extra");
477 EXPECT_SUB_FIND_("NULL");
478 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW1 call");
479 EXPECT_SUB_FIND_("id");
480 EXPECT_SUB_FIND_("5");
481 EXPECT_SUB_FIND_("extra");
482 EXPECT_SUB_FIND_("value");
483 EXPECT_FIND_("TRACE_EVENT_END_ETW0 call");
484 EXPECT_SUB_FIND_("id");
485 EXPECT_SUB_FIND_("5");
486 EXPECT_SUB_FIND_("extra");
487 EXPECT_SUB_FIND_("NULL");
488 EXPECT_FIND_("TRACE_EVENT_END_ETW1 call");
489 EXPECT_SUB_FIND_("id");
490 EXPECT_SUB_FIND_("5");
491 EXPECT_SUB_FIND_("extra");
492 EXPECT_SUB_FIND_("value");
493 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW0 call");
494 EXPECT_SUB_FIND_("id");
495 EXPECT_SUB_FIND_("5");
496 EXPECT_SUB_FIND_("extra");
497 EXPECT_SUB_FIND_("NULL");
498 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW1 call");
499 EXPECT_SUB_FIND_("id");
500 EXPECT_SUB_FIND_("5");
501 EXPECT_SUB_FIND_("extra");
502 EXPECT_SUB_FIND_("value");
503
nduca@chromium.org62210b02011-11-18 18:36:36 +0900504 EXPECT_FIND_("TRACE_COUNTER1 call");
505 {
506 std::string ph;
507 EXPECT_TRUE((item && item->GetString("ph", &ph)));
508 EXPECT_EQ("C", ph);
509
510 int value;
511 EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
512 EXPECT_EQ(31415, value);
513 }
514
515 EXPECT_FIND_("TRACE_COUNTER2 call");
516 {
517 std::string ph;
518 EXPECT_TRUE((item && item->GetString("ph", &ph)));
519 EXPECT_EQ("C", ph);
520
521 int value;
522 EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
523 EXPECT_EQ(30000, value);
524
525 EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
526 EXPECT_EQ(1415, value);
527 }
528
piman@chromium.org902b2952011-12-16 10:19:06 +0900529 EXPECT_FIND_("TRACE_COUNTER_ID1 call");
530 {
531 std::string id;
532 EXPECT_TRUE((item && item->GetString("id", &id)));
533 EXPECT_EQ("319009", id);
534
535 std::string ph;
536 EXPECT_TRUE((item && item->GetString("ph", &ph)));
537 EXPECT_EQ("C", ph);
538
539 int value;
540 EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
541 EXPECT_EQ(31415, value);
542 }
543
544 EXPECT_FIND_("TRACE_COUNTER_ID2 call");
545 {
546 std::string id;
547 EXPECT_TRUE((item && item->GetString("id", &id)));
548 EXPECT_EQ("319009", id);
549
550 std::string ph;
551 EXPECT_TRUE((item && item->GetString("ph", &ph)));
552 EXPECT_EQ("C", ph);
553
554 int value;
555 EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
556 EXPECT_EQ(30000, value);
557
558 EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
559 EXPECT_EQ(1415, value);
560 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900561}
562
nduca@chromium.org6d048772011-08-10 00:16:25 +0900563void TraceManyInstantEvents(int thread_id, int num_events,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900564 WaitableEvent* task_complete_event) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900565 for (int i = 0; i < num_events; i++) {
566 TRACE_EVENT_INSTANT2("all", "multi thread event",
567 "thread", thread_id,
568 "event", i);
569 }
570
571 if (task_complete_event)
572 task_complete_event->Signal();
573}
574
575void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900576 int num_threads,
577 int num_events) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900578 std::map<int, std::map<int, bool> > results;
579
580 size_t trace_parsed_count = trace_parsed.GetSize();
581 for (size_t i = 0; i < trace_parsed_count; i++) {
582 Value* value = NULL;
583 trace_parsed.Get(i, &value);
584 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
585 continue;
586 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
587 std::string name;
588 dict->GetString("name", &name);
589 if (name != "multi thread event")
590 continue;
591
592 int thread = 0;
593 int event = 0;
594 EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
595 EXPECT_TRUE(dict->GetInteger("args.event", &event));
596 results[thread][event] = true;
597 }
598
599 EXPECT_FALSE(results[-1][-1]);
600 for (int thread = 0; thread < num_threads; thread++) {
601 for (int event = 0; event < num_events; event++) {
602 EXPECT_TRUE(results[thread][event]);
603 }
604 }
605}
606
607void TraceCallsWithCachedCategoryPointersPointers(const char* name_str) {
608 TRACE_EVENT0("category name1", name_str);
609 TRACE_EVENT_INSTANT0("category name2", name_str);
610 TRACE_EVENT_BEGIN0("category name3", name_str);
611 TRACE_EVENT_END0("category name4", name_str);
612}
613
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900614} // namespace
615
616// Simple Test for emitting data and validating it was received.
617TEST_F(TraceEventTestFixture, DataCaptured) {
618 ManualTestSetUp();
619 TraceLog::GetInstance()->SetEnabled(true);
620
nduca@chromium.org6d048772011-08-10 00:16:25 +0900621 TraceWithAllMacroVariants(NULL);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900622
623 TraceLog::GetInstance()->SetEnabled(false);
624
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900625 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900626}
627
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900628// Test that categories work.
629TEST_F(TraceEventTestFixture, Categories) {
630 ManualTestSetUp();
631
632 // Test that categories that are used can be retrieved whether trace was
633 // enabled or disabled when the trace event was encountered.
634 TRACE_EVENT_INSTANT0("c1", "name");
635 TRACE_EVENT_INSTANT0("c2", "name");
636 TraceLog::GetInstance()->SetEnabled(true);
637 TRACE_EVENT_INSTANT0("c3", "name");
638 TRACE_EVENT_INSTANT0("c4", "name");
639 TraceLog::GetInstance()->SetEnabled(false);
640 std::vector<std::string> cats;
641 TraceLog::GetInstance()->GetKnownCategories(&cats);
642 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c1") != cats.end());
643 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c2") != cats.end());
644 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c3") != cats.end());
645 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c4") != cats.end());
646
647 const std::vector<std::string> empty_categories;
648 std::vector<std::string> included_categories;
649 std::vector<std::string> excluded_categories;
650
651 // Test that category filtering works.
652
653 // Include nonexistent category -> no events
654 Clear();
655 included_categories.clear();
656 included_categories.push_back("not_found823564786");
657 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
658 TRACE_EVENT_INSTANT0("cat1", "name");
659 TRACE_EVENT_INSTANT0("cat2", "name");
660 TraceLog::GetInstance()->SetDisabled();
661 EXPECT_TRUE(trace_parsed_.empty());
662
663 // Include existent category -> only events of that category
664 Clear();
665 included_categories.clear();
666 included_categories.push_back("inc");
667 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
668 TRACE_EVENT_INSTANT0("inc", "name");
669 TRACE_EVENT_INSTANT0("inc2", "name");
670 TraceLog::GetInstance()->SetDisabled();
671 EXPECT_TRUE(FindMatchingValue("cat", "inc"));
672 EXPECT_FALSE(FindNonMatchingValue("cat", "inc"));
673
674 // Include existent wildcard -> all categories matching wildcard
675 Clear();
676 included_categories.clear();
677 included_categories.push_back("inc_wildcard_*");
678 included_categories.push_back("inc_wildchar_?_end");
679 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
680 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "included");
681 TRACE_EVENT_INSTANT0("inc_wildcard_", "included");
682 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "included");
683 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "not_inc");
684 TRACE_EVENT_INSTANT0("cat1", "not_inc");
685 TRACE_EVENT_INSTANT0("cat2", "not_inc");
686 TraceLog::GetInstance()->SetDisabled();
687 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_abc"));
688 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_"));
689 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_x_end"));
690 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
691
692 included_categories.clear();
693
694 // Exclude nonexistent category -> all events
695 Clear();
696 excluded_categories.clear();
697 excluded_categories.push_back("not_found823564786");
698 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
699 TRACE_EVENT_INSTANT0("cat1", "name");
700 TRACE_EVENT_INSTANT0("cat2", "name");
701 TraceLog::GetInstance()->SetDisabled();
702 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
703 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
704
705 // Exclude existent category -> only events of other categories
706 Clear();
707 excluded_categories.clear();
708 excluded_categories.push_back("inc");
709 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
710 TRACE_EVENT_INSTANT0("inc", "name");
711 TRACE_EVENT_INSTANT0("inc2", "name");
712 TraceLog::GetInstance()->SetDisabled();
713 EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
714 EXPECT_FALSE(FindMatchingValue("cat", "inc"));
715
716 // Exclude existent wildcard -> all categories not matching wildcard
717 Clear();
718 excluded_categories.clear();
719 excluded_categories.push_back("inc_wildcard_*");
720 excluded_categories.push_back("inc_wildchar_?_end");
721 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
722 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "not_inc");
723 TRACE_EVENT_INSTANT0("inc_wildcard_", "not_inc");
724 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "not_inc");
725 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "included");
726 TRACE_EVENT_INSTANT0("cat1", "included");
727 TRACE_EVENT_INSTANT0("cat2", "included");
728 TraceLog::GetInstance()->SetDisabled();
729 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_bla_end"));
730 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
731 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
732 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
733}
734
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900735// Simple Test for time threshold events.
736TEST_F(TraceEventTestFixture, DataCapturedThreshold) {
737 ManualTestSetUp();
738 TraceLog::GetInstance()->SetEnabled(true);
739
740 // Test that events at the same level are properly filtered by threshold.
741 {
742 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "threshold 100");
743 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "threshold 1000");
744 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "threshold 10000");
745 // 100+ seconds to avoid flakiness.
746 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "threshold long1");
747 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "threshold long2");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900748 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900749 }
750
751 // Test that a normal nested event remains after it's parent event is dropped.
752 {
753 TRACE_EVENT_IF_LONGER_THAN0(1000000, "time", "2threshold10000");
754 {
755 TRACE_EVENT0("time", "nonthreshold1");
756 }
757 }
758
759 // Test that parent thresholded events are dropped while some nested events
760 // remain.
761 {
762 TRACE_EVENT0("time", "nonthreshold3");
763 {
764 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "3thresholdlong2");
765 {
766 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "3thresholdlong1");
767 {
768 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "3threshold10000");
769 {
770 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "3threshold1000");
771 {
772 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "3threshold100");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900773 base::PlatformThread::Sleep(
774 base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900775 }
776 }
777 }
778 }
779 }
780 }
781
782 // Test that child thresholded events are dropped while some parent events
783 // remain.
784 {
785 TRACE_EVENT0("time", "nonthreshold4");
786 {
787 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "4threshold100");
788 {
789 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "4threshold1000");
790 {
791 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "4threshold10000");
792 {
793 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time",
794 "4thresholdlong1");
795 {
796 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time",
797 "4thresholdlong2");
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900798 base::PlatformThread::Sleep(
799 base::TimeDelta::FromMilliseconds(20));
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900800 }
801 }
802 }
803 }
804 }
805 }
806
807 TraceLog::GetInstance()->SetEnabled(false);
808
809#define EXPECT_FIND_BE_(str) \
810 EXPECT_TRUE(FindNamePhase(str, "B")); \
811 EXPECT_TRUE(FindNamePhase(str, "E"))
812#define EXPECT_NOT_FIND_BE_(str) \
813 EXPECT_FALSE(FindNamePhase(str, "B")); \
814 EXPECT_FALSE(FindNamePhase(str, "E"))
815
816 EXPECT_FIND_BE_("threshold 100");
817 EXPECT_FIND_BE_("threshold 1000");
818 EXPECT_FIND_BE_("threshold 10000");
819 EXPECT_NOT_FIND_BE_("threshold long1");
820 EXPECT_NOT_FIND_BE_("threshold long2");
821
822 EXPECT_NOT_FIND_BE_("2threshold10000");
823 EXPECT_FIND_BE_("nonthreshold1");
824
825 EXPECT_FIND_BE_("nonthreshold3");
826 EXPECT_FIND_BE_("3threshold100");
827 EXPECT_FIND_BE_("3threshold1000");
828 EXPECT_FIND_BE_("3threshold10000");
829 EXPECT_NOT_FIND_BE_("3thresholdlong1");
830 EXPECT_NOT_FIND_BE_("3thresholdlong2");
831
832 EXPECT_FIND_BE_("nonthreshold4");
833 EXPECT_FIND_BE_("4threshold100");
834 EXPECT_FIND_BE_("4threshold1000");
835 EXPECT_FIND_BE_("4threshold10000");
836 EXPECT_NOT_FIND_BE_("4thresholdlong1");
837 EXPECT_NOT_FIND_BE_("4thresholdlong2");
838}
839
jbates@chromium.org8bb0ee62011-12-03 02:17:38 +0900840// Test Start/Finish events
841TEST_F(TraceEventTestFixture, StartFinishEvents) {
842 ManualTestSetUp();
843 TraceLog::GetInstance()->SetEnabled(true);
844
845 unsigned long long id = 0xfeedbeeffeedbeefull;
846 TRACE_EVENT_START0( "cat", "name1", id);
847 TRACE_EVENT_FINISH0("cat", "name1", id);
848 TRACE_EVENT_BEGIN0( "cat", "name2");
849 TRACE_EVENT_START0( "cat", "name3", 0);
850
851 TraceLog::GetInstance()->SetEnabled(false);
852
853 EXPECT_TRUE(FindNamePhase("name1", "S"));
854 EXPECT_TRUE(FindNamePhase("name1", "F"));
855
856 std::string id_str;
857 StringAppendF(&id_str, "%llx", id);
858
859 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "S", "id", id_str.c_str()));
860 EXPECT_TRUE(FindNamePhaseKeyValue("name1", "F", "id", id_str.c_str()));
861 EXPECT_TRUE(FindNamePhaseKeyValue("name3", "S", "id", "0"));
862
863 // BEGIN events should not have id
864 EXPECT_FALSE(FindNamePhaseKeyValue("name2", "B", "id", "0"));
865}
866
867// Test Start/Finish events
868TEST_F(TraceEventTestFixture, StartFinishPointerMangling) {
869 ManualTestSetUp();
870
871 void* ptr = this;
872
873 TraceLog::GetInstance()->SetProcessID(100);
874 TraceLog::GetInstance()->SetEnabled(true);
875 TRACE_EVENT_START0( "cat", "name1", ptr);
876 TRACE_EVENT_START0( "cat", "name2", ptr);
877 TraceLog::GetInstance()->SetEnabled(false);
878
879 TraceLog::GetInstance()->SetProcessID(200);
880 TraceLog::GetInstance()->SetEnabled(true);
881 TRACE_EVENT_FINISH0( "cat", "name1", ptr);
882 TraceLog::GetInstance()->SetEnabled(false);
883
884 DictionaryValue* start = FindNamePhase("name1", "S");
885 DictionaryValue* start2 = FindNamePhase("name2", "S");
886 DictionaryValue* finish = FindNamePhase("name1", "F");
887 EXPECT_TRUE(start);
888 EXPECT_TRUE(start2);
889 EXPECT_TRUE(finish);
890
891 Value* value = NULL;
892 std::string start_id_str;
893 std::string start2_id_str;
894 std::string finish_id_str;
895 ASSERT_TRUE(start->Get("id", &value));
896 ASSERT_TRUE(value->GetAsString(&start_id_str));
897 ASSERT_TRUE(start2->Get("id", &value));
898 ASSERT_TRUE(value->GetAsString(&start2_id_str));
899 ASSERT_TRUE(finish->Get("id", &value));
900 ASSERT_TRUE(value->GetAsString(&finish_id_str));
901
902 EXPECT_STREQ(start_id_str.c_str(), start2_id_str.c_str());
903 EXPECT_STRNE(start_id_str.c_str(), finish_id_str.c_str());
904}
905
jbates@chromium.org1f18e462011-09-07 02:56:24 +0900906// Test that static strings are not copied.
907TEST_F(TraceEventTestFixture, StaticStringVsString) {
908 ManualTestSetUp();
909 TraceLog* tracer = TraceLog::GetInstance();
910 // Make sure old events are flushed:
911 tracer->SetEnabled(false);
912 EXPECT_EQ(0u, tracer->GetEventsSize());
913
914 {
915 tracer->SetEnabled(true);
916 // Test that string arguments are copied.
917 TRACE_EVENT2("cat", "name1",
918 "arg1", std::string("argval"), "arg2", std::string("argval"));
919 // Test that static TRACE_STR_COPY string arguments are copied.
920 TRACE_EVENT2("cat", "name2",
921 "arg1", TRACE_STR_COPY("argval"),
922 "arg2", TRACE_STR_COPY("argval"));
923 size_t num_events = tracer->GetEventsSize();
924 EXPECT_GT(num_events, 1u);
925 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
926 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
927 EXPECT_STREQ("name1", event1.name());
928 EXPECT_STREQ("name2", event2.name());
929 EXPECT_TRUE(event1.parameter_copy_storage() != NULL);
930 EXPECT_TRUE(event2.parameter_copy_storage() != NULL);
931 EXPECT_GT(event1.parameter_copy_storage()->size(), 0u);
932 EXPECT_GT(event2.parameter_copy_storage()->size(), 0u);
933 tracer->SetEnabled(false);
934 }
935
936 {
937 tracer->SetEnabled(true);
938 // Test that static literal string arguments are not copied.
939 TRACE_EVENT2("cat", "name1",
940 "arg1", "argval", "arg2", "argval");
941 // Test that static TRACE_STR_COPY NULL string arguments are not copied.
942 const char* str1 = NULL;
943 const char* str2 = NULL;
944 TRACE_EVENT2("cat", "name2",
945 "arg1", TRACE_STR_COPY(str1),
946 "arg2", TRACE_STR_COPY(str2));
947 size_t num_events = tracer->GetEventsSize();
948 EXPECT_GT(num_events, 1u);
949 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
950 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
951 EXPECT_STREQ("name1", event1.name());
952 EXPECT_STREQ("name2", event2.name());
953 EXPECT_TRUE(event1.parameter_copy_storage() == NULL);
954 EXPECT_TRUE(event2.parameter_copy_storage() == NULL);
955 tracer->SetEnabled(false);
956 }
957}
958
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900959// Test that data sent from other threads is gathered
960TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
961 ManualTestSetUp();
962 TraceLog::GetInstance()->SetEnabled(true);
963
964 Thread thread("1");
965 WaitableEvent task_complete_event(false, false);
966 thread.Start();
967
968 thread.message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900969 FROM_HERE, base::Bind(&TraceWithAllMacroVariants, &task_complete_event));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900970 task_complete_event.Wait();
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900971 thread.Stop();
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900972
973 TraceLog::GetInstance()->SetEnabled(false);
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900974 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900975}
976
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900977// Test that data sent from multiple threads is gathered
978TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
979 ManualTestSetUp();
980 TraceLog::GetInstance()->SetEnabled(true);
981
982 const int num_threads = 4;
983 const int num_events = 4000;
984 Thread* threads[num_threads];
985 WaitableEvent* task_complete_events[num_threads];
986 for (int i = 0; i < num_threads; i++) {
987 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
988 task_complete_events[i] = new WaitableEvent(false, false);
989 threads[i]->Start();
990 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900991 FROM_HERE, base::Bind(&TraceManyInstantEvents,
992 i, num_events, task_complete_events[i]));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900993 }
994
995 for (int i = 0; i < num_threads; i++) {
996 task_complete_events[i]->Wait();
997 }
998
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900999 for (int i = 0; i < num_threads; i++) {
1000 threads[i]->Stop();
1001 delete threads[i];
1002 delete task_complete_events[i];
1003 }
1004
jbates@chromium.orgb84db522011-10-04 02:51:25 +09001005 TraceLog::GetInstance()->SetEnabled(false);
1006
jbates@chromium.org6a092d72011-10-25 01:34:08 +09001007 ValidateInstantEventPresentOnEveryThread(trace_parsed_,
nduca@chromium.org6d048772011-08-10 00:16:25 +09001008 num_threads, num_events);
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001009}
1010
nduca@chromium.org6d048772011-08-10 00:16:25 +09001011// Test that thread and process names show up in the trace
1012TEST_F(TraceEventTestFixture, ThreadNames) {
1013 ManualTestSetUp();
1014
1015 // Create threads before we enable tracing to make sure
1016 // that tracelog still captures them.
1017 const int num_threads = 4;
1018 const int num_events = 10;
1019 Thread* threads[num_threads];
1020 PlatformThreadId thread_ids[num_threads];
1021 for (int i = 0; i < num_threads; i++)
1022 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
1023
1024 // Enable tracing.
1025 TraceLog::GetInstance()->SetEnabled(true);
1026
1027 // Now run some trace code on these threads.
1028 WaitableEvent* task_complete_events[num_threads];
1029 for (int i = 0; i < num_threads; i++) {
1030 task_complete_events[i] = new WaitableEvent(false, false);
1031 threads[i]->Start();
1032 thread_ids[i] = threads[i]->thread_id();
1033 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +09001034 FROM_HERE, base::Bind(&TraceManyInstantEvents,
1035 i, num_events, task_complete_events[i]));
nduca@chromium.org6d048772011-08-10 00:16:25 +09001036 }
1037 for (int i = 0; i < num_threads; i++) {
1038 task_complete_events[i]->Wait();
1039 }
1040
1041 // Shut things down.
nduca@chromium.org6d048772011-08-10 00:16:25 +09001042 for (int i = 0; i < num_threads; i++) {
1043 threads[i]->Stop();
1044 delete threads[i];
1045 delete task_complete_events[i];
1046 }
1047
jbates@chromium.orgb84db522011-10-04 02:51:25 +09001048 TraceLog::GetInstance()->SetEnabled(false);
1049
nduca@chromium.org6d048772011-08-10 00:16:25 +09001050 std::string tmp;
1051 int tmp_int;
1052 DictionaryValue* item;
1053
1054 // Make sure we get thread name metadata.
1055 // Note, the test suite may have created a ton of threads.
1056 // So, we'll have thread names for threads we didn't create.
1057 std::vector<DictionaryValue*> items =
1058 FindTraceEntries(trace_parsed_, "thread_name");
1059 for (int i = 0; i < static_cast<int>(items.size()); i++) {
1060 item = items[i];
joth@chromium.org088ae012011-11-11 01:26:23 +09001061 ASSERT_TRUE(item);
nduca@chromium.org6d048772011-08-10 00:16:25 +09001062 EXPECT_TRUE(item->GetInteger("tid", &tmp_int));
1063
1064 // See if this thread name is one of the threads we just created
1065 for (int j = 0; j < num_threads; j++) {
1066 if(static_cast<int>(thread_ids[j]) != tmp_int)
1067 continue;
1068
1069 std::string expected_name = StringPrintf("Thread %d", j).c_str();
1070 EXPECT_TRUE(item->GetString("ph", &tmp) && tmp == "M");
1071 EXPECT_TRUE(item->GetInteger("pid", &tmp_int) &&
1072 tmp_int == static_cast<int>(base::GetCurrentProcId()));
1073 EXPECT_TRUE(item->GetString("args.name", &tmp) &&
1074 tmp == expected_name);
1075 }
1076 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001077}
1078
joth@chromium.org088ae012011-11-11 01:26:23 +09001079TEST_F(TraceEventTestFixture, ThreadNameChanges) {
1080 ManualTestSetUp();
1081
1082 TraceLog::GetInstance()->SetEnabled(true);
1083
1084 PlatformThread::SetName("");
1085 TRACE_EVENT_INSTANT0("drink", "water");
1086
1087 PlatformThread::SetName("cafe");
1088 TRACE_EVENT_INSTANT0("drink", "coffee");
1089
1090 PlatformThread::SetName("shop");
1091 // No event here, so won't appear in combined name.
1092
1093 PlatformThread::SetName("pub");
1094 TRACE_EVENT_INSTANT0("drink", "beer");
1095 TRACE_EVENT_INSTANT0("drink", "wine");
1096
1097 PlatformThread::SetName(" bar");
1098 TRACE_EVENT_INSTANT0("drink", "whisky");
1099
1100 TraceLog::GetInstance()->SetEnabled(false);
1101
1102 std::vector<DictionaryValue*> items =
1103 FindTraceEntries(trace_parsed_, "thread_name");
1104 EXPECT_EQ(1u, items.size());
1105 ASSERT_GT(items.size(), 0u);
1106 DictionaryValue* item = items[0];
1107 ASSERT_TRUE(item);
1108 int tid;
1109 EXPECT_TRUE(item->GetInteger("tid", &tid));
1110 EXPECT_EQ(PlatformThread::CurrentId(), static_cast<PlatformThreadId>(tid));
1111
1112 std::string expected_name = "cafe,pub, bar";
1113 std::string tmp;
1114 EXPECT_TRUE(item->GetString("args.name", &tmp));
1115 EXPECT_EQ(expected_name, tmp);
1116}
nduca@chromium.org6d048772011-08-10 00:16:25 +09001117
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001118// Test trace calls made after tracing singleton shut down.
1119//
1120// The singleton is destroyed by our base::AtExitManager, but there can be
1121// code still executing as the C++ static objects are destroyed. This test
1122// forces the singleton to destroy early, and intentinally makes trace calls
1123// afterwards.
1124TEST_F(TraceEventTestFixture, AtExit) {
1125 // Repeat this test a few times. Besides just showing robustness, it also
1126 // allows us to test that events at shutdown do not appear with valid events
1127 // recorded after the system is started again.
1128 for (int i = 0; i < 4; i++) {
1129 // Scope to contain the then destroy the TraceLog singleton.
1130 {
1131 base::ShadowingAtExitManager exit_manager_will_destroy_singletons;
1132
1133 // Setup TraceLog singleton inside this test's exit manager scope
1134 // so that it will be destroyed when this scope closes.
1135 ManualTestSetUp();
1136
1137 TRACE_EVENT_INSTANT0("all", "not recorded; system not enabled");
1138
1139 TraceLog::GetInstance()->SetEnabled(true);
1140
1141 TRACE_EVENT_INSTANT0("all", "is recorded 1; system has been enabled");
1142 // Trace calls that will cache pointers to categories; they're valid here
1143 TraceCallsWithCachedCategoryPointersPointers(
1144 "is recorded 2; system has been enabled");
1145
1146 TraceLog::GetInstance()->SetEnabled(false);
1147 } // scope to destroy singleton
1148 ASSERT_FALSE(TraceLog::GetInstance());
1149
1150 // Now that singleton is destroyed, check what trace events were recorded
1151 DictionaryValue* item = NULL;
1152 ListValue& trace_parsed = trace_parsed_;
1153 EXPECT_FIND_("is recorded 1");
1154 EXPECT_FIND_("is recorded 2");
1155 EXPECT_NOT_FIND_("not recorded");
1156
1157 // Make additional trace event calls on the shutdown system. They should
1158 // all pass cleanly, but the data not be recorded. We'll verify that next
1159 // time around the loop (the only way to flush the trace buffers).
1160 TRACE_EVENT_BEGIN_ETW("not recorded; system shutdown", 0, NULL);
1161 TRACE_EVENT_END_ETW("not recorded; system shutdown", 0, NULL);
1162 TRACE_EVENT_INSTANT_ETW("not recorded; system shutdown", 0, NULL);
1163 TRACE_EVENT0("all", "not recorded; system shutdown");
1164 TRACE_EVENT_INSTANT0("all", "not recorded; system shutdown");
1165 TRACE_EVENT_BEGIN0("all", "not recorded; system shutdown");
1166 TRACE_EVENT_END0("all", "not recorded; system shutdown");
1167
1168 TRACE_EVENT0("new category 0!", "not recorded; system shutdown");
1169 TRACE_EVENT_INSTANT0("new category 1!", "not recorded; system shutdown");
1170 TRACE_EVENT_BEGIN0("new category 2!", "not recorded; system shutdown");
1171 TRACE_EVENT_END0("new category 3!", "not recorded; system shutdown");
1172
1173 // Cached categories should be safe to check, and still disable traces
1174 TraceCallsWithCachedCategoryPointersPointers(
1175 "not recorded; system shutdown");
1176 }
1177}
1178
joth@chromium.org113de992011-07-21 21:28:59 +09001179TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
1180 // Test that the TRACE_EVENT macros do not deep-copy their string. If they
1181 // do so it may indicate a performance regression, but more-over it would
1182 // make the DEEP_COPY overloads redundant.
1183 ManualTestSetUp();
1184
1185 std::string name_string("event name");
1186
1187 TraceLog::GetInstance()->SetEnabled(true);
1188 TRACE_EVENT_INSTANT0("category", name_string.c_str());
1189
1190 // Modify the string in place (a wholesale reassignment may leave the old
1191 // string intact on the heap).
1192 name_string[0] = '@';
1193
1194 TraceLog::GetInstance()->SetEnabled(false);
1195
1196 EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
1197 EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
1198}
1199
1200TEST_F(TraceEventTestFixture, DeepCopy) {
1201 ManualTestSetUp();
1202
1203 static const char kOriginalName1[] = "name1";
1204 static const char kOriginalName2[] = "name2";
1205 static const char kOriginalName3[] = "name3";
1206 std::string name1(kOriginalName1);
1207 std::string name2(kOriginalName2);
1208 std::string name3(kOriginalName3);
1209 std::string arg1("arg1");
1210 std::string arg2("arg2");
1211 std::string val1("val1");
1212 std::string val2("val2");
1213
1214 TraceLog::GetInstance()->SetEnabled(true);
1215 TRACE_EVENT_COPY_INSTANT0("category", name1.c_str());
1216 TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
1217 arg1.c_str(), 5);
1218 TRACE_EVENT_COPY_END2("category", name3.c_str(),
jbates@chromium.org1f18e462011-09-07 02:56:24 +09001219 arg1.c_str(), val1,
1220 arg2.c_str(), val2);
joth@chromium.org113de992011-07-21 21:28:59 +09001221
1222 // As per NormallyNoDeepCopy, modify the strings in place.
1223 name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
1224
1225 TraceLog::GetInstance()->SetEnabled(false);
1226
1227 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
1228 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
1229 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
1230
1231 DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
1232 DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
1233 DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
1234 ASSERT_TRUE(entry1);
1235 ASSERT_TRUE(entry2);
1236 ASSERT_TRUE(entry3);
1237
1238 int i;
1239 EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
1240 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
1241 EXPECT_EQ(5, i);
1242
1243 std::string s;
1244 EXPECT_TRUE(entry3->GetString("args.arg1", &s));
1245 EXPECT_EQ("val1", s);
1246 EXPECT_TRUE(entry3->GetString("args.arg2", &s));
1247 EXPECT_EQ("val2", s);
1248}
1249
jbates@chromium.org6a092d72011-10-25 01:34:08 +09001250// Test that TraceResultBuffer outputs the correct result whether it is added
1251// in chunks or added all at once.
1252TEST_F(TraceEventTestFixture, TraceResultBuffer) {
1253 ManualTestSetUp();
1254
1255 Clear();
1256
1257 trace_buffer_.Start();
1258 trace_buffer_.AddFragment("bla1");
1259 trace_buffer_.AddFragment("bla2");
1260 trace_buffer_.AddFragment("bla3,bla4");
1261 trace_buffer_.Finish();
1262 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1263
1264 Clear();
1265
1266 trace_buffer_.Start();
1267 trace_buffer_.AddFragment("bla1,bla2,bla3,bla4");
1268 trace_buffer_.Finish();
1269 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1270}
1271
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001272} // namespace debug
1273} // namespace base