blob: 6f0a744ea871f44d47d3496ecfe06decc70e4bb4 [file] [log] [blame]
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/debug/trace_event.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/json/json_reader.h"
10#include "base/json/json_writer.h"
jbates@chromium.org1f18e462011-09-07 02:56:24 +090011#include "base/memory/ref_counted_memory.h"
scheib@chromium.org603f46e2011-05-10 11:23:58 +090012#include "base/memory/scoped_ptr.h"
joth@chromium.org088ae012011-11-11 01:26:23 +090013#include "base/memory/singleton.h"
nduca@chromium.org6d048772011-08-10 00:16:25 +090014#include "base/process_util.h"
scheib@chromium.org603f46e2011-05-10 11:23:58 +090015#include "base/stringprintf.h"
16#include "base/synchronization/waitable_event.h"
joth@chromium.org088ae012011-11-11 01:26:23 +090017#include "base/threading/platform_thread.h"
scheib@chromium.org603f46e2011-05-10 11:23:58 +090018#include "base/threading/thread.h"
19#include "base/values.h"
20#include "testing/gmock/include/gmock/gmock.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23namespace base {
24namespace debug {
25
26namespace {
27
jbates@chromium.org11d4c362011-09-13 07:03:41 +090028enum CompareOp {
29 IS_EQUAL,
30 IS_NOT_EQUAL,
31};
32
jbates@chromium.orgb3cab862011-05-14 08:30:35 +090033struct JsonKeyValue {
34 const char* key;
35 const char* value;
jbates@chromium.org11d4c362011-09-13 07:03:41 +090036 CompareOp op;
jbates@chromium.orgb3cab862011-05-14 08:30:35 +090037};
38
scheib@chromium.org603f46e2011-05-10 11:23:58 +090039class TraceEventTestFixture : public testing::Test {
40 public:
joth@chromium.org113de992011-07-21 21:28:59 +090041 // This fixture does not use SetUp() because the fixture must be manually set
42 // up multiple times when testing AtExit. Use ManualTestSetUp for this.
scheib@chromium.org603f46e2011-05-10 11:23:58 +090043 void ManualTestSetUp();
ajwong@chromium.orgec1750a2011-06-27 01:22:50 +090044 void OnTraceDataCollected(
jbates@chromium.org6a092d72011-10-25 01:34:08 +090045 scoped_refptr<TraceLog::RefCountedString> events_str);
jbates@chromium.orgb3cab862011-05-14 08:30:35 +090046 bool FindMatchingTraceEntry(const JsonKeyValue* key_values);
47 bool FindNamePhase(const char* name, const char* phase);
jbates@chromium.org11d4c362011-09-13 07:03:41 +090048 bool FindMatchingValue(const char* key,
49 const char* value);
50 bool FindNonMatchingValue(const char* key,
51 const char* value);
52 void Clear() {
jbates@chromium.org11d4c362011-09-13 07:03:41 +090053 trace_parsed_.Clear();
jbates@chromium.org6a092d72011-10-25 01:34:08 +090054 json_output_.json_output.clear();
jbates@chromium.org11d4c362011-09-13 07:03:41 +090055 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +090056
joth@chromium.org088ae012011-11-11 01:26:23 +090057 virtual void SetUp() {
58 old_thread_name_ = PlatformThread::GetName();
59 }
60 virtual void TearDown() {
61 PlatformThread::SetName(old_thread_name_ ? old_thread_name_ : "");
62 }
63
64 const char* old_thread_name_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090065 ListValue trace_parsed_;
jbates@chromium.org6a092d72011-10-25 01:34:08 +090066 base::debug::TraceResultBuffer trace_buffer_;
67 base::debug::TraceResultBuffer::SimpleOutput json_output_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090068
69 private:
70 // We want our singleton torn down after each test.
71 ShadowingAtExitManager at_exit_manager_;
jbates@chromium.orgb84db522011-10-04 02:51:25 +090072 Lock lock_;
scheib@chromium.org603f46e2011-05-10 11:23:58 +090073};
74
75void TraceEventTestFixture::ManualTestSetUp() {
jbates@chromium.orgb84db522011-10-04 02:51:25 +090076 TraceLog::DeleteForTesting();
scheib@chromium.org603f46e2011-05-10 11:23:58 +090077 TraceLog::Resurrect();
78 TraceLog* tracelog = TraceLog::GetInstance();
79 ASSERT_TRUE(tracelog);
80 ASSERT_FALSE(tracelog->IsEnabled());
81 tracelog->SetOutputCallback(
jbates@chromium.orgb84db522011-10-04 02:51:25 +090082 base::Bind(&TraceEventTestFixture::OnTraceDataCollected,
83 base::Unretained(this)));
jbates@chromium.org6a092d72011-10-25 01:34:08 +090084 trace_buffer_.SetOutputCallback(json_output_.GetCallback());
scheib@chromium.org603f46e2011-05-10 11:23:58 +090085}
86
87void TraceEventTestFixture::OnTraceDataCollected(
jbates@chromium.org6a092d72011-10-25 01:34:08 +090088 scoped_refptr<TraceLog::RefCountedString> events_str) {
jbates@chromium.orgb84db522011-10-04 02:51:25 +090089 AutoLock lock(lock_);
jbates@chromium.org6a092d72011-10-25 01:34:08 +090090 json_output_.json_output.clear();
91 trace_buffer_.Start();
92 trace_buffer_.AddFragment(events_str->data);
93 trace_buffer_.Finish();
scheib@chromium.org603f46e2011-05-10 11:23:58 +090094
95 scoped_ptr<Value> root;
jbates@chromium.org6a092d72011-10-25 01:34:08 +090096 root.reset(base::JSONReader::Read(json_output_.json_output, false));
scheib@chromium.org603f46e2011-05-10 11:23:58 +090097
98 ListValue* root_list = NULL;
99 ASSERT_TRUE(root.get());
100 ASSERT_TRUE(root->GetAsList(&root_list));
101
102 // Move items into our aggregate collection
103 while (root_list->GetSize()) {
104 Value* item = NULL;
105 root_list->Remove(0, &item);
106 trace_parsed_.Append(item);
107 }
108}
109
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900110static bool CompareJsonValues(const std::string& lhs,
111 const std::string& rhs,
112 CompareOp op) {
113 switch (op) {
114 case IS_EQUAL:
115 return lhs == rhs;
116 case IS_NOT_EQUAL:
117 return lhs != rhs;
118 default:
119 CHECK(0);
120 }
121 return false;
122}
123
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900124static bool IsKeyValueInDict(const JsonKeyValue* key_value,
125 DictionaryValue* dict) {
126 Value* value = NULL;
127 std::string value_str;
128 if (dict->Get(key_value->key, &value) &&
129 value->GetAsString(&value_str) &&
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900130 CompareJsonValues(value_str, key_value->value, key_value->op))
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900131 return true;
132
133 // Recurse to test arguments
134 DictionaryValue* args_dict = NULL;
135 dict->GetDictionary("args", &args_dict);
136 if (args_dict)
137 return IsKeyValueInDict(key_value, args_dict);
138
139 return false;
140}
141
142static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
143 DictionaryValue* dict) {
144 // Scan all key_values, they must all be present and equal.
145 while (key_values && key_values->key) {
146 if (!IsKeyValueInDict(key_values, dict))
147 return false;
148 ++key_values;
149 }
150 return true;
151}
152
153bool TraceEventTestFixture::FindMatchingTraceEntry(
154 const JsonKeyValue* key_values) {
155 // Scan all items
156 size_t trace_parsed_count = trace_parsed_.GetSize();
157 for (size_t i = 0; i < trace_parsed_count; i++) {
158 Value* value = NULL;
159 trace_parsed_.Get(i, &value);
160 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
161 continue;
162 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
163
164 if (IsAllKeyValueInDict(key_values, dict))
165 return true;
166 }
167 return false;
168}
169
170bool TraceEventTestFixture::FindNamePhase(const char* name, const char* phase) {
171 JsonKeyValue key_values[] = {
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900172 {"name", name, IS_EQUAL},
173 {"ph", phase, IS_EQUAL},
174 {0, 0, IS_EQUAL}
175 };
176 return FindMatchingTraceEntry(key_values);
177}
178
179bool TraceEventTestFixture::FindMatchingValue(const char* key,
180 const char* value) {
181 JsonKeyValue key_values[] = {
182 {key, value, IS_EQUAL},
183 {0, 0, IS_EQUAL}
184 };
185 return FindMatchingTraceEntry(key_values);
186}
187
188bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
189 const char* value) {
190 JsonKeyValue key_values[] = {
191 {key, value, IS_NOT_EQUAL},
192 {0, 0, IS_EQUAL}
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900193 };
194 return FindMatchingTraceEntry(key_values);
195}
196
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900197bool IsStringInDict(const char* string_to_match, DictionaryValue* dict) {
198 for (DictionaryValue::key_iterator ikey = dict->begin_keys();
199 ikey != dict->end_keys(); ++ikey) {
200 Value* child = NULL;
201 if (!dict->GetWithoutPathExpansion(*ikey, &child))
202 continue;
203
204 if ((*ikey).find(string_to_match) != std::string::npos)
205 return true;
206
207 std::string value_str;
208 child->GetAsString(&value_str);
209 if (value_str.find(string_to_match) != std::string::npos)
210 return true;
211 }
212
213 // Recurse to test arguments
214 DictionaryValue* args_dict = NULL;
215 dict->GetDictionary("args", &args_dict);
216 if (args_dict)
217 return IsStringInDict(string_to_match, args_dict);
218
219 return false;
220}
221
222DictionaryValue* FindTraceEntry(const ListValue& trace_parsed,
nduca@chromium.org6d048772011-08-10 00:16:25 +0900223 const char* string_to_match,
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900224 DictionaryValue* match_after_this_item = NULL) {
225 // Scan all items
226 size_t trace_parsed_count = trace_parsed.GetSize();
227 for (size_t i = 0; i < trace_parsed_count; i++) {
228 Value* value = NULL;
229 trace_parsed.Get(i, &value);
230 if (match_after_this_item) {
231 if (value == match_after_this_item)
232 match_after_this_item = NULL;
233 continue;
234 }
235 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
236 continue;
237 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
238
239 if (IsStringInDict(string_to_match, dict))
240 return dict;
241 }
242 return NULL;
243}
244
nduca@chromium.org6d048772011-08-10 00:16:25 +0900245std::vector<DictionaryValue*> FindTraceEntries(
246 const ListValue& trace_parsed,
247 const char* string_to_match) {
248 std::vector<DictionaryValue*> hits;
249 size_t trace_parsed_count = trace_parsed.GetSize();
250 for (size_t i = 0; i < trace_parsed_count; i++) {
251 Value* value = NULL;
252 trace_parsed.Get(i, &value);
253 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
254 continue;
255 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
256
257 if (IsStringInDict(string_to_match, dict))
258 hits.push_back(dict);
259 }
260 return hits;
261}
262
263void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900264 {
265 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW call", 1122, "extrastring1");
266 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW call", 3344, "extrastring2");
267 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW call",
268 5566, "extrastring3");
269
270 TRACE_EVENT0("all", "TRACE_EVENT0 call");
271 TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
272 TRACE_EVENT2("all", "TRACE_EVENT2 call",
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900273 "name1", "\"value1\"",
274 "name2", "value\\2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900275
276 TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call");
277 TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call", "name1", "value1");
278 TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
279 "name1", "value1",
280 "name2", "value2");
281
282 TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
283 TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
284 TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
285 "name1", "value1",
286 "name2", "value2");
287
288 TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
289 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
290 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
291 "name1", "value1",
292 "name2", "value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900293
294 TRACE_COUNTER1("all", "TRACE_COUNTER1 call", 31415);
295 TRACE_COUNTER2("all", "TRACE_COUNTER2 call",
296 "a", 30000,
297 "b", 1415);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900298 } // Scope close causes TRACE_EVENT0 etc to send their END events.
299
300 if (task_complete_event)
301 task_complete_event->Signal();
302}
303
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900304void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) {
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900305 DictionaryValue* item = NULL;
306
307#define EXPECT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900308 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900309#define EXPECT_NOT_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900310 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900311#define EXPECT_SUB_FIND_(string) \
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900312 if (item) EXPECT_TRUE((IsStringInDict(string, item)));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900313
314 EXPECT_FIND_("ETW Trace Event");
315 EXPECT_FIND_("all");
316 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW call");
317 {
318 int int_val = 0;
319 EXPECT_TRUE(item && item->GetInteger("args.id", &int_val));
320 EXPECT_EQ(1122, int_val);
321 }
322 EXPECT_SUB_FIND_("extrastring1");
323 EXPECT_FIND_("TRACE_EVENT_END_ETW call");
324 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW call");
325 EXPECT_FIND_("TRACE_EVENT0 call");
326 {
327 std::string ph_begin;
328 std::string ph_end;
329 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
330 EXPECT_TRUE((item && item->GetString("ph", &ph_begin)));
331 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call",
332 item)));
333 EXPECT_TRUE((item && item->GetString("ph", &ph_end)));
334 EXPECT_EQ("B", ph_begin);
335 EXPECT_EQ("E", ph_end);
336 }
337 EXPECT_FIND_("TRACE_EVENT1 call");
338 EXPECT_FIND_("TRACE_EVENT2 call");
339 EXPECT_SUB_FIND_("name1");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900340 EXPECT_SUB_FIND_("\"value1\"");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900341 EXPECT_SUB_FIND_("name2");
jbates@chromium.org788d5a12011-09-07 09:43:11 +0900342 EXPECT_SUB_FIND_("value\\2");
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900343 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
344 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
345 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
346 EXPECT_SUB_FIND_("name1");
347 EXPECT_SUB_FIND_("value1");
348 EXPECT_SUB_FIND_("name2");
349 EXPECT_SUB_FIND_("value2");
350 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
351 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
352 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
353 EXPECT_SUB_FIND_("name1");
354 EXPECT_SUB_FIND_("value1");
355 EXPECT_SUB_FIND_("name2");
356 EXPECT_SUB_FIND_("value2");
357 EXPECT_FIND_("TRACE_EVENT_END0 call");
358 EXPECT_FIND_("TRACE_EVENT_END1 call");
359 EXPECT_FIND_("TRACE_EVENT_END2 call");
360 EXPECT_SUB_FIND_("name1");
361 EXPECT_SUB_FIND_("value1");
362 EXPECT_SUB_FIND_("name2");
363 EXPECT_SUB_FIND_("value2");
nduca@chromium.org62210b02011-11-18 18:36:36 +0900364
365 EXPECT_FIND_("TRACE_COUNTER1 call");
366 {
367 std::string ph;
368 EXPECT_TRUE((item && item->GetString("ph", &ph)));
369 EXPECT_EQ("C", ph);
370
371 int value;
372 EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
373 EXPECT_EQ(31415, value);
374 }
375
376 EXPECT_FIND_("TRACE_COUNTER2 call");
377 {
378 std::string ph;
379 EXPECT_TRUE((item && item->GetString("ph", &ph)));
380 EXPECT_EQ("C", ph);
381
382 int value;
383 EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
384 EXPECT_EQ(30000, value);
385
386 EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
387 EXPECT_EQ(1415, value);
388 }
389
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900390}
391
nduca@chromium.org6d048772011-08-10 00:16:25 +0900392void TraceManyInstantEvents(int thread_id, int num_events,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900393 WaitableEvent* task_complete_event) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900394 for (int i = 0; i < num_events; i++) {
395 TRACE_EVENT_INSTANT2("all", "multi thread event",
396 "thread", thread_id,
397 "event", i);
398 }
399
400 if (task_complete_event)
401 task_complete_event->Signal();
402}
403
404void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed,
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900405 int num_threads,
406 int num_events) {
nduca@chromium.org6d048772011-08-10 00:16:25 +0900407 std::map<int, std::map<int, bool> > results;
408
409 size_t trace_parsed_count = trace_parsed.GetSize();
410 for (size_t i = 0; i < trace_parsed_count; i++) {
411 Value* value = NULL;
412 trace_parsed.Get(i, &value);
413 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
414 continue;
415 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
416 std::string name;
417 dict->GetString("name", &name);
418 if (name != "multi thread event")
419 continue;
420
421 int thread = 0;
422 int event = 0;
423 EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
424 EXPECT_TRUE(dict->GetInteger("args.event", &event));
425 results[thread][event] = true;
426 }
427
428 EXPECT_FALSE(results[-1][-1]);
429 for (int thread = 0; thread < num_threads; thread++) {
430 for (int event = 0; event < num_events; event++) {
431 EXPECT_TRUE(results[thread][event]);
432 }
433 }
434}
435
436void TraceCallsWithCachedCategoryPointersPointers(const char* name_str) {
437 TRACE_EVENT0("category name1", name_str);
438 TRACE_EVENT_INSTANT0("category name2", name_str);
439 TRACE_EVENT_BEGIN0("category name3", name_str);
440 TRACE_EVENT_END0("category name4", name_str);
441}
442
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900443} // namespace
444
445// Simple Test for emitting data and validating it was received.
446TEST_F(TraceEventTestFixture, DataCaptured) {
447 ManualTestSetUp();
448 TraceLog::GetInstance()->SetEnabled(true);
449
nduca@chromium.org6d048772011-08-10 00:16:25 +0900450 TraceWithAllMacroVariants(NULL);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900451
452 TraceLog::GetInstance()->SetEnabled(false);
453
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900454 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900455}
456
jbates@chromium.org11d4c362011-09-13 07:03:41 +0900457// Test that categories work.
458TEST_F(TraceEventTestFixture, Categories) {
459 ManualTestSetUp();
460
461 // Test that categories that are used can be retrieved whether trace was
462 // enabled or disabled when the trace event was encountered.
463 TRACE_EVENT_INSTANT0("c1", "name");
464 TRACE_EVENT_INSTANT0("c2", "name");
465 TraceLog::GetInstance()->SetEnabled(true);
466 TRACE_EVENT_INSTANT0("c3", "name");
467 TRACE_EVENT_INSTANT0("c4", "name");
468 TraceLog::GetInstance()->SetEnabled(false);
469 std::vector<std::string> cats;
470 TraceLog::GetInstance()->GetKnownCategories(&cats);
471 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c1") != cats.end());
472 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c2") != cats.end());
473 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c3") != cats.end());
474 EXPECT_TRUE(std::find(cats.begin(), cats.end(), "c4") != cats.end());
475
476 const std::vector<std::string> empty_categories;
477 std::vector<std::string> included_categories;
478 std::vector<std::string> excluded_categories;
479
480 // Test that category filtering works.
481
482 // Include nonexistent category -> no events
483 Clear();
484 included_categories.clear();
485 included_categories.push_back("not_found823564786");
486 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
487 TRACE_EVENT_INSTANT0("cat1", "name");
488 TRACE_EVENT_INSTANT0("cat2", "name");
489 TraceLog::GetInstance()->SetDisabled();
490 EXPECT_TRUE(trace_parsed_.empty());
491
492 // Include existent category -> only events of that category
493 Clear();
494 included_categories.clear();
495 included_categories.push_back("inc");
496 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
497 TRACE_EVENT_INSTANT0("inc", "name");
498 TRACE_EVENT_INSTANT0("inc2", "name");
499 TraceLog::GetInstance()->SetDisabled();
500 EXPECT_TRUE(FindMatchingValue("cat", "inc"));
501 EXPECT_FALSE(FindNonMatchingValue("cat", "inc"));
502
503 // Include existent wildcard -> all categories matching wildcard
504 Clear();
505 included_categories.clear();
506 included_categories.push_back("inc_wildcard_*");
507 included_categories.push_back("inc_wildchar_?_end");
508 TraceLog::GetInstance()->SetEnabled(included_categories, empty_categories);
509 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "included");
510 TRACE_EVENT_INSTANT0("inc_wildcard_", "included");
511 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "included");
512 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "not_inc");
513 TRACE_EVENT_INSTANT0("cat1", "not_inc");
514 TRACE_EVENT_INSTANT0("cat2", "not_inc");
515 TraceLog::GetInstance()->SetDisabled();
516 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_abc"));
517 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_"));
518 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_x_end"));
519 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
520
521 included_categories.clear();
522
523 // Exclude nonexistent category -> all events
524 Clear();
525 excluded_categories.clear();
526 excluded_categories.push_back("not_found823564786");
527 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
528 TRACE_EVENT_INSTANT0("cat1", "name");
529 TRACE_EVENT_INSTANT0("cat2", "name");
530 TraceLog::GetInstance()->SetDisabled();
531 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
532 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
533
534 // Exclude existent category -> only events of other categories
535 Clear();
536 excluded_categories.clear();
537 excluded_categories.push_back("inc");
538 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
539 TRACE_EVENT_INSTANT0("inc", "name");
540 TRACE_EVENT_INSTANT0("inc2", "name");
541 TraceLog::GetInstance()->SetDisabled();
542 EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
543 EXPECT_FALSE(FindMatchingValue("cat", "inc"));
544
545 // Exclude existent wildcard -> all categories not matching wildcard
546 Clear();
547 excluded_categories.clear();
548 excluded_categories.push_back("inc_wildcard_*");
549 excluded_categories.push_back("inc_wildchar_?_end");
550 TraceLog::GetInstance()->SetEnabled(empty_categories, excluded_categories);
551 TRACE_EVENT_INSTANT0("inc_wildcard_abc", "not_inc");
552 TRACE_EVENT_INSTANT0("inc_wildcard_", "not_inc");
553 TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "not_inc");
554 TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "included");
555 TRACE_EVENT_INSTANT0("cat1", "included");
556 TRACE_EVENT_INSTANT0("cat2", "included");
557 TraceLog::GetInstance()->SetDisabled();
558 EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_bla_end"));
559 EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
560 EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
561 EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
562}
563
jbates@chromium.orgb3cab862011-05-14 08:30:35 +0900564// Simple Test for time threshold events.
565TEST_F(TraceEventTestFixture, DataCapturedThreshold) {
566 ManualTestSetUp();
567 TraceLog::GetInstance()->SetEnabled(true);
568
569 // Test that events at the same level are properly filtered by threshold.
570 {
571 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "threshold 100");
572 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "threshold 1000");
573 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "threshold 10000");
574 // 100+ seconds to avoid flakiness.
575 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "threshold long1");
576 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "threshold long2");
577 base::PlatformThread::Sleep(20); // 20000 us
578 }
579
580 // Test that a normal nested event remains after it's parent event is dropped.
581 {
582 TRACE_EVENT_IF_LONGER_THAN0(1000000, "time", "2threshold10000");
583 {
584 TRACE_EVENT0("time", "nonthreshold1");
585 }
586 }
587
588 // Test that parent thresholded events are dropped while some nested events
589 // remain.
590 {
591 TRACE_EVENT0("time", "nonthreshold3");
592 {
593 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time", "3thresholdlong2");
594 {
595 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time", "3thresholdlong1");
596 {
597 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "3threshold10000");
598 {
599 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "3threshold1000");
600 {
601 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "3threshold100");
602 base::PlatformThread::Sleep(20);
603 }
604 }
605 }
606 }
607 }
608 }
609
610 // Test that child thresholded events are dropped while some parent events
611 // remain.
612 {
613 TRACE_EVENT0("time", "nonthreshold4");
614 {
615 TRACE_EVENT_IF_LONGER_THAN0(100, "time", "4threshold100");
616 {
617 TRACE_EVENT_IF_LONGER_THAN0(1000, "time", "4threshold1000");
618 {
619 TRACE_EVENT_IF_LONGER_THAN0(10000, "time", "4threshold10000");
620 {
621 TRACE_EVENT_IF_LONGER_THAN0(100000000, "time",
622 "4thresholdlong1");
623 {
624 TRACE_EVENT_IF_LONGER_THAN0(200000000, "time",
625 "4thresholdlong2");
626 base::PlatformThread::Sleep(20);
627 }
628 }
629 }
630 }
631 }
632 }
633
634 TraceLog::GetInstance()->SetEnabled(false);
635
636#define EXPECT_FIND_BE_(str) \
637 EXPECT_TRUE(FindNamePhase(str, "B")); \
638 EXPECT_TRUE(FindNamePhase(str, "E"))
639#define EXPECT_NOT_FIND_BE_(str) \
640 EXPECT_FALSE(FindNamePhase(str, "B")); \
641 EXPECT_FALSE(FindNamePhase(str, "E"))
642
643 EXPECT_FIND_BE_("threshold 100");
644 EXPECT_FIND_BE_("threshold 1000");
645 EXPECT_FIND_BE_("threshold 10000");
646 EXPECT_NOT_FIND_BE_("threshold long1");
647 EXPECT_NOT_FIND_BE_("threshold long2");
648
649 EXPECT_NOT_FIND_BE_("2threshold10000");
650 EXPECT_FIND_BE_("nonthreshold1");
651
652 EXPECT_FIND_BE_("nonthreshold3");
653 EXPECT_FIND_BE_("3threshold100");
654 EXPECT_FIND_BE_("3threshold1000");
655 EXPECT_FIND_BE_("3threshold10000");
656 EXPECT_NOT_FIND_BE_("3thresholdlong1");
657 EXPECT_NOT_FIND_BE_("3thresholdlong2");
658
659 EXPECT_FIND_BE_("nonthreshold4");
660 EXPECT_FIND_BE_("4threshold100");
661 EXPECT_FIND_BE_("4threshold1000");
662 EXPECT_FIND_BE_("4threshold10000");
663 EXPECT_NOT_FIND_BE_("4thresholdlong1");
664 EXPECT_NOT_FIND_BE_("4thresholdlong2");
665}
666
jbates@chromium.org1f18e462011-09-07 02:56:24 +0900667// Test that static strings are not copied.
668TEST_F(TraceEventTestFixture, StaticStringVsString) {
669 ManualTestSetUp();
670 TraceLog* tracer = TraceLog::GetInstance();
671 // Make sure old events are flushed:
672 tracer->SetEnabled(false);
673 EXPECT_EQ(0u, tracer->GetEventsSize());
674
675 {
676 tracer->SetEnabled(true);
677 // Test that string arguments are copied.
678 TRACE_EVENT2("cat", "name1",
679 "arg1", std::string("argval"), "arg2", std::string("argval"));
680 // Test that static TRACE_STR_COPY string arguments are copied.
681 TRACE_EVENT2("cat", "name2",
682 "arg1", TRACE_STR_COPY("argval"),
683 "arg2", TRACE_STR_COPY("argval"));
684 size_t num_events = tracer->GetEventsSize();
685 EXPECT_GT(num_events, 1u);
686 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
687 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
688 EXPECT_STREQ("name1", event1.name());
689 EXPECT_STREQ("name2", event2.name());
690 EXPECT_TRUE(event1.parameter_copy_storage() != NULL);
691 EXPECT_TRUE(event2.parameter_copy_storage() != NULL);
692 EXPECT_GT(event1.parameter_copy_storage()->size(), 0u);
693 EXPECT_GT(event2.parameter_copy_storage()->size(), 0u);
694 tracer->SetEnabled(false);
695 }
696
697 {
698 tracer->SetEnabled(true);
699 // Test that static literal string arguments are not copied.
700 TRACE_EVENT2("cat", "name1",
701 "arg1", "argval", "arg2", "argval");
702 // Test that static TRACE_STR_COPY NULL string arguments are not copied.
703 const char* str1 = NULL;
704 const char* str2 = NULL;
705 TRACE_EVENT2("cat", "name2",
706 "arg1", TRACE_STR_COPY(str1),
707 "arg2", TRACE_STR_COPY(str2));
708 size_t num_events = tracer->GetEventsSize();
709 EXPECT_GT(num_events, 1u);
710 const TraceEvent& event1 = tracer->GetEventAt(num_events - 2);
711 const TraceEvent& event2 = tracer->GetEventAt(num_events - 1);
712 EXPECT_STREQ("name1", event1.name());
713 EXPECT_STREQ("name2", event2.name());
714 EXPECT_TRUE(event1.parameter_copy_storage() == NULL);
715 EXPECT_TRUE(event2.parameter_copy_storage() == NULL);
716 tracer->SetEnabled(false);
717 }
718}
719
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900720// Test that data sent from other threads is gathered
721TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
722 ManualTestSetUp();
723 TraceLog::GetInstance()->SetEnabled(true);
724
725 Thread thread("1");
726 WaitableEvent task_complete_event(false, false);
727 thread.Start();
728
729 thread.message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900730 FROM_HERE, base::Bind(&TraceWithAllMacroVariants, &task_complete_event));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900731 task_complete_event.Wait();
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900732 thread.Stop();
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900733
734 TraceLog::GetInstance()->SetEnabled(false);
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900735 ValidateAllTraceMacrosCreatedData(trace_parsed_);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900736}
737
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900738// Test that data sent from multiple threads is gathered
739TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
740 ManualTestSetUp();
741 TraceLog::GetInstance()->SetEnabled(true);
742
743 const int num_threads = 4;
744 const int num_events = 4000;
745 Thread* threads[num_threads];
746 WaitableEvent* task_complete_events[num_threads];
747 for (int i = 0; i < num_threads; i++) {
748 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
749 task_complete_events[i] = new WaitableEvent(false, false);
750 threads[i]->Start();
751 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900752 FROM_HERE, base::Bind(&TraceManyInstantEvents,
753 i, num_events, task_complete_events[i]));
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900754 }
755
756 for (int i = 0; i < num_threads; i++) {
757 task_complete_events[i]->Wait();
758 }
759
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900760 for (int i = 0; i < num_threads; i++) {
761 threads[i]->Stop();
762 delete threads[i];
763 delete task_complete_events[i];
764 }
765
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900766 TraceLog::GetInstance()->SetEnabled(false);
767
jbates@chromium.org6a092d72011-10-25 01:34:08 +0900768 ValidateInstantEventPresentOnEveryThread(trace_parsed_,
nduca@chromium.org6d048772011-08-10 00:16:25 +0900769 num_threads, num_events);
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900770}
771
nduca@chromium.org6d048772011-08-10 00:16:25 +0900772// Test that thread and process names show up in the trace
773TEST_F(TraceEventTestFixture, ThreadNames) {
774 ManualTestSetUp();
775
776 // Create threads before we enable tracing to make sure
777 // that tracelog still captures them.
778 const int num_threads = 4;
779 const int num_events = 10;
780 Thread* threads[num_threads];
781 PlatformThreadId thread_ids[num_threads];
782 for (int i = 0; i < num_threads; i++)
783 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
784
785 // Enable tracing.
786 TraceLog::GetInstance()->SetEnabled(true);
787
788 // Now run some trace code on these threads.
789 WaitableEvent* task_complete_events[num_threads];
790 for (int i = 0; i < num_threads; i++) {
791 task_complete_events[i] = new WaitableEvent(false, false);
792 threads[i]->Start();
793 thread_ids[i] = threads[i]->thread_id();
794 threads[i]->message_loop()->PostTask(
jbates@chromium.org0b837e42011-10-06 01:58:20 +0900795 FROM_HERE, base::Bind(&TraceManyInstantEvents,
796 i, num_events, task_complete_events[i]));
nduca@chromium.org6d048772011-08-10 00:16:25 +0900797 }
798 for (int i = 0; i < num_threads; i++) {
799 task_complete_events[i]->Wait();
800 }
801
802 // Shut things down.
nduca@chromium.org6d048772011-08-10 00:16:25 +0900803 for (int i = 0; i < num_threads; i++) {
804 threads[i]->Stop();
805 delete threads[i];
806 delete task_complete_events[i];
807 }
808
jbates@chromium.orgb84db522011-10-04 02:51:25 +0900809 TraceLog::GetInstance()->SetEnabled(false);
810
nduca@chromium.org6d048772011-08-10 00:16:25 +0900811 std::string tmp;
812 int tmp_int;
813 DictionaryValue* item;
814
815 // Make sure we get thread name metadata.
816 // Note, the test suite may have created a ton of threads.
817 // So, we'll have thread names for threads we didn't create.
818 std::vector<DictionaryValue*> items =
819 FindTraceEntries(trace_parsed_, "thread_name");
820 for (int i = 0; i < static_cast<int>(items.size()); i++) {
821 item = items[i];
joth@chromium.org088ae012011-11-11 01:26:23 +0900822 ASSERT_TRUE(item);
nduca@chromium.org6d048772011-08-10 00:16:25 +0900823 EXPECT_TRUE(item->GetInteger("tid", &tmp_int));
824
825 // See if this thread name is one of the threads we just created
826 for (int j = 0; j < num_threads; j++) {
827 if(static_cast<int>(thread_ids[j]) != tmp_int)
828 continue;
829
830 std::string expected_name = StringPrintf("Thread %d", j).c_str();
831 EXPECT_TRUE(item->GetString("ph", &tmp) && tmp == "M");
832 EXPECT_TRUE(item->GetInteger("pid", &tmp_int) &&
833 tmp_int == static_cast<int>(base::GetCurrentProcId()));
834 EXPECT_TRUE(item->GetString("args.name", &tmp) &&
835 tmp == expected_name);
836 }
837 }
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900838}
839
joth@chromium.org088ae012011-11-11 01:26:23 +0900840TEST_F(TraceEventTestFixture, ThreadNameChanges) {
841 ManualTestSetUp();
842
843 TraceLog::GetInstance()->SetEnabled(true);
844
845 PlatformThread::SetName("");
846 TRACE_EVENT_INSTANT0("drink", "water");
847
848 PlatformThread::SetName("cafe");
849 TRACE_EVENT_INSTANT0("drink", "coffee");
850
851 PlatformThread::SetName("shop");
852 // No event here, so won't appear in combined name.
853
854 PlatformThread::SetName("pub");
855 TRACE_EVENT_INSTANT0("drink", "beer");
856 TRACE_EVENT_INSTANT0("drink", "wine");
857
858 PlatformThread::SetName(" bar");
859 TRACE_EVENT_INSTANT0("drink", "whisky");
860
861 TraceLog::GetInstance()->SetEnabled(false);
862
863 std::vector<DictionaryValue*> items =
864 FindTraceEntries(trace_parsed_, "thread_name");
865 EXPECT_EQ(1u, items.size());
866 ASSERT_GT(items.size(), 0u);
867 DictionaryValue* item = items[0];
868 ASSERT_TRUE(item);
869 int tid;
870 EXPECT_TRUE(item->GetInteger("tid", &tid));
871 EXPECT_EQ(PlatformThread::CurrentId(), static_cast<PlatformThreadId>(tid));
872
873 std::string expected_name = "cafe,pub, bar";
874 std::string tmp;
875 EXPECT_TRUE(item->GetString("args.name", &tmp));
876 EXPECT_EQ(expected_name, tmp);
877}
nduca@chromium.org6d048772011-08-10 00:16:25 +0900878
scheib@chromium.org603f46e2011-05-10 11:23:58 +0900879// Test trace calls made after tracing singleton shut down.
880//
881// The singleton is destroyed by our base::AtExitManager, but there can be
882// code still executing as the C++ static objects are destroyed. This test
883// forces the singleton to destroy early, and intentinally makes trace calls
884// afterwards.
885TEST_F(TraceEventTestFixture, AtExit) {
886 // Repeat this test a few times. Besides just showing robustness, it also
887 // allows us to test that events at shutdown do not appear with valid events
888 // recorded after the system is started again.
889 for (int i = 0; i < 4; i++) {
890 // Scope to contain the then destroy the TraceLog singleton.
891 {
892 base::ShadowingAtExitManager exit_manager_will_destroy_singletons;
893
894 // Setup TraceLog singleton inside this test's exit manager scope
895 // so that it will be destroyed when this scope closes.
896 ManualTestSetUp();
897
898 TRACE_EVENT_INSTANT0("all", "not recorded; system not enabled");
899
900 TraceLog::GetInstance()->SetEnabled(true);
901
902 TRACE_EVENT_INSTANT0("all", "is recorded 1; system has been enabled");
903 // Trace calls that will cache pointers to categories; they're valid here
904 TraceCallsWithCachedCategoryPointersPointers(
905 "is recorded 2; system has been enabled");
906
907 TraceLog::GetInstance()->SetEnabled(false);
908 } // scope to destroy singleton
909 ASSERT_FALSE(TraceLog::GetInstance());
910
911 // Now that singleton is destroyed, check what trace events were recorded
912 DictionaryValue* item = NULL;
913 ListValue& trace_parsed = trace_parsed_;
914 EXPECT_FIND_("is recorded 1");
915 EXPECT_FIND_("is recorded 2");
916 EXPECT_NOT_FIND_("not recorded");
917
918 // Make additional trace event calls on the shutdown system. They should
919 // all pass cleanly, but the data not be recorded. We'll verify that next
920 // time around the loop (the only way to flush the trace buffers).
921 TRACE_EVENT_BEGIN_ETW("not recorded; system shutdown", 0, NULL);
922 TRACE_EVENT_END_ETW("not recorded; system shutdown", 0, NULL);
923 TRACE_EVENT_INSTANT_ETW("not recorded; system shutdown", 0, NULL);
924 TRACE_EVENT0("all", "not recorded; system shutdown");
925 TRACE_EVENT_INSTANT0("all", "not recorded; system shutdown");
926 TRACE_EVENT_BEGIN0("all", "not recorded; system shutdown");
927 TRACE_EVENT_END0("all", "not recorded; system shutdown");
928
929 TRACE_EVENT0("new category 0!", "not recorded; system shutdown");
930 TRACE_EVENT_INSTANT0("new category 1!", "not recorded; system shutdown");
931 TRACE_EVENT_BEGIN0("new category 2!", "not recorded; system shutdown");
932 TRACE_EVENT_END0("new category 3!", "not recorded; system shutdown");
933
934 // Cached categories should be safe to check, and still disable traces
935 TraceCallsWithCachedCategoryPointersPointers(
936 "not recorded; system shutdown");
937 }
938}
939
joth@chromium.org113de992011-07-21 21:28:59 +0900940TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
941 // Test that the TRACE_EVENT macros do not deep-copy their string. If they
942 // do so it may indicate a performance regression, but more-over it would
943 // make the DEEP_COPY overloads redundant.
944 ManualTestSetUp();
945
946 std::string name_string("event name");
947
948 TraceLog::GetInstance()->SetEnabled(true);
949 TRACE_EVENT_INSTANT0("category", name_string.c_str());
950
951 // Modify the string in place (a wholesale reassignment may leave the old
952 // string intact on the heap).
953 name_string[0] = '@';
954
955 TraceLog::GetInstance()->SetEnabled(false);
956
957 EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
958 EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
959}
960
961TEST_F(TraceEventTestFixture, DeepCopy) {
962 ManualTestSetUp();
963
964 static const char kOriginalName1[] = "name1";
965 static const char kOriginalName2[] = "name2";
966 static const char kOriginalName3[] = "name3";
967 std::string name1(kOriginalName1);
968 std::string name2(kOriginalName2);
969 std::string name3(kOriginalName3);
970 std::string arg1("arg1");
971 std::string arg2("arg2");
972 std::string val1("val1");
973 std::string val2("val2");
974
975 TraceLog::GetInstance()->SetEnabled(true);
976 TRACE_EVENT_COPY_INSTANT0("category", name1.c_str());
977 TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
978 arg1.c_str(), 5);
979 TRACE_EVENT_COPY_END2("category", name3.c_str(),
jbates@chromium.org1f18e462011-09-07 02:56:24 +0900980 arg1.c_str(), val1,
981 arg2.c_str(), val2);
joth@chromium.org113de992011-07-21 21:28:59 +0900982
983 // As per NormallyNoDeepCopy, modify the strings in place.
984 name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
985
986 TraceLog::GetInstance()->SetEnabled(false);
987
988 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
989 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
990 EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
991
992 DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
993 DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
994 DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
995 ASSERT_TRUE(entry1);
996 ASSERT_TRUE(entry2);
997 ASSERT_TRUE(entry3);
998
999 int i;
1000 EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
1001 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
1002 EXPECT_EQ(5, i);
1003
1004 std::string s;
1005 EXPECT_TRUE(entry3->GetString("args.arg1", &s));
1006 EXPECT_EQ("val1", s);
1007 EXPECT_TRUE(entry3->GetString("args.arg2", &s));
1008 EXPECT_EQ("val2", s);
1009}
1010
jbates@chromium.org6a092d72011-10-25 01:34:08 +09001011// Test that TraceResultBuffer outputs the correct result whether it is added
1012// in chunks or added all at once.
1013TEST_F(TraceEventTestFixture, TraceResultBuffer) {
1014 ManualTestSetUp();
1015
1016 Clear();
1017
1018 trace_buffer_.Start();
1019 trace_buffer_.AddFragment("bla1");
1020 trace_buffer_.AddFragment("bla2");
1021 trace_buffer_.AddFragment("bla3,bla4");
1022 trace_buffer_.Finish();
1023 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1024
1025 Clear();
1026
1027 trace_buffer_.Start();
1028 trace_buffer_.AddFragment("bla1,bla2,bla3,bla4");
1029 trace_buffer_.Finish();
1030 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
1031}
1032
scheib@chromium.org603f46e2011-05-10 11:23:58 +09001033} // namespace debug
1034} // namespace base