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

Side by Side Diff: components/tracing/child/child_trace_message_filter_browsertest.cc

Issue 2694083005: memory-infra: Finish moving memory_infra from TracingController (Closed)
Patch Set: style: auto must not deduce to raw pointer Created 3 years, 9 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
« no previous file with comments | « components/tracing/child/child_trace_message_filter.cc ('k') | content/browser/browser_main.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include <stdint.h>
6
7 #include <memory>
8 #include <tuple>
9
10 #include "base/callback.h"
11 #include "base/run_loop.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/trace_event/memory_dump_manager.h"
14 #include "base/trace_event/memory_dump_provider.h"
15 #include "base/trace_event/trace_event.h"
16 #include "components/tracing/child/child_memory_dump_manager_delegate_impl.h"
17 #include "components/tracing/child/child_trace_message_filter.h"
18 #include "components/tracing/common/tracing_messages.h"
19 #include "content/public/test/render_view_test.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21
22 using base::trace_event::MemoryDumpManager;
23 using base::trace_event::MemoryDumpRequestArgs;
24 using base::trace_event::MemoryDumpArgs;
25 using base::trace_event::MemoryDumpLevelOfDetail;
26 using base::trace_event::MemoryDumpType;
27 using testing::_;
28 using testing::Return;
29
30 namespace tracing {
31
32 // A mock dump provider, used to check that dump requests actually end up
33 // creating memory dumps.
34 class MockDumpProvider : public base::trace_event::MemoryDumpProvider {
35 public:
36 MOCK_METHOD2(OnMemoryDump,
37 bool(const MemoryDumpArgs& args,
38 base::trace_event::ProcessMemoryDump* pmd));
39 };
40
41 class ChildTracingTest : public content::RenderViewTest, public IPC::Listener {
42 public:
43 // Used as callback argument for MemoryDumpManager::RequestGlobalDump():
44 void OnMemoryDumpCallback(uint64_t dump_guid, bool status) {
45 last_callback_dump_guid_ = dump_guid;
46 last_callback_status_ = status;
47 ++callback_call_count_;
48 }
49
50 protected:
51 void SetUp() override {
52 // RenderViewTest::SetUp causes additional registrations, so we first
53 // register the mock dump provider and ignore registrations from then on.
54 // In addition to the mock dump provider, the TraceLog has already
55 // registered itself by now; this cannot be prevented easily.
56 mock_dump_provider_.reset(new MockDumpProvider());
57 MemoryDumpManager::GetInstance()->RegisterDumpProvider(
58 mock_dump_provider_.get(), "MockDumpProvider",
59 base::ThreadTaskRunnerHandle::Get());
60 MemoryDumpManager::GetInstance()
61 ->set_dumper_registrations_ignored_for_testing(true);
62
63 RenderViewTest::SetUp();
64
65 callback_call_count_ = 0;
66 last_callback_dump_guid_ = 0;
67 last_callback_status_ = false;
68 wait_for_ipc_message_type_ = 0;
69 callback_ = base::Bind(&ChildTracingTest::OnMemoryDumpCallback,
70 base::Unretained(this));
71 task_runner_ = base::ThreadTaskRunnerHandle::Get();
72 ctmf_ = make_scoped_refptr(new ChildTraceMessageFilter(task_runner_.get()));
73 render_thread_->AddFilter(ctmf_.get());
74
75 // Add a filter to the TestSink which allows to WaitForIPCMessage() by
76 // posting a nested RunLoop closure when a given IPC Message is seen.
77 render_thread_->sink().AddFilter(this);
78
79 // Getting an instance of |ChildMemoryDumpManagerDelegateImpl| calls
80 // |MemoryDumpManager::Initialize| with the correct delegate.
81 ChildMemoryDumpManagerDelegateImpl::GetInstance();
82 }
83
84 void TearDown() override {
85 render_thread_->sink().RemoveFilter(this);
86 RenderViewTest::TearDown();
87 MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
88 mock_dump_provider_.get());
89 mock_dump_provider_.reset();
90 ctmf_ = nullptr;
91 task_runner_ = nullptr;
92 }
93
94 // IPC::Filter implementation.
95 bool OnMessageReceived(const IPC::Message& message) override {
96 if (message.type() == wait_for_ipc_message_type_) {
97 DCHECK(!wait_for_ipc_closure_.is_null());
98 task_runner_->PostTask(FROM_HERE, wait_for_ipc_closure_);
99 }
100 // Always propagate messages to the sink, never consume them here.
101 return false;
102 }
103
104 const IPC::Message* WaitForIPCMessage(uint32_t message_type) {
105 base::RunLoop run_loop;
106 wait_for_ipc_message_type_ = message_type;
107 wait_for_ipc_closure_ = run_loop.QuitClosure();
108 run_loop.Run();
109 wait_for_ipc_message_type_ = 0;
110 wait_for_ipc_closure_.Reset();
111 return render_thread_->sink().GetUniqueMessageMatching(message_type);
112 }
113
114 // Simulates a synthetic browser -> child (this process) IPC message.
115 void SimulateSyntheticMessageFromBrowser(const IPC::Message& msg) {
116 ctmf_->OnMessageReceived(msg);
117 }
118
119 void EnableTracingWithMemoryDumps() {
120 // Re-enabling tracing could crash these tests https://crbug.com/656729 .
121 if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) {
122 FAIL() << "Tracing seems to be already enabled. "
123 "Very likely this is because the startup tracing file "
124 "has been leaked from a previous test.";
125 }
126
127 std::string category_filter = "-*,"; // Disable all other trace categories.
128 category_filter += MemoryDumpManager::kTraceCategory;
129 base::trace_event::TraceConfig trace_config(category_filter, "");
130 TracingMsg_BeginTracing msg(trace_config.ToString(), base::TimeTicks(), 0);
131 SimulateSyntheticMessageFromBrowser(msg);
132 }
133
134 void DisableTracing() {
135 SimulateSyntheticMessageFromBrowser(TracingMsg_EndTracing());
136 }
137
138 // Simulates a synthetic browser -> child process memory dump request and
139 // checks that the child actually sends a response to that.
140 void RequestProcessMemoryDumpAndCheckResponse(uint64_t dump_guid) {
141 SimulateSyntheticMessageFromBrowser(TracingMsg_ProcessMemoryDumpRequest(
142 {dump_guid, MemoryDumpType::EXPLICITLY_TRIGGERED,
143 MemoryDumpLevelOfDetail::DETAILED}));
144
145 // Check that a child -> browser response to the local dump request is sent.
146 const IPC::Message* msg =
147 WaitForIPCMessage(TracingHostMsg_ProcessMemoryDumpResponse::ID);
148 EXPECT_NE(nullptr, msg);
149
150 // Check that the |dump_guid| and the |success| fields are properly set.
151 TracingHostMsg_ProcessMemoryDumpResponse::Param params;
152 TracingHostMsg_ProcessMemoryDumpResponse::Read(msg, &params);
153 const uint64_t resp_guid = std::get<0>(params);
154 const bool resp_success = std::get<1>(params);
155 EXPECT_EQ(dump_guid, resp_guid);
156 EXPECT_TRUE(resp_success);
157 }
158
159 // Retrieves the MemoryDumpRequestArgs of the global memory dump request that
160 // this child process tried to send to the browser. Fails if either none or
161 // multiple requests were sent.
162 MemoryDumpRequestArgs GetInterceptedGlobalMemoryDumpRequest() {
163 const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
164 TracingHostMsg_GlobalMemoryDumpRequest::ID);
165 EXPECT_NE(nullptr, msg);
166 TracingHostMsg_GlobalMemoryDumpRequest::Param params;
167 TracingHostMsg_GlobalMemoryDumpRequest::Read(msg, &params);
168 MemoryDumpRequestArgs args = std::get<0>(params);
169 EXPECT_NE(0U, args.dump_guid);
170 return args;
171 }
172
173 scoped_refptr<ChildTraceMessageFilter> ctmf_;
174 std::unique_ptr<MockDumpProvider> mock_dump_provider_;
175 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
176 base::trace_event::MemoryDumpCallback callback_;
177 uint32_t wait_for_ipc_message_type_;
178 base::Closure wait_for_ipc_closure_;
179 uint32_t callback_call_count_;
180 uint64_t last_callback_dump_guid_;
181 bool last_callback_status_;
182 };
183
184 // Covers the case of some browser-initiated memory dumps.
185 #if defined(OS_ANDROID)
186 // Flaky on Android. http://crbug.com/620734.
187 #define MAYBE_BrowserInitiatedMemoryDumps DISABLED_BrowserInitiatedMemoryDumps
188 #else
189 #define MAYBE_BrowserInitiatedMemoryDumps BrowserInitiatedMemoryDumps
190 #endif
191 TEST_F(ChildTracingTest, MAYBE_BrowserInitiatedMemoryDumps) {
192 const uint32_t kNumDumps = 3;
193
194 EnableTracingWithMemoryDumps();
195 EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _))
196 .Times(kNumDumps)
197 .WillRepeatedly(Return(true));
198
199 for (uint32_t i = 0; i < kNumDumps; ++i) {
200 render_thread_->sink().ClearMessages();
201 RequestProcessMemoryDumpAndCheckResponse(i + 1);
202 }
203
204 DisableTracing();
205 }
206
207 // Covers the case of one simple child-initiated memory dump without callback,
208 // simulating a global memory dump request to the browser (+ response).
209 TEST_F(ChildTracingTest, SingleChildInitiatedMemoryDump) {
210 EnableTracingWithMemoryDumps();
211
212 // Expect that our mock dump provider is called when the emulated memory dump
213 // request (browser -> child) is sent.
214 EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _))
215 .Times(1)
216 .WillRepeatedly(Return(true));
217
218 // Send the global memory dump request to the browser.
219 render_thread_->sink().ClearMessages();
220 MemoryDumpManager::GetInstance()->RequestGlobalDump(
221 MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::DETAILED);
222 base::RunLoop().RunUntilIdle();
223
224 // Check that the child -> browser global dump request IPC is actually sent.
225 MemoryDumpRequestArgs args = GetInterceptedGlobalMemoryDumpRequest();
226 EXPECT_EQ(MemoryDumpType::EXPLICITLY_TRIGGERED, args.dump_type);
227
228 // Emulate a browser -> child process dump request and corresponding response.
229 RequestProcessMemoryDumpAndCheckResponse(args.dump_guid);
230
231 // Send a synthetic browser -> child global memory dump response.
232 SimulateSyntheticMessageFromBrowser(
233 TracingMsg_GlobalMemoryDumpResponse(args.dump_guid, true));
234
235 DisableTracing();
236 }
237
238 // Covers the case of a global memory dump being requested while another one is
239 // in progress and has not been acknowledged by the browser. The second request
240 // is expected to fail immediately, while the first one is expected to suceed.
241 TEST_F(ChildTracingTest, OverlappingChildInitiatedMemoryDumps) {
242 EnableTracingWithMemoryDumps();
243
244 // Expect that our mock dump provider is called only once.
245 EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _))
246 .Times(1)
247 .WillRepeatedly(Return(true));
248
249 // Send the global memory dump request to the browser.
250 render_thread_->sink().ClearMessages();
251 MemoryDumpManager::GetInstance()->RequestGlobalDump(
252 MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::DETAILED,
253 callback_);
254 base::RunLoop().RunUntilIdle();
255
256 // Check that the child -> browser global dump request IPC is actually sent.
257 MemoryDumpRequestArgs args = GetInterceptedGlobalMemoryDumpRequest();
258 EXPECT_EQ(MemoryDumpType::EXPLICITLY_TRIGGERED, args.dump_type);
259
260 // Emulate a browser -> child process dump request and corresponding response.
261 RequestProcessMemoryDumpAndCheckResponse(args.dump_guid);
262
263 // Before the response for the first global dump is sent, send another one,
264 // and expect that to fail.
265 render_thread_->sink().ClearMessages();
266 MemoryDumpManager::GetInstance()->RequestGlobalDump(
267 MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::DETAILED,
268 callback_);
269 base::RunLoop().RunUntilIdle();
270
271 EXPECT_EQ(1u, callback_call_count_);
272 EXPECT_FALSE(last_callback_status_);
273 // Whatever the guid of the second failing request is, it cannot possibly be
274 // equal to the guid of the first request.
275 EXPECT_NE(args.dump_guid, last_callback_dump_guid_);
276
277 // Also, check that no request has been forwarded to the browser (because the
278 // first request is still outstanding and has not received any response yet).
279 EXPECT_EQ(nullptr, render_thread_->sink().GetUniqueMessageMatching(
280 TracingHostMsg_GlobalMemoryDumpRequest::ID));
281
282 // Now send a synthetic browser -> child response to the first request.
283 SimulateSyntheticMessageFromBrowser(
284 TracingMsg_GlobalMemoryDumpResponse(args.dump_guid, true));
285
286 // Verify that the the callback for the first request is finally called.
287 EXPECT_EQ(2u, callback_call_count_);
288 EXPECT_EQ(args.dump_guid, last_callback_dump_guid_);
289 EXPECT_TRUE(last_callback_status_);
290
291 DisableTracing();
292 }
293
294 // Covers the case of five child-initiated global memory dumps. Each global dump
295 // request has a callback, which is expected to fail for 3 out of 5 cases.
296 TEST_F(ChildTracingTest, MultipleChildInitiatedMemoryDumpWithFailures) {
297 const uint32_t kNumRequests = 5;
298 MemoryDumpType kDumpType = MemoryDumpType::EXPLICITLY_TRIGGERED;
299
300 EnableTracingWithMemoryDumps();
301 EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _))
302 .Times(kNumRequests)
303 .WillRepeatedly(Return(true));
304
305 for (uint32_t i = 0; i < kNumRequests; ++i) {
306 render_thread_->sink().ClearMessages();
307 MemoryDumpManager::GetInstance()->RequestGlobalDump(
308 kDumpType, MemoryDumpLevelOfDetail::DETAILED, callback_);
309 base::RunLoop().RunUntilIdle();
310
311 MemoryDumpRequestArgs args = GetInterceptedGlobalMemoryDumpRequest();
312 EXPECT_EQ(kDumpType, args.dump_type);
313 RequestProcessMemoryDumpAndCheckResponse(args.dump_guid);
314
315 const bool success = (i & 1) ? true : false;
316 SimulateSyntheticMessageFromBrowser(
317 TracingMsg_GlobalMemoryDumpResponse(args.dump_guid, success));
318 EXPECT_EQ(i + 1, callback_call_count_);
319 EXPECT_EQ(args.dump_guid, last_callback_dump_guid_);
320 EXPECT_EQ(success, last_callback_status_);
321 }
322
323 DisableTracing();
324 }
325
326 } // namespace tracing
OLDNEW
« no previous file with comments | « components/tracing/child/child_trace_message_filter.cc ('k') | content/browser/browser_main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698