Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: base/debug/trace_event_unittest.cc

Issue 6862002: Merge gpu_trace_event back into base/debug/trace_event (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge to r83717 Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // 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/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/stringprintf.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread.h"
12 #include "base/values.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base {
17 namespace debug {
18
19 namespace {
Sigurður Ásgeirsson 2011/05/02 19:28:41 is there commonly an anonymous namespace nested in
scheib 2011/05/04 02:14:15 I think the same reasoning applies for anonymous N
20
21 class TraceEventTestFixture: public testing::Test {
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: spaces both side of : http://google-stylegui
scheib 2011/05/04 02:14:15 Done.
22 public:
23 TraceEventTestFixture() {};
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: no semicolon after the body.
scheib 2011/05/04 02:14:15 Done.
24
25 void ManualTestSetUp();
26 void OnTraceDataCollected(const std::string& data);
27
28 ListValue trace_parsed_;
29 std::string trace_string_;
30
31 private:
32 // We want our singleton torn down after each test.
33 ShadowingAtExitManager at_exit_manager_;
34 };
35
36 void TraceEventTestFixture::ManualTestSetUp() {
37 TraceLog::Resurrect();
38 TraceLog* tracelog = TraceLog::GetInstance();
39 ASSERT_TRUE(tracelog);
40 ASSERT_FALSE(tracelog->IsEnabled());
41 tracelog->SetOutputCallback(
42 NewCallback(this, &TraceEventTestFixture::OnTraceDataCollected));
Sigurður Ásgeirsson 2011/05/02 19:28:41 nit: 4 space indent on continuation.
scheib 2011/05/04 02:14:15 Done.
43 }
44
45 void TraceEventTestFixture::OnTraceDataCollected(const std::string& data) {
46 if (0 && "Enable for visualizing what data was collected and parsed") {
Sigurður Ásgeirsson 2011/05/02 19:28:41 either remove, or e.g. control through the command
scheib 2011/05/04 02:14:15 Done.
47 fprintf(stderr, "\n\nRawJSON:\n%s\n", data.c_str());
48 }
49 trace_string_ += data;
50
51 scoped_ptr<Value> root;
52 root.reset(base::JSONReader::Read(data, false));
53
54 ListValue* root_list = NULL;
55 EXPECT_TRUE(root.get());
Sigurður Ásgeirsson 2011/05/02 19:28:41 ASSERT_TRUE will return from a void function on fa
scheib 2011/05/04 02:14:15 Done.
56 if (!root.get())
57 return;
58 EXPECT_TRUE(root->GetAsList(&root_list));
59 if (!root_list)
60 return;
61
62 // Move items into our aggregate collection
63 while (root_list->GetSize()) {
64 Value* item = NULL;
65 root_list->Remove(0, &item);
66 trace_parsed_.Append(item);
67 }
68
69 if (0 && "Enable for visualizing what data was collected and parsed") {
70 std::string parsed;
71 base::JSONWriter::Write(&trace_parsed_, true, &parsed);
72 fprintf(stderr, "\nParsedJSON:\n%s\n\n", parsed.c_str());
73 }
74 }
75
76 bool IsStringInDict(const char* string_to_match, DictionaryValue* dict) {
77 if (0 && "Enable for visualizing what data is being tested") {
78 std::string parsed;
79 base::JSONWriter::Write(dict, true, &parsed);
80 fprintf(stderr, "\n\nParsedJSON:\n%s\n\n", parsed.c_str());
81 }
82
83 for (DictionaryValue::key_iterator ikey = dict->begin_keys();
84 ikey != dict->end_keys(); ++ikey) {
85 Value* child = NULL;
86 if (!dict->GetWithoutPathExpansion(*ikey, &child))
87 continue;
88
89 if ((*ikey).find(string_to_match) != std::string::npos)
90 return true;
91
92 std::string value_str;
93 child->GetAsString(&value_str);
94 if (value_str.find(string_to_match) != std::string::npos)
95 return true;
96 }
97
98 // Recurse to test arguments
99 DictionaryValue* args_dict = NULL;
100 dict->GetDictionary("args", &args_dict);
101 if (args_dict)
102 return IsStringInDict(string_to_match, args_dict);
103
104 return false;
105 }
106
107 DictionaryValue* FindTraceEntry(const ListValue& trace_parsed,
Sigurður Ásgeirsson 2011/05/02 19:28:41 http://google-styleguide.googlecode.com/svn/trunk/
scheib 2011/05/04 02:14:15 Done.
108 const char *string_to_match,
109 DictionaryValue* match_after_this_item = NULL) {
110 // Scan all items
111 size_t trace_parsed_count = trace_parsed.GetSize();
112 for (size_t i = 0; i < trace_parsed_count; i++) {
113 Value* value = NULL;
114 trace_parsed.Get(i, &value);
115 if (match_after_this_item) {
116 if (value == match_after_this_item)
117 match_after_this_item = NULL;
118 continue;
119 }
120 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
121 continue;
122 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
123
124 if (IsStringInDict(string_to_match, dict))
125 return dict;
126 }
127 return NULL;
128 }
129
130 void DataCaptured_CallTraces(WaitableEvent* task_complete_event) {
Sigurður Ásgeirsson 2011/05/02 19:28:41 why the _ in the function name?
scheib 2011/05/04 02:14:15 Done.
131 TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW call", 0xaa, "extrastring1");
132 TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW call", 0xbb, "extrastring2");
133 TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW call", 0xcc, "extrastring3");
134
135 TRACE_EVENT0("all", "TRACE_EVENT0 call");
136 TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
137 TRACE_EVENT2("all", "TRACE_EVENT2 call",
138 "name1", "value1",
139 "name2", "value2");
140
141 TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call");
142 TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call", "name1", "value1");
143 TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
144 "name1", "value1",
145 "name2", "value2");
146
147 TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
148 TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
149 TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
150 "name1", "value1",
151 "name2", "value2");
152
153 TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
154 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
155 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
156 "name1", "value1",
157 "name2", "value2");
158
159
160 if (task_complete_event)
161 task_complete_event->Signal();
162 }
163
164 void DataCaptured_ValidateTraces(const ListValue& trace_parsed,
165 const std::string& trace_string) {
166 DictionaryValue* item = NULL;
167
168 #define EXPECT_FIND_(string) \
169 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string)));
170 #define EXPECT_NOT_FIND_(string) \
171 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string)));
172 #define EXPECT_SUB_FIND_(string) \
173 if (item) EXPECT_TRUE((IsStringInDict(string, item)));
174
175 EXPECT_FIND_("ETW Trace Event");
176 EXPECT_FIND_("all");
177 EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW call");
178 EXPECT_SUB_FIND_("0xaa");
179 EXPECT_SUB_FIND_("extrastring1");
180 EXPECT_FIND_("TRACE_EVENT_END_ETW call");
181 EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW call");
182 EXPECT_FIND_("TRACE_EVENT0 call");
183 {
184 std::string ph_begin;
185 std::string ph_end;
186 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
187 EXPECT_TRUE((item && item->GetString("ph", &ph_begin)));
188 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call",
189 item)));
190 EXPECT_TRUE((item && item->GetString("ph", &ph_end)));
191 EXPECT_EQ("B", ph_begin);
192 EXPECT_EQ("E", ph_end);
193 }
194 EXPECT_FIND_("TRACE_EVENT1 call");
195 EXPECT_FIND_("TRACE_EVENT2 call");
196 EXPECT_SUB_FIND_("name1");
197 EXPECT_SUB_FIND_("value1");
198 EXPECT_SUB_FIND_("name2");
199 EXPECT_SUB_FIND_("value2");
200 EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
201 EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
202 EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
203 EXPECT_SUB_FIND_("name1");
204 EXPECT_SUB_FIND_("value1");
205 EXPECT_SUB_FIND_("name2");
206 EXPECT_SUB_FIND_("value2");
207 EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
208 EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
209 EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
210 EXPECT_SUB_FIND_("name1");
211 EXPECT_SUB_FIND_("value1");
212 EXPECT_SUB_FIND_("name2");
213 EXPECT_SUB_FIND_("value2");
214 EXPECT_FIND_("TRACE_EVENT_END0 call");
215 EXPECT_FIND_("TRACE_EVENT_END1 call");
216 EXPECT_FIND_("TRACE_EVENT_END2 call");
217 EXPECT_SUB_FIND_("name1");
218 EXPECT_SUB_FIND_("value1");
219 EXPECT_SUB_FIND_("name2");
220 EXPECT_SUB_FIND_("value2");
221 }
222
223 } // namespace
224
225 // Simple Test for emitting data and validating it was received.
226 TEST_F(TraceEventTestFixture, DataCaptured) {
227 ManualTestSetUp();
228 TraceLog::GetInstance()->SetEnabled(true);
229
230 DataCaptured_CallTraces(NULL);
231
232 TraceLog::GetInstance()->SetEnabled(false);
233
234 DataCaptured_ValidateTraces(trace_parsed_, trace_string_);
235 }
236
237 // Test that data sent from other threads is gathered
238 TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
239 ManualTestSetUp();
240 TraceLog::GetInstance()->SetEnabled(true);
241
242 Thread thread("1");
243 WaitableEvent task_complete_event(false, false);
244 thread.Start();
245
246 thread.message_loop()->PostTask(
247 FROM_HERE, NewRunnableFunction(&DataCaptured_CallTraces,
248 &task_complete_event));
249 task_complete_event.Wait();
250
251 TraceLog::GetInstance()->SetEnabled(false);
252 thread.Stop();
253 DataCaptured_ValidateTraces(trace_parsed_, trace_string_);
254 }
255
256 namespace {
257
258 void DataCaptured_CallManyTraces(int thread_id, int num_events,
259 WaitableEvent* task_complete_event) {
260 for (int i = 0; i < num_events; i++) {
261 TRACE_EVENT_INSTANT2("all", "multi thread event",
262 "thread", thread_id,
263 "event", i);
264 }
265
266 if (task_complete_event)
267 task_complete_event->Signal();
268 }
269
270 void DataCaptured_ValidateManyTraces(const ListValue& trace_parsed,
271 const std::string& trace_string,
272 int num_threads, int num_events) {
273 std::map<int, std::map<int, bool> > results;
274
275 size_t trace_parsed_count = trace_parsed.GetSize();
276 for (size_t i = 0; i < trace_parsed_count; i++) {
277 Value* value = NULL;
278 trace_parsed.Get(i, &value);
279 if (!value || value->GetType() != Value::TYPE_DICTIONARY)
280 continue;
281 DictionaryValue* dict = static_cast<DictionaryValue*>(value);
282 std::string name;
283 dict->GetString("name", &name);
284 if (name != "multi thread event")
285 continue;
286
287 int thread = 0;
288 int event = 0;
289 EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
290 EXPECT_TRUE(dict->GetInteger("args.event", &event));
291 results[thread][event] = true;
292 }
293
294 EXPECT_FALSE(results[-1][-1]);
295 for (int thread = 0; thread < num_threads; thread++) {
296 for (int event = 0; event < num_events; event++) {
297 EXPECT_TRUE(results[thread][event]);
298 }
299 }
300 }
301
302 } // namespace
303
304 // Test that data sent from multiple threads is gathered
305 TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
306 ManualTestSetUp();
307 TraceLog::GetInstance()->SetEnabled(true);
308
309 const int num_threads = 10;
310 const int num_events = 1000;
311 Thread* threads[num_threads];
312 WaitableEvent* task_complete_events[num_threads];
313 for (int i = 0; i < num_threads; i++) {
314 threads[i] = new Thread(StringPrintf("Thread %d", i).c_str());
315 task_complete_events[i] = new WaitableEvent(false, false);
316 threads[i]->Start();
317 threads[i]->message_loop()->PostTask(
318 FROM_HERE, NewRunnableFunction(&DataCaptured_CallManyTraces,
319 i, num_events, task_complete_events[i]));
320 }
321
322 for (int i = 0; i < num_threads; i++) {
323 task_complete_events[i]->Wait();
324 }
325
326 TraceLog::GetInstance()->SetEnabled(false);
327
328 for (int i = 0; i < num_threads; i++) {
329 threads[i]->Stop();
330 delete threads[i];
331 delete task_complete_events[i];
332 }
333
334 DataCaptured_ValidateManyTraces(trace_parsed_, trace_string_,
335 num_threads, num_events);
336 }
337
338 void TraceCallsWillCacheStaticCategory() {
339 TRACE_EVENT0("category name1", "name1");
340 TRACE_EVENT_INSTANT0("category name2", "name2");
341 TRACE_EVENT_BEGIN0("category name3", "name3");
342 TRACE_EVENT_END0("category name4", "name4");
343 }
344
345 // Test trace calls made after tracing singleton shut down
346 TEST_F(TraceEventTestFixture, AtExit) {
347 for (int i = 0; i < 4; i++) {
348 { // scope to destroy singleton
Sigurður Ásgeirsson 2011/05/02 19:28:41 nice test!. It could do with a little bit of runni
scheib 2011/05/04 02:14:15 Done.
349 base::ShadowingAtExitManager exit_manager_will_destroy_singletons;
350
351 ManualTestSetUp(); // Inside this test's exit manager scope
352
353 TRACE_EVENT_INSTANT0("all", "not recorded; system not enabled");
354
355 TraceLog::GetInstance()->SetEnabled(true);
356 TRACE_EVENT_INSTANT0("all", "is recorded; system has been enabled");
357 TraceCallsWillCacheStaticCategory();
358 TraceLog::GetInstance()->SetEnabled(false);
359 } // scope to destroy singleton
360 ASSERT_FALSE(TraceLog::GetInstance());
361
362 DictionaryValue* item = NULL;
363 ListValue& trace_parsed = trace_parsed_;
364 EXPECT_FIND_("is recorded");
365 EXPECT_NOT_FIND_("not recorded");
366
367 TRACE_EVENT_BEGIN_ETW("not recorded; system shutdown", 0, NULL);
368 TRACE_EVENT_END_ETW("not recorded; system shutdown", 0, NULL);
369 TRACE_EVENT_INSTANT_ETW("not recorded; system shutdown", 0, NULL);
370 TRACE_EVENT0("all", "not recorded; system shutdown");
371 TRACE_EVENT_INSTANT0("all", "not recorded; system shutdown");
372 TRACE_EVENT_BEGIN0("all", "not recorded; system shutdown");
373 TRACE_EVENT_END0("all", "not recorded; system shutdown");
374
375 TRACE_EVENT0("new category 0!", "not recorded; system shutdown");
376 TRACE_EVENT_INSTANT0("new category 1!", "not recorded; system shutdown");
377 TRACE_EVENT_BEGIN0("new category 2!", "not recorded; system shutdown");
378 TRACE_EVENT_END0("new category 3!", "not recorded; system shutdown");
379
380 // static categories should disable traces
381 TraceCallsWillCacheStaticCategory();
382 }
383 }
384
385 } // namespace debug
386 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698