1 // Copyright 2013 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.
5 #include "base/callback.h"
6 #include "base/command_line.h"
7 #include "base/location.h"
8 #include "base/memory/discardable_memory.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "components/scheduler/renderer/renderer_scheduler.h"
13 #include "content/common/in_process_child_thread_params.h"
14 #include "content/common/resource_messages.h"
15 #include "content/common/websocket_messages.h"
16 #include "content/public/browser/content_browser_client.h"
17 #include "content/public/common/content_client.h"
18 #include "content/public/common/content_switches.h"
19 #include "content/public/renderer/content_renderer_client.h"
20 #include "content/renderer/render_process_impl.h"
21 #include "content/renderer/render_thread_impl.h"
22 #include "content/test/mock_render_process.h"
23 #include "content/test/render_thread_impl_browser_test_ipc_helper.h"
24 #include "gpu/GLES2/gl2extchromium.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 // IPC messages for testing ----------------------------------------------------
29 #define IPC_MESSAGE_IMPL
30 #include "ipc/ipc_message_macros.h"
32 #undef IPC_MESSAGE_START
33 #define IPC_MESSAGE_START TestMsgStart
34 IPC_MESSAGE_CONTROL0(TestMsg_QuitRunLoop
)
36 // -----------------------------------------------------------------------------
38 // These tests leak memory, this macro disables the test when under the
41 #define WILL_LEAK(NAME) DISABLED_##NAME
43 #define WILL_LEAK(NAME) NAME
49 // FIXME: It would be great if there was a reusable mock SingleThreadTaskRunner
50 class TestTaskCounter
: public base::SingleThreadTaskRunner
{
52 TestTaskCounter() : count_(0) {}
54 // SingleThreadTaskRunner implementation.
55 bool PostDelayedTask(const tracked_objects::Location
&,
57 base::TimeDelta
) override
{
58 base::AutoLock
auto_lock(lock_
);
63 bool PostNonNestableDelayedTask(const tracked_objects::Location
&,
65 base::TimeDelta
) override
{
66 base::AutoLock
auto_lock(lock_
);
71 bool RunsTasksOnCurrentThread() const override
{ return true; }
73 int NumTasksPosted() const {
74 base::AutoLock
auto_lock(lock_
);
79 ~TestTaskCounter() override
{}
81 mutable base::Lock lock_
;
85 #if defined(COMPILER_MSVC)
86 // See explanation for other RenderViewHostImpl which is the same issue.
88 #pragma warning(disable: 4250)
91 class RenderThreadImplForTest
: public RenderThreadImpl
{
93 RenderThreadImplForTest(const InProcessChildThreadParams
& params
,
94 scoped_ptr
<scheduler::RendererScheduler
> scheduler
,
95 scoped_refptr
<TestTaskCounter
> test_task_counter
)
96 : RenderThreadImpl(params
, scheduler
.Pass()),
97 test_task_counter_(test_task_counter
) {}
99 ~RenderThreadImplForTest() override
{}
101 void SetResourceDispatchTaskQueue(
102 const scoped_refptr
<base::SingleThreadTaskRunner
>&) override
{
103 // Use our TestTaskCounter instead.
104 RenderThreadImpl::SetResourceDispatchTaskQueue(test_task_counter_
);
107 using ChildThreadImpl::OnMessageReceived
;
110 scoped_refptr
<TestTaskCounter
> test_task_counter_
;
113 #if defined(COMPILER_MSVC)
117 void QuitTask(base::MessageLoop
* message_loop
) {
118 message_loop
->QuitWhenIdle();
121 class QuitOnTestMsgFilter
: public IPC::MessageFilter
{
123 explicit QuitOnTestMsgFilter(base::MessageLoop
* message_loop
)
124 : message_loop_(message_loop
) {}
126 // IPC::MessageFilter overrides:
127 bool OnMessageReceived(const IPC::Message
& message
) override
{
128 message_loop_
->task_runner()->PostTask(
129 FROM_HERE
, base::Bind(&QuitTask
, message_loop_
));
133 bool GetSupportedMessageClasses(
134 std::vector
<uint32
>* supported_message_classes
) const override
{
135 supported_message_classes
->push_back(TestMsgStart
);
140 ~QuitOnTestMsgFilter() override
{}
142 base::MessageLoop
* message_loop_
;
145 class RenderThreadImplBrowserTest
: public testing::Test
{
147 void SetUp() override
{
148 content_client_
.reset(new ContentClient());
149 content_browser_client_
.reset(new ContentBrowserClient());
150 content_renderer_client_
.reset(new ContentRendererClient());
151 SetContentClient(content_client_
.get());
152 SetBrowserClientForTesting(content_browser_client_
.get());
153 SetRendererClientForTesting(content_renderer_client_
.get());
155 test_helper_
.reset(new RenderThreadImplBrowserIPCTestHelper());
157 mock_process_
.reset(new MockRenderProcess
);
158 test_task_counter_
= make_scoped_refptr(new TestTaskCounter());
160 // RenderThreadImpl expects the browser to pass these flags.
161 base::CommandLine
* cmd
= base::CommandLine::ForCurrentProcess();
162 base::CommandLine::StringVector old_argv
= cmd
->argv();
164 cmd
->AppendSwitchASCII(switches::kNumRasterThreads
, "1");
165 std::string image_targets
;
166 for (size_t format
= 0;
167 format
< static_cast<size_t>(gfx::BufferFormat::LAST
) + 1; format
++) {
168 if (!image_targets
.empty())
169 image_targets
+= ",";
170 image_targets
+= base::UintToString(GL_TEXTURE_2D
);
172 cmd
->AppendSwitchASCII(switches::kContentImageTextureTarget
, image_targets
);
174 scoped_ptr
<scheduler::RendererScheduler
> renderer_scheduler
=
175 scheduler::RendererScheduler::Create();
176 thread_
= new RenderThreadImplForTest(
177 InProcessChildThreadParams(test_helper_
->GetChannelId(),
178 test_helper_
->GetIOTaskRunner()),
179 renderer_scheduler
.Pass(), test_task_counter_
);
180 cmd
->InitFromArgv(old_argv
);
182 thread_
->EnsureWebKitInitialized();
184 test_msg_filter_
= make_scoped_refptr(
185 new QuitOnTestMsgFilter(test_helper_
->GetMessageLoop()));
186 thread_
->AddFilter(test_msg_filter_
.get());
189 scoped_refptr
<TestTaskCounter
> test_task_counter_
;
190 scoped_ptr
<ContentClient
> content_client_
;
191 scoped_ptr
<ContentBrowserClient
> content_browser_client_
;
192 scoped_ptr
<ContentRendererClient
> content_renderer_client_
;
193 scoped_ptr
<RenderThreadImplBrowserIPCTestHelper
> test_helper_
;
194 scoped_ptr
<MockRenderProcess
> mock_process_
;
195 scoped_refptr
<QuitOnTestMsgFilter
> test_msg_filter_
;
196 RenderThreadImplForTest
* thread_
; // Owned by mock_process_.
197 std::string channel_id_
;
200 void CheckRenderThreadInputHandlerManager(RenderThreadImpl
* thread
) {
201 ASSERT_TRUE(thread
->input_handler_manager());
204 // Check that InputHandlerManager outlives compositor thread because it uses
205 // raw pointers to post tasks.
206 // Disabled under LeakSanitizer due to memory leaks. http://crbug.com/348994
207 TEST_F(RenderThreadImplBrowserTest
,
208 WILL_LEAK(InputHandlerManagerDestroyedAfterCompositorThread
)) {
209 ASSERT_TRUE(thread_
->input_handler_manager());
211 thread_
->compositor_task_runner()->PostTask(
212 FROM_HERE
, base::Bind(&CheckRenderThreadInputHandlerManager
, thread_
));
215 // Disabled under LeakSanitizer due to memory leaks.
216 TEST_F(RenderThreadImplBrowserTest
,
217 WILL_LEAK(ResourceDispatchIPCTasksGoThroughScheduler
)) {
218 test_helper_
->Sender()->Send(new ResourceHostMsg_FollowRedirect(0));
219 test_helper_
->Sender()->Send(new TestMsg_QuitRunLoop());
221 test_helper_
->GetMessageLoop()->Run();
222 EXPECT_EQ(1, test_task_counter_
->NumTasksPosted());
225 // Disabled under LeakSanitizer due to memory leaks.
226 TEST_F(RenderThreadImplBrowserTest
,
227 WILL_LEAK(NonResourceDispatchIPCTasksDontGoThroughScheduler
)) {
228 // NOTE other than not being a resource message, the actual message is
230 test_helper_
->Sender()->Send(new WebSocketMsg_NotifyFailure(1, ""));
231 test_helper_
->Sender()->Send(new TestMsg_QuitRunLoop());
233 test_helper_
->GetMessageLoop()->Run();
235 EXPECT_EQ(0, test_task_counter_
->NumTasksPosted());
239 } // namespace content