1 // Copyright 2015 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.
6 #include "base/trace_event/trace_event.h"
7 #include "content/public/browser/background_tracing_manager.h"
8 #include "content/public/browser/background_tracing_preemptive_config.h"
9 #include "content/public/browser/background_tracing_reactive_config.h"
10 #include "content/public/test/content_browser_test.h"
11 #include "content/public/test/content_browser_test_utils.h"
12 #include "content/public/test/test_utils.h"
13 #include "third_party/zlib/zlib.h"
17 class BackgroundTracingManagerBrowserTest
: public ContentBrowserTest
{
19 BackgroundTracingManagerBrowserTest() {}
22 DISALLOW_COPY_AND_ASSIGN(BackgroundTracingManagerBrowserTest
);
25 class BackgroundTracingManagerUploadConfigWrapper
{
27 BackgroundTracingManagerUploadConfigWrapper(const base::Closure
& callback
)
28 : callback_(callback
), receive_count_(0) {
30 base::Bind(&BackgroundTracingManagerUploadConfigWrapper::Upload
,
31 base::Unretained(this));
34 void Upload(const scoped_refptr
<base::RefCountedString
>& file_contents
,
35 base::Callback
<void()> done_callback
) {
37 EXPECT_TRUE(file_contents
);
39 size_t compressed_length
= file_contents
->data().length();
40 const size_t kOutputBufferLength
= 10 * 1024 * 1024;
41 std::vector
<char> output_str(kOutputBufferLength
);
43 z_stream stream
= {0};
44 stream
.avail_in
= compressed_length
;
45 stream
.avail_out
= kOutputBufferLength
;
46 stream
.next_in
= (Bytef
*)&file_contents
->data()[0];
47 stream
.next_out
= (Bytef
*)vector_as_array(&output_str
);
49 // 16 + MAX_WBITS means only decoding gzip encoded streams, and using
50 // the biggest window size, according to zlib.h
51 int result
= inflateInit2(&stream
, 16 + MAX_WBITS
);
52 EXPECT_EQ(Z_OK
, result
);
53 result
= inflate(&stream
, Z_FINISH
);
54 int bytes_written
= kOutputBufferLength
- stream
.avail_out
;
57 EXPECT_EQ(Z_STREAM_END
, result
);
59 last_file_contents_
.assign(vector_as_array(&output_str
), bytes_written
);
60 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
61 base::Bind(done_callback
));
62 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
63 base::Bind(callback_
));
66 bool TraceHasMatchingString(const char* str
) {
67 return last_file_contents_
.find(str
) != std::string::npos
;
70 int get_receive_count() const { return receive_count_
; }
72 const BackgroundTracingManager::ReceiveCallback
& get_receive_callback()
74 return receive_callback_
;
78 BackgroundTracingManager::ReceiveCallback receive_callback_
;
79 base::Closure callback_
;
81 std::string last_file_contents_
;
84 void StartedFinalizingCallback(base::Closure callback
,
87 EXPECT_EQ(expected
, value
);
88 if (!callback
.is_null())
92 scoped_ptr
<BackgroundTracingPreemptiveConfig
> CreatePreemptiveConfig() {
93 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config(
94 new BackgroundTracingPreemptiveConfig());
96 BackgroundTracingPreemptiveConfig::MonitoringRule rule
;
98 BackgroundTracingPreemptiveConfig::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED
;
99 rule
.named_trigger_info
.trigger_name
= "preemptive_test";
101 config
->configs
.push_back(rule
);
103 return config
.Pass();
106 scoped_ptr
<BackgroundTracingReactiveConfig
> CreateReactiveConfig() {
107 scoped_ptr
<BackgroundTracingReactiveConfig
> config(
108 new BackgroundTracingReactiveConfig());
110 BackgroundTracingReactiveConfig::TracingRule rule
;
112 BackgroundTracingReactiveConfig::TRACE_FOR_10S_OR_TRIGGER_OR_FULL
;
113 rule
.trigger_name
= "reactive_test";
114 rule
.category_preset
=
115 BackgroundTracingConfig::CategoryPreset::BENCHMARK_DEEP
;
117 config
->configs
.push_back(rule
);
119 return config
.Pass();
122 void SetupBackgroundTracingManager() {
123 content::BackgroundTracingManager::GetInstance()
124 ->InvalidateTriggerHandlesForTesting();
127 void DisableScenarioWhenIdle() {
128 BackgroundTracingManager::GetInstance()->SetActiveScenario(
129 NULL
, BackgroundTracingManager::ReceiveCallback(),
130 BackgroundTracingManager::NO_DATA_FILTERING
);
133 // This tests that the endpoint receives the final trace data.
134 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
135 ReceiveTraceFinalContentsOnTrigger
) {
137 SetupBackgroundTracingManager();
139 base::RunLoop run_loop
;
140 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
141 run_loop
.QuitClosure());
143 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
144 CreatePreemptiveConfig();
146 BackgroundTracingManager::TriggerHandle handle
=
147 BackgroundTracingManager::
148 GetInstance()->RegisterTriggerType("preemptive_test");
150 BackgroundTracingManager::GetInstance()->SetActiveScenario(
151 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
152 BackgroundTracingManager::NO_DATA_FILTERING
);
154 BackgroundTracingManager::GetInstance()->WhenIdle(
155 base::Bind(&DisableScenarioWhenIdle
));
157 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
158 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
162 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
166 // This tests triggering more than once still only gathers once.
167 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
168 CallTriggersMoreThanOnceOnlyGatherOnce
) {
170 SetupBackgroundTracingManager();
172 base::RunLoop run_loop
;
173 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
174 run_loop
.QuitClosure());
176 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
177 CreatePreemptiveConfig();
179 content::BackgroundTracingManager::TriggerHandle handle
=
180 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
183 BackgroundTracingManager::GetInstance()->SetActiveScenario(
184 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
185 BackgroundTracingManager::NO_DATA_FILTERING
);
187 BackgroundTracingManager::GetInstance()->WhenIdle(
188 base::Bind(&DisableScenarioWhenIdle
));
190 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
191 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
192 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
193 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), false));
197 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
203 bool IsTraceEventArgsWhitelisted(const char* category_group_name
,
204 const char* event_name
) {
205 if (MatchPattern(category_group_name
, "benchmark") &&
206 MatchPattern(event_name
, "whitelisted")) {
215 // This tests that non-whitelisted args get stripped if required.
216 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
217 NoWhitelistedArgsStripped
) {
218 SetupBackgroundTracingManager();
220 base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
221 base::Bind(&IsTraceEventArgsWhitelisted
));
223 base::RunLoop wait_for_upload
;
224 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
225 wait_for_upload
.QuitClosure());
227 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
228 CreatePreemptiveConfig();
230 content::BackgroundTracingManager::TriggerHandle handle
=
231 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
234 base::RunLoop wait_for_activated
;
235 BackgroundTracingManager::GetInstance()->SetTracingEnabledCallbackForTesting(
236 wait_for_activated
.QuitClosure());
237 EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
238 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
239 BackgroundTracingManager::ANONYMIZE_DATA
));
241 wait_for_activated
.Run();
243 TRACE_EVENT1("benchmark", "whitelisted", "find_this", 1);
244 TRACE_EVENT1("benchmark", "not_whitelisted", "this_not_found", 1);
246 BackgroundTracingManager::GetInstance()->WhenIdle(
247 base::Bind(&DisableScenarioWhenIdle
));
249 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
250 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
252 wait_for_upload
.Run();
254 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
255 EXPECT_TRUE(upload_config_wrapper
.TraceHasMatchingString("{"));
256 EXPECT_TRUE(upload_config_wrapper
.TraceHasMatchingString("find_this"));
257 EXPECT_TRUE(!upload_config_wrapper
.TraceHasMatchingString("this_not_found"));
260 // This tests subprocesses (like a navigating renderer) which gets told to
261 // provide a argument-filtered trace and has no predicate in place to do the
262 // filtering (in this case, only the browser process gets it set), will crash
263 // rather than return potential PII.
264 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
265 CrashWhenSubprocessWithoutArgumentFilter
) {
266 SetupBackgroundTracingManager();
268 base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
269 base::Bind(&IsTraceEventArgsWhitelisted
));
271 base::RunLoop wait_for_upload
;
272 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
273 wait_for_upload
.QuitClosure());
275 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
276 CreatePreemptiveConfig();
278 content::BackgroundTracingManager::TriggerHandle handle
=
279 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
282 base::RunLoop wait_for_activated
;
283 BackgroundTracingManager::GetInstance()->SetTracingEnabledCallbackForTesting(
284 wait_for_activated
.QuitClosure());
285 EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
286 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
287 BackgroundTracingManager::ANONYMIZE_DATA
));
289 wait_for_activated
.Run();
291 NavigateToURL(shell(), GetTestUrl("", "about:blank"));
293 BackgroundTracingManager::GetInstance()->WhenIdle(
294 base::Bind(&DisableScenarioWhenIdle
));
296 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
297 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
299 wait_for_upload
.Run();
301 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
302 // We should *not* receive anything at all from the renderer,
303 // the process should've crashed rather than letting that happen.
304 EXPECT_TRUE(!upload_config_wrapper
.TraceHasMatchingString("CrRendererMain"));
307 // This tests multiple triggers still only gathers once.
308 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
309 CallMultipleTriggersOnlyGatherOnce
) {
311 SetupBackgroundTracingManager();
313 base::RunLoop run_loop
;
314 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
315 run_loop
.QuitClosure());
317 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
318 CreatePreemptiveConfig();
320 BackgroundTracingPreemptiveConfig::MonitoringRule rule
;
322 BackgroundTracingPreemptiveConfig::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED
;
323 rule
.named_trigger_info
.trigger_name
= "test1";
324 config
->configs
.push_back(rule
);
326 rule
.named_trigger_info
.trigger_name
= "test2";
327 config
->configs
.push_back(rule
);
329 BackgroundTracingManager::TriggerHandle handle1
=
330 BackgroundTracingManager::GetInstance()->RegisterTriggerType("test1");
331 BackgroundTracingManager::TriggerHandle handle2
=
332 BackgroundTracingManager::GetInstance()->RegisterTriggerType("test2");
334 BackgroundTracingManager::GetInstance()->SetActiveScenario(
335 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
336 BackgroundTracingManager::NO_DATA_FILTERING
);
338 BackgroundTracingManager::GetInstance()->WhenIdle(
339 base::Bind(&DisableScenarioWhenIdle
));
341 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
342 handle1
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
343 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
345 base::Bind(&StartedFinalizingCallback
, base::Closure(), false));
349 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
353 // This tests that you can't trigger without a scenario set.
354 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
355 CannotTriggerWithoutScenarioSet
) {
357 SetupBackgroundTracingManager();
359 base::RunLoop run_loop
;
360 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
363 scoped_ptr
<BackgroundTracingConfig
> config
= CreatePreemptiveConfig();
365 content::BackgroundTracingManager::TriggerHandle handle
=
366 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
369 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
371 base::Bind(&StartedFinalizingCallback
, run_loop
.QuitClosure(), false));
375 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 0);
379 // This tests that no trace is triggered with a handle that isn't specified
381 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
382 DoesNotTriggerWithWrongHandle
) {
384 SetupBackgroundTracingManager();
386 base::RunLoop run_loop
;
387 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
390 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
391 CreatePreemptiveConfig();
393 content::BackgroundTracingManager::TriggerHandle handle
=
394 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
397 BackgroundTracingManager::GetInstance()->SetActiveScenario(
398 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
399 BackgroundTracingManager::NO_DATA_FILTERING
);
401 BackgroundTracingManager::GetInstance()->WhenIdle(
402 base::Bind(&DisableScenarioWhenIdle
));
404 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
406 base::Bind(&StartedFinalizingCallback
, run_loop
.QuitClosure(), false));
410 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 0);
414 // This tests that no trace is triggered with an invalid handle.
415 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
416 DoesNotTriggerWithInvalidHandle
) {
418 SetupBackgroundTracingManager();
420 base::RunLoop run_loop
;
421 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
424 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
425 CreatePreemptiveConfig();
427 content::BackgroundTracingManager::TriggerHandle handle
=
428 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
431 content::BackgroundTracingManager::GetInstance()
432 ->InvalidateTriggerHandlesForTesting();
434 BackgroundTracingManager::GetInstance()->SetActiveScenario(
435 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
436 BackgroundTracingManager::NO_DATA_FILTERING
);
438 BackgroundTracingManager::GetInstance()->WhenIdle(
439 base::Bind(&DisableScenarioWhenIdle
));
441 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
443 base::Bind(&StartedFinalizingCallback
, run_loop
.QuitClosure(), false));
447 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 0);
451 // This tests that preemptive mode configs will fail.
452 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
453 DoesNotAllowPreemptiveConfigThatsNotManual
) {
455 SetupBackgroundTracingManager();
457 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
460 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config(
461 new content::BackgroundTracingPreemptiveConfig());
463 BackgroundTracingPreemptiveConfig::MonitoringRule rule
;
464 rule
.type
= BackgroundTracingPreemptiveConfig::
465 MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE
;
466 rule
.histogram_trigger_info
.histogram_name_to_trigger_on
= "fake";
467 rule
.histogram_trigger_info
.histogram_bin_to_trigger_on
= 0;
468 config
->configs
.push_back(rule
);
470 bool result
= BackgroundTracingManager::GetInstance()->SetActiveScenario(
471 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
472 BackgroundTracingManager::NO_DATA_FILTERING
);
474 EXPECT_FALSE(result
);
478 // This tests that reactive mode records and terminates with timeout.
479 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
480 ReactiveTimeoutTermination
) {
482 SetupBackgroundTracingManager();
484 base::RunLoop run_loop
;
485 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
486 run_loop
.QuitClosure());
488 scoped_ptr
<BackgroundTracingReactiveConfig
> config
=
489 CreateReactiveConfig();
491 BackgroundTracingManager::TriggerHandle handle
=
492 BackgroundTracingManager::
493 GetInstance()->RegisterTriggerType("reactive_test");
495 BackgroundTracingManager::GetInstance()->SetActiveScenario(
496 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
497 BackgroundTracingManager::NO_DATA_FILTERING
);
499 BackgroundTracingManager::GetInstance()->WhenIdle(
500 base::Bind(&DisableScenarioWhenIdle
));
502 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
503 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
505 BackgroundTracingManager::GetInstance()->FireTimerForTesting();
509 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
513 // This tests that reactive mode records and terminates with a second trigger.
514 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
515 ReactiveSecondTriggerTermination
) {
517 SetupBackgroundTracingManager();
519 base::RunLoop run_loop
;
520 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
521 run_loop
.QuitClosure());
523 scoped_ptr
<BackgroundTracingReactiveConfig
> config
=
524 CreateReactiveConfig();
526 BackgroundTracingManager::TriggerHandle handle
=
527 BackgroundTracingManager::
528 GetInstance()->RegisterTriggerType("reactive_test");
530 BackgroundTracingManager::GetInstance()->SetActiveScenario(
531 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
532 BackgroundTracingManager::NO_DATA_FILTERING
);
534 BackgroundTracingManager::GetInstance()->WhenIdle(
535 base::Bind(&DisableScenarioWhenIdle
));
537 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
538 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
539 // second trigger to terminate.
540 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
541 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
545 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
549 // This tests a third trigger in reactive more does not start another trace.
550 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
551 ReactiveThirdTriggerTimeout
) {
553 SetupBackgroundTracingManager();
555 base::RunLoop run_loop
;
556 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
557 run_loop
.QuitClosure());
559 scoped_ptr
<BackgroundTracingReactiveConfig
> config
=
560 CreateReactiveConfig();
562 BackgroundTracingManager::TriggerHandle handle
=
563 BackgroundTracingManager::
564 GetInstance()->RegisterTriggerType("reactive_test");
566 BackgroundTracingManager::GetInstance()->SetActiveScenario(
567 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
568 BackgroundTracingManager::NO_DATA_FILTERING
);
570 BackgroundTracingManager::GetInstance()->WhenIdle(
571 base::Bind(&DisableScenarioWhenIdle
));
573 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
574 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
575 // second trigger to terminate.
576 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
577 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
578 // third trigger to trigger again, fails as it is still gathering.
579 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
580 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), false));
584 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
588 } // namespace content