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/strings/pattern.h"
7 #include "base/trace_event/trace_event.h"
8 #include "content/public/browser/background_tracing_manager.h"
9 #include "content/public/browser/background_tracing_preemptive_config.h"
10 #include "content/public/browser/background_tracing_reactive_config.h"
11 #include "content/public/test/content_browser_test.h"
12 #include "content/public/test/content_browser_test_utils.h"
13 #include "content/public/test/test_utils.h"
14 #include "third_party/zlib/zlib.h"
18 class BackgroundTracingManagerBrowserTest
: public ContentBrowserTest
{
20 BackgroundTracingManagerBrowserTest() {}
23 DISALLOW_COPY_AND_ASSIGN(BackgroundTracingManagerBrowserTest
);
26 class BackgroundTracingManagerUploadConfigWrapper
{
28 BackgroundTracingManagerUploadConfigWrapper(const base::Closure
& callback
)
29 : callback_(callback
), receive_count_(0) {
31 base::Bind(&BackgroundTracingManagerUploadConfigWrapper::Upload
,
32 base::Unretained(this));
35 void Upload(const scoped_refptr
<base::RefCountedString
>& file_contents
,
36 scoped_ptr
<base::DictionaryValue
> metadata
,
37 base::Callback
<void()> done_callback
) {
39 EXPECT_TRUE(file_contents
);
41 size_t compressed_length
= file_contents
->data().length();
42 const size_t kOutputBufferLength
= 10 * 1024 * 1024;
43 std::vector
<char> output_str(kOutputBufferLength
);
45 z_stream stream
= {0};
46 stream
.avail_in
= compressed_length
;
47 stream
.avail_out
= kOutputBufferLength
;
48 stream
.next_in
= (Bytef
*)&file_contents
->data()[0];
49 stream
.next_out
= (Bytef
*)vector_as_array(&output_str
);
51 // 16 + MAX_WBITS means only decoding gzip encoded streams, and using
52 // the biggest window size, according to zlib.h
53 int result
= inflateInit2(&stream
, 16 + MAX_WBITS
);
54 EXPECT_EQ(Z_OK
, result
);
55 result
= inflate(&stream
, Z_FINISH
);
56 int bytes_written
= kOutputBufferLength
- stream
.avail_out
;
59 EXPECT_EQ(Z_STREAM_END
, result
);
61 last_file_contents_
.assign(vector_as_array(&output_str
), bytes_written
);
62 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
63 base::Bind(done_callback
));
64 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
65 base::Bind(callback_
));
68 bool TraceHasMatchingString(const char* str
) {
69 return last_file_contents_
.find(str
) != std::string::npos
;
72 int get_receive_count() const { return receive_count_
; }
74 const BackgroundTracingManager::ReceiveCallback
& get_receive_callback()
76 return receive_callback_
;
80 BackgroundTracingManager::ReceiveCallback receive_callback_
;
81 base::Closure callback_
;
83 std::string last_file_contents_
;
86 void StartedFinalizingCallback(base::Closure callback
,
89 EXPECT_EQ(expected
, value
);
90 if (!callback
.is_null())
94 scoped_ptr
<BackgroundTracingPreemptiveConfig
> CreatePreemptiveConfig() {
95 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config(
96 new BackgroundTracingPreemptiveConfig());
98 BackgroundTracingPreemptiveConfig::MonitoringRule rule
;
100 BackgroundTracingPreemptiveConfig::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED
;
101 rule
.named_trigger_info
.trigger_name
= "preemptive_test";
103 config
->configs
.push_back(rule
);
105 return config
.Pass();
108 scoped_ptr
<BackgroundTracingReactiveConfig
> CreateReactiveConfig() {
109 scoped_ptr
<BackgroundTracingReactiveConfig
> config(
110 new BackgroundTracingReactiveConfig());
112 BackgroundTracingReactiveConfig::TracingRule rule
;
114 BackgroundTracingReactiveConfig::TRACE_FOR_10S_OR_TRIGGER_OR_FULL
;
115 rule
.trigger_name
= "reactive_test";
116 rule
.category_preset
=
117 BackgroundTracingConfig::CategoryPreset::BENCHMARK_DEEP
;
119 config
->configs
.push_back(rule
);
121 return config
.Pass();
124 void SetupBackgroundTracingManager() {
125 content::BackgroundTracingManager::GetInstance()
126 ->InvalidateTriggerHandlesForTesting();
129 void DisableScenarioWhenIdle() {
130 BackgroundTracingManager::GetInstance()->SetActiveScenario(
131 NULL
, BackgroundTracingManager::ReceiveCallback(),
132 BackgroundTracingManager::NO_DATA_FILTERING
);
135 // This tests that the endpoint receives the final trace data.
136 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
137 ReceiveTraceFinalContentsOnTrigger
) {
139 SetupBackgroundTracingManager();
141 base::RunLoop run_loop
;
142 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
143 run_loop
.QuitClosure());
145 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
146 CreatePreemptiveConfig();
148 BackgroundTracingManager::TriggerHandle handle
=
149 BackgroundTracingManager::
150 GetInstance()->RegisterTriggerType("preemptive_test");
152 BackgroundTracingManager::GetInstance()->SetActiveScenario(
153 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
154 BackgroundTracingManager::NO_DATA_FILTERING
);
156 BackgroundTracingManager::GetInstance()->WhenIdle(
157 base::Bind(&DisableScenarioWhenIdle
));
159 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
160 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
164 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
168 // This tests triggering more than once still only gathers once.
169 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
170 CallTriggersMoreThanOnceOnlyGatherOnce
) {
172 SetupBackgroundTracingManager();
174 base::RunLoop run_loop
;
175 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
176 run_loop
.QuitClosure());
178 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
179 CreatePreemptiveConfig();
181 content::BackgroundTracingManager::TriggerHandle handle
=
182 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
185 BackgroundTracingManager::GetInstance()->SetActiveScenario(
186 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
187 BackgroundTracingManager::NO_DATA_FILTERING
);
189 BackgroundTracingManager::GetInstance()->WhenIdle(
190 base::Bind(&DisableScenarioWhenIdle
));
192 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
193 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
194 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
195 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), false));
199 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
205 bool IsTraceEventArgsWhitelisted(const char* category_group_name
,
206 const char* event_name
) {
207 if (base::MatchPattern(category_group_name
, "benchmark") &&
208 base::MatchPattern(event_name
, "whitelisted")) {
217 // This tests that non-whitelisted args get stripped if required.
218 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
219 NoWhitelistedArgsStripped
) {
220 SetupBackgroundTracingManager();
222 base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
223 base::Bind(&IsTraceEventArgsWhitelisted
));
225 base::RunLoop wait_for_upload
;
226 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
227 wait_for_upload
.QuitClosure());
229 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
230 CreatePreemptiveConfig();
232 content::BackgroundTracingManager::TriggerHandle handle
=
233 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
236 base::RunLoop wait_for_activated
;
237 BackgroundTracingManager::GetInstance()->SetTracingEnabledCallbackForTesting(
238 wait_for_activated
.QuitClosure());
239 EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
240 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
241 BackgroundTracingManager::ANONYMIZE_DATA
));
243 wait_for_activated
.Run();
245 TRACE_EVENT1("benchmark", "whitelisted", "find_this", 1);
246 TRACE_EVENT1("benchmark", "not_whitelisted", "this_not_found", 1);
248 BackgroundTracingManager::GetInstance()->WhenIdle(
249 base::Bind(&DisableScenarioWhenIdle
));
251 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
252 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
254 wait_for_upload
.Run();
256 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
257 EXPECT_TRUE(upload_config_wrapper
.TraceHasMatchingString("{"));
258 EXPECT_TRUE(upload_config_wrapper
.TraceHasMatchingString("find_this"));
259 EXPECT_TRUE(!upload_config_wrapper
.TraceHasMatchingString("this_not_found"));
262 // This tests subprocesses (like a navigating renderer) which gets told to
263 // provide a argument-filtered trace and has no predicate in place to do the
264 // filtering (in this case, only the browser process gets it set), will crash
265 // rather than return potential PII.
266 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
267 CrashWhenSubprocessWithoutArgumentFilter
) {
268 SetupBackgroundTracingManager();
270 base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
271 base::Bind(&IsTraceEventArgsWhitelisted
));
273 base::RunLoop wait_for_upload
;
274 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
275 wait_for_upload
.QuitClosure());
277 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
278 CreatePreemptiveConfig();
280 content::BackgroundTracingManager::TriggerHandle handle
=
281 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
284 base::RunLoop wait_for_activated
;
285 BackgroundTracingManager::GetInstance()->SetTracingEnabledCallbackForTesting(
286 wait_for_activated
.QuitClosure());
287 EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
288 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
289 BackgroundTracingManager::ANONYMIZE_DATA
));
291 wait_for_activated
.Run();
293 NavigateToURL(shell(), GetTestUrl("", "about:blank"));
295 BackgroundTracingManager::GetInstance()->WhenIdle(
296 base::Bind(&DisableScenarioWhenIdle
));
298 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
299 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
301 wait_for_upload
.Run();
303 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
304 // We should *not* receive anything at all from the renderer,
305 // the process should've crashed rather than letting that happen.
306 EXPECT_TRUE(!upload_config_wrapper
.TraceHasMatchingString("CrRendererMain"));
309 // This tests multiple triggers still only gathers once.
310 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
311 CallMultipleTriggersOnlyGatherOnce
) {
313 SetupBackgroundTracingManager();
315 base::RunLoop run_loop
;
316 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
317 run_loop
.QuitClosure());
319 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
320 CreatePreemptiveConfig();
322 BackgroundTracingPreemptiveConfig::MonitoringRule rule
;
324 BackgroundTracingPreemptiveConfig::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED
;
325 rule
.named_trigger_info
.trigger_name
= "test1";
326 config
->configs
.push_back(rule
);
328 rule
.named_trigger_info
.trigger_name
= "test2";
329 config
->configs
.push_back(rule
);
331 BackgroundTracingManager::TriggerHandle handle1
=
332 BackgroundTracingManager::GetInstance()->RegisterTriggerType("test1");
333 BackgroundTracingManager::TriggerHandle handle2
=
334 BackgroundTracingManager::GetInstance()->RegisterTriggerType("test2");
336 BackgroundTracingManager::GetInstance()->SetActiveScenario(
337 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
338 BackgroundTracingManager::NO_DATA_FILTERING
);
340 BackgroundTracingManager::GetInstance()->WhenIdle(
341 base::Bind(&DisableScenarioWhenIdle
));
343 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
344 handle1
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
345 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
347 base::Bind(&StartedFinalizingCallback
, base::Closure(), false));
351 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
355 // This tests that you can't trigger without a scenario set.
356 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
357 CannotTriggerWithoutScenarioSet
) {
359 SetupBackgroundTracingManager();
361 base::RunLoop run_loop
;
362 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
365 scoped_ptr
<BackgroundTracingConfig
> config
= CreatePreemptiveConfig();
367 content::BackgroundTracingManager::TriggerHandle handle
=
368 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
371 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
373 base::Bind(&StartedFinalizingCallback
, run_loop
.QuitClosure(), false));
377 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 0);
381 // This tests that no trace is triggered with a handle that isn't specified
383 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
384 DoesNotTriggerWithWrongHandle
) {
386 SetupBackgroundTracingManager();
388 base::RunLoop run_loop
;
389 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
392 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
393 CreatePreemptiveConfig();
395 content::BackgroundTracingManager::TriggerHandle handle
=
396 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
399 BackgroundTracingManager::GetInstance()->SetActiveScenario(
400 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
401 BackgroundTracingManager::NO_DATA_FILTERING
);
403 BackgroundTracingManager::GetInstance()->WhenIdle(
404 base::Bind(&DisableScenarioWhenIdle
));
406 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
408 base::Bind(&StartedFinalizingCallback
, run_loop
.QuitClosure(), false));
412 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 0);
416 // This tests that no trace is triggered with an invalid handle.
417 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
418 DoesNotTriggerWithInvalidHandle
) {
420 SetupBackgroundTracingManager();
422 base::RunLoop run_loop
;
423 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
426 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config
=
427 CreatePreemptiveConfig();
429 content::BackgroundTracingManager::TriggerHandle handle
=
430 content::BackgroundTracingManager::GetInstance()->RegisterTriggerType(
433 content::BackgroundTracingManager::GetInstance()
434 ->InvalidateTriggerHandlesForTesting();
436 BackgroundTracingManager::GetInstance()->SetActiveScenario(
437 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
438 BackgroundTracingManager::NO_DATA_FILTERING
);
440 BackgroundTracingManager::GetInstance()->WhenIdle(
441 base::Bind(&DisableScenarioWhenIdle
));
443 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
445 base::Bind(&StartedFinalizingCallback
, run_loop
.QuitClosure(), false));
449 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 0);
453 // This tests that preemptive mode configs will fail.
454 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
455 DoesNotAllowPreemptiveConfigThatsNotManual
) {
457 SetupBackgroundTracingManager();
459 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
462 scoped_ptr
<BackgroundTracingPreemptiveConfig
> config(
463 new content::BackgroundTracingPreemptiveConfig());
465 BackgroundTracingPreemptiveConfig::MonitoringRule rule
;
466 rule
.type
= BackgroundTracingPreemptiveConfig::
467 MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE
;
468 rule
.histogram_trigger_info
.histogram_name_to_trigger_on
= "fake";
469 rule
.histogram_trigger_info
.histogram_bin_to_trigger_on
= 0;
470 config
->configs
.push_back(rule
);
472 bool result
= BackgroundTracingManager::GetInstance()->SetActiveScenario(
473 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
474 BackgroundTracingManager::NO_DATA_FILTERING
);
476 EXPECT_FALSE(result
);
480 // This tests that reactive mode records and terminates with timeout.
481 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
482 ReactiveTimeoutTermination
) {
484 SetupBackgroundTracingManager();
486 base::RunLoop run_loop
;
487 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
488 run_loop
.QuitClosure());
490 scoped_ptr
<BackgroundTracingReactiveConfig
> config
=
491 CreateReactiveConfig();
493 BackgroundTracingManager::TriggerHandle handle
=
494 BackgroundTracingManager::
495 GetInstance()->RegisterTriggerType("reactive_test");
497 BackgroundTracingManager::GetInstance()->SetActiveScenario(
498 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
499 BackgroundTracingManager::NO_DATA_FILTERING
);
501 BackgroundTracingManager::GetInstance()->WhenIdle(
502 base::Bind(&DisableScenarioWhenIdle
));
504 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
505 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
507 BackgroundTracingManager::GetInstance()->FireTimerForTesting();
511 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
515 // This tests that reactive mode records and terminates with a second trigger.
516 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
517 ReactiveSecondTriggerTermination
) {
519 SetupBackgroundTracingManager();
521 base::RunLoop run_loop
;
522 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
523 run_loop
.QuitClosure());
525 scoped_ptr
<BackgroundTracingReactiveConfig
> config
=
526 CreateReactiveConfig();
528 BackgroundTracingManager::TriggerHandle handle
=
529 BackgroundTracingManager::
530 GetInstance()->RegisterTriggerType("reactive_test");
532 BackgroundTracingManager::GetInstance()->SetActiveScenario(
533 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
534 BackgroundTracingManager::NO_DATA_FILTERING
);
536 BackgroundTracingManager::GetInstance()->WhenIdle(
537 base::Bind(&DisableScenarioWhenIdle
));
539 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
540 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
541 // second trigger to terminate.
542 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
543 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
547 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
551 // This tests a third trigger in reactive more does not start another trace.
552 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest
,
553 ReactiveThirdTriggerTimeout
) {
555 SetupBackgroundTracingManager();
557 base::RunLoop run_loop
;
558 BackgroundTracingManagerUploadConfigWrapper
upload_config_wrapper(
559 run_loop
.QuitClosure());
561 scoped_ptr
<BackgroundTracingReactiveConfig
> config
=
562 CreateReactiveConfig();
564 BackgroundTracingManager::TriggerHandle handle
=
565 BackgroundTracingManager::
566 GetInstance()->RegisterTriggerType("reactive_test");
568 BackgroundTracingManager::GetInstance()->SetActiveScenario(
569 config
.Pass(), upload_config_wrapper
.get_receive_callback(),
570 BackgroundTracingManager::NO_DATA_FILTERING
);
572 BackgroundTracingManager::GetInstance()->WhenIdle(
573 base::Bind(&DisableScenarioWhenIdle
));
575 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
576 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
577 // second trigger to terminate.
578 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
579 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), true));
580 // third trigger to trigger again, fails as it is still gathering.
581 BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
582 handle
, base::Bind(&StartedFinalizingCallback
, base::Closure(), false));
586 EXPECT_TRUE(upload_config_wrapper
.get_receive_count() == 1);
590 } // namespace content