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/command_line.h"
7 #include "base/run_loop.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "base/trace_event/memory_dump_manager.h"
10 #include "base/trace_event/memory_dump_provider.h"
11 #include "base/trace_event/memory_dump_request_args.h"
12 #include "content/public/browser/tracing_controller.h"
13 #include "content/public/common/content_switches.h"
14 #include "content/public/test/browser_test_utils.h"
15 #include "content/public/test/content_browser_test.h"
16 #include "content/public/test/content_browser_test_utils.h"
17 #include "content/shell/browser/shell.h"
18 #include "testing/gmock/include/gmock/gmock.h"
20 using base::trace_event::MemoryDumpArgs
;
21 using base::trace_event::MemoryDumpManager
;
22 using base::trace_event::MemoryDumpType
;
23 using base::trace_event::ProcessMemoryDump
;
25 using testing::Return
;
29 // A mock dump provider, used to check that dump requests actually end up
30 // creating memory dumps.
31 class MockDumpProvider
: public base::trace_event::MemoryDumpProvider
{
33 MOCK_METHOD2(OnMemoryDump
, bool(const MemoryDumpArgs
& args
,
34 ProcessMemoryDump
* pmd
));
37 class MemoryTracingTest
: public ContentBrowserTest
{
39 void DoRequestGlobalDump(const base::trace_event::MemoryDumpCallback
& cb
) {
40 MemoryDumpArgs dump_args
= { MemoryDumpArgs::LevelOfDetail::HIGH
};
41 MemoryDumpManager::GetInstance()->RequestGlobalDump(
42 MemoryDumpType::EXPLICITLY_TRIGGERED
, dump_args
, cb
);
45 // Used as callback argument for MemoryDumpManager::RequestGlobalDump():
46 void OnGlobalMemoryDumpDone(
47 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
48 base::Closure closure
,
51 // Make sure we run the RunLoop closure on the same thread that originated
52 // the run loop (which is the IN_PROC_BROWSER_TEST_F main thread).
53 if (!task_runner
->RunsTasksOnCurrentThread()) {
54 task_runner
->PostTask(
55 FROM_HERE
, base::Bind(&MemoryTracingTest::OnGlobalMemoryDumpDone
,
56 base::Unretained(this), task_runner
, closure
,
60 ++callback_call_count_
;
61 last_callback_dump_guid_
= dump_guid
;
62 last_callback_success_
= success
;
67 void SetUp() override
{
68 callback_call_count_
= 0;
69 last_callback_dump_guid_
= 0;
70 last_callback_success_
= false;
72 // TODO(primiano): This should be done via TraceConfig.
73 // See https://goo.gl/5Hj3o0.
74 MemoryDumpManager::GetInstance()->DisablePeriodicDumpsForTesting();
76 mock_dump_provider_
.reset(new MockDumpProvider());
77 MemoryDumpManager::GetInstance()->RegisterDumpProvider(
78 mock_dump_provider_
.get());
79 ContentBrowserTest::SetUp();
82 void TearDown() override
{
83 MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
84 mock_dump_provider_
.get());
85 mock_dump_provider_
.reset();
86 ContentBrowserTest::TearDown();
89 void EnableMemoryTracing() {
90 base::RunLoop run_loop
;
91 std::string category_filter
= MemoryDumpManager::kTraceCategory
;
92 base::trace_event::TraceConfig
trace_config(category_filter
, "");
93 bool success
= TracingController::GetInstance()->EnableRecording(
94 trace_config
, run_loop
.QuitClosure());
99 void DisableTracing() {
100 bool success
= TracingController::GetInstance()->DisableRecording(NULL
);
101 EXPECT_TRUE(success
);
102 base::RunLoop().RunUntilIdle();
105 void RequestGlobalDumpAndWait(bool from_renderer_thread
) {
106 base::RunLoop run_loop
;
107 base::trace_event::MemoryDumpCallback callback
= base::Bind(
108 &MemoryTracingTest::OnGlobalMemoryDumpDone
, base::Unretained(this),
109 base::ThreadTaskRunnerHandle::Get(), run_loop
.QuitClosure());
110 if (from_renderer_thread
) {
111 PostTaskToInProcessRendererAndWait(
112 base::Bind(&MemoryTracingTest::DoRequestGlobalDump
,
113 base::Unretained(this), callback
));
115 DoRequestGlobalDump(callback
);
120 void Navigate(Shell
* shell
) {
121 NavigateToURL(shell
, GetTestUrl("", "title.html"));
124 base::Closure on_memory_dump_complete_closure_
;
125 scoped_ptr
<MockDumpProvider
> mock_dump_provider_
;
126 uint32 callback_call_count_
;
127 uint64 last_callback_dump_guid_
;
128 bool last_callback_success_
;
131 // Ignore SingleProcessMemoryTracingTests for Google Chrome builds because
132 // single-process is not supported on those builds.
133 #if !defined(GOOGLE_CHROME_BUILD)
135 class SingleProcessMemoryTracingTest
: public MemoryTracingTest
{
137 SingleProcessMemoryTracingTest() {}
139 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
140 command_line
->AppendSwitch(switches::kSingleProcess
);
144 // Checks that a memory dump initiated from a the main browser thread ends up in
145 // a single dump even in single process mode.
146 IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest
,
147 BrowserInitiatedSingleDump
) {
150 EXPECT_CALL(*mock_dump_provider_
, OnMemoryDump(_
,_
)).WillOnce(Return(true));
152 EnableMemoryTracing();
153 RequestGlobalDumpAndWait(false /* from_renderer_thread */);
154 EXPECT_EQ(1u, callback_call_count_
);
155 EXPECT_NE(0u, last_callback_dump_guid_
);
156 EXPECT_TRUE(last_callback_success_
);
160 // Checks that a memory dump initiated from a renderer thread ends up in a
161 // single dump even in single process mode.
162 IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest
,
163 RendererInitiatedSingleDump
) {
166 EXPECT_CALL(*mock_dump_provider_
, OnMemoryDump(_
,_
)).WillOnce(Return(true));
168 EnableMemoryTracing();
169 RequestGlobalDumpAndWait(true /* from_renderer_thread */);
170 EXPECT_EQ(1u, callback_call_count_
);
171 EXPECT_NE(0u, last_callback_dump_guid_
);
172 EXPECT_TRUE(last_callback_success_
);
176 IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest
, ManyInterleavedDumps
) {
179 EXPECT_CALL(*mock_dump_provider_
, OnMemoryDump(_
,_
))
181 .WillRepeatedly(Return(true));
183 EnableMemoryTracing();
185 RequestGlobalDumpAndWait(true /* from_renderer_thread */);
186 EXPECT_NE(0u, last_callback_dump_guid_
);
187 EXPECT_TRUE(last_callback_success_
);
189 RequestGlobalDumpAndWait(false /* from_renderer_thread */);
190 EXPECT_NE(0u, last_callback_dump_guid_
);
191 EXPECT_TRUE(last_callback_success_
);
193 RequestGlobalDumpAndWait(false /* from_renderer_thread */);
194 EXPECT_NE(0u, last_callback_dump_guid_
);
195 EXPECT_TRUE(last_callback_success_
);
197 RequestGlobalDumpAndWait(true /* from_renderer_thread */);
198 EXPECT_EQ(4u, callback_call_count_
);
199 EXPECT_NE(0u, last_callback_dump_guid_
);
200 EXPECT_TRUE(last_callback_success_
);
205 #endif // !defined(GOOGLE_CHROME_BUILD)
207 // Checks that a memory dump initiated from a the main browser thread ends up in
208 // a successful dump.
209 IN_PROC_BROWSER_TEST_F(MemoryTracingTest
, BrowserInitiatedDump
) {
212 EXPECT_CALL(*mock_dump_provider_
, OnMemoryDump(_
,_
)).WillOnce(Return(true));
214 EnableMemoryTracing();
215 RequestGlobalDumpAndWait(false /* from_renderer_thread */);
216 EXPECT_EQ(1u, callback_call_count_
);
217 EXPECT_NE(0u, last_callback_dump_guid_
);
218 EXPECT_TRUE(last_callback_success_
);
222 } // namespace content