1 // Copyright (c) 2014 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/run_loop.h"
6 #include "base/synchronization/waitable_event.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "content/common/gpu/gpu_channel.h"
9 #include "content/common/gpu/gpu_channel_manager.h"
10 #include "content/common/gpu/gpu_messages.h"
11 #include "content/common/message_router.h"
12 #include "gpu/command_buffer/common/value_state.h"
13 #include "gpu/command_buffer/service/gl_utils.h"
14 #include "gpu/command_buffer/service/valuebuffer_manager.h"
15 #include "ipc/ipc_sync_channel.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using base::WaitableEvent
;
20 using gpu::gles2::ValuebufferManager
;
21 using gpu::ValueState
;
25 class SimpleWorker
: public Listener
, public Sender
{
27 SimpleWorker(Channel::Mode mode
, const std::string
& thread_name
)
29 ipc_thread_((thread_name
+ "_ipc").c_str()),
30 shutdown_event_(true, false) {
33 ~SimpleWorker() override
{
38 bool Send(Message
* msg
) override
{ return channel_
->Send(msg
); }
40 virtual void Start() {
41 StartThread(&ipc_thread_
, base::MessageLoop::TYPE_IO
);
42 channel_
.reset(CreateChannel());
45 virtual void Shutdown() {
46 WaitableEvent
ipc_done(false, false);
47 ipc_thread_
.message_loop()->PostTask(
48 FROM_HERE
, base::Bind(&SimpleWorker::OnShutdown
, this, &ipc_done
));
57 SyncChannel
* CreateChannel() {
58 scoped_ptr
<SyncChannel
> channel
= SyncChannel::Create(
59 channel_name_
, mode_
, this, ipc_thread_
.message_loop_proxy().get(),
60 true, &shutdown_event_
);
61 return channel
.release();
64 void OnShutdown(WaitableEvent
* ipc_event
) {
65 base::RunLoop().RunUntilIdle();
69 const base::Thread
& ipc_thread() const { return ipc_thread_
; }
71 WaitableEvent
* shutdown_event() { return &shutdown_event_
; }
73 SyncChannel
* channel() { return channel_
.get(); }
76 bool OnMessageReceived(const Message
& message
) override
{ return false; }
78 void StartThread(base::Thread
* thread
, base::MessageLoop::Type type
) {
79 base::Thread::Options options
;
80 options
.message_loop_type
= type
;
81 thread
->StartWithOptions(options
);
84 std::string channel_name_
;
86 scoped_ptr
<SyncChannel
> channel_
;
87 base::Thread ipc_thread_
;
89 base::WaitableEvent shutdown_event_
;
91 DISALLOW_COPY_AND_ASSIGN(SimpleWorker
);
94 class SimpleServer
: public SimpleWorker
{
96 explicit SimpleServer()
97 : SimpleWorker(Channel::MODE_SERVER
, "simpler_server") { }
104 class SimpleGpuClient
: public IPC::SimpleWorker
{
107 : IPC::SimpleWorker(IPC::Channel::MODE_CLIENT
, "simple_client"),
111 void Start() override
{
112 IPC::SimpleWorker::Start();
113 gpu_channel_manager_
.reset(
114 new GpuChannelManager(&router_
,
116 ipc_thread().message_loop_proxy().get(),
121 void Shutdown() override
{
122 gpu_channel_manager_
.reset();
123 IPC::SimpleWorker::Shutdown();
126 GpuChannelManager
* gpu_channel_manager() {
127 return gpu_channel_manager_
.get();
131 class SimpleMessageRouter
: public MessageRouter
{
133 explicit SimpleMessageRouter(IPC::Sender
* sender
)
137 bool Send(IPC::Message
* msg
) override
{ return sender_
->Send(msg
); }
140 IPC::Sender
* const sender_
;
143 SimpleMessageRouter router_
;
145 scoped_ptr
<GpuChannelManager
> gpu_channel_manager_
;
148 class GpuChannelManagerTest
: public testing::Test
{
150 GpuChannelManagerTest() {}
152 void SetUp() override
{
153 simple_client_
.reset(new SimpleGpuClient());
154 simple_server_
.reset(new IPC::SimpleServer());
155 simple_server_
->Start();
156 simple_client_
->Start();
159 void TearDown() override
{
160 simple_client_
->Shutdown();
161 simple_server_
->Shutdown();
165 scoped_ptr
<SimpleGpuClient
> simple_client_
;
166 scoped_ptr
<IPC::SimpleServer
> simple_server_
;
169 base::MessageLoop message_loop_
;
172 TEST_F(GpuChannelManagerTest
, SecureValueStateForwarding
) {
173 const int kClientId1
= 111;
174 const int kClientId2
= 222;
175 ValueState value_state1
;
176 value_state1
.int_value
[0] = 1111;
177 value_state1
.int_value
[1] = 0;
178 value_state1
.int_value
[2] = 0;
179 value_state1
.int_value
[3] = 0;
180 ValueState value_state2
;
181 value_state2
.int_value
[0] = 3333;
182 value_state2
.int_value
[1] = 0;
183 value_state2
.int_value
[2] = 0;
184 value_state2
.int_value
[3] = 0;
186 ASSERT_TRUE(simple_client_
->gpu_channel_manager() != NULL
);
188 // Initialize gpu channels
189 simple_client_
->gpu_channel_manager()->OnMessageReceived(
190 GpuMsg_EstablishChannel(kClientId1
, false, false));
191 GpuChannel
*channel1
=
192 simple_client_
->gpu_channel_manager()->LookupChannel(kClientId1
);
193 simple_client_
->gpu_channel_manager()->OnMessageReceived(
194 GpuMsg_EstablishChannel(kClientId2
, false, false));
195 GpuChannel
*channel2
=
196 simple_client_
->gpu_channel_manager()->LookupChannel(kClientId2
);
197 ASSERT_TRUE(channel1
!= NULL
);
198 ASSERT_TRUE(channel2
!= NULL
);
199 ASSERT_NE(channel1
, channel2
);
201 // Make sure value states are only accessible by proper channels
202 simple_client_
->gpu_channel_manager()->OnMessageReceived(
203 GpuMsg_UpdateValueState(
204 kClientId1
, GL_MOUSE_POSITION_CHROMIUM
, value_state1
));
205 simple_client_
->gpu_channel_manager()->OnMessageReceived(
206 GpuMsg_UpdateValueState(
207 kClientId2
, GL_MOUSE_POSITION_CHROMIUM
, value_state2
));
209 const gpu::ValueStateMap
* pending_value_buffer_state1
=
210 channel1
->pending_valuebuffer_state();
211 const gpu::ValueStateMap
* pending_value_buffer_state2
=
212 channel2
->pending_valuebuffer_state();
213 ASSERT_NE(pending_value_buffer_state1
, pending_value_buffer_state2
);
215 const ValueState
* state1
=
216 pending_value_buffer_state1
->GetState(GL_MOUSE_POSITION_CHROMIUM
);
217 const ValueState
* state2
=
218 pending_value_buffer_state2
->GetState(GL_MOUSE_POSITION_CHROMIUM
);
219 ASSERT_NE(state1
, state2
);
221 ASSERT_EQ(state1
->int_value
[0], value_state1
.int_value
[0]);
222 ASSERT_EQ(state2
->int_value
[0], value_state2
.int_value
[0]);
223 ASSERT_NE(state1
->int_value
[0], state2
->int_value
[0]);
226 } // namespace content