1 // Copyright (c) 2012 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.
8 #include "base/message_loop.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread.h"
12 #include "ppapi/c/pp_instance.h"
13 #include "ppapi/proxy/host_dispatcher.h"
14 #include "ppapi/proxy/plugin_dispatcher.h"
15 #include "ppapi/proxy/plugin_globals.h"
16 #include "ppapi/proxy/plugin_proxy_delegate.h"
17 #include "ppapi/proxy/plugin_resource_tracker.h"
18 #include "ppapi/proxy/plugin_var_tracker.h"
19 #include "ppapi/proxy/resource_message_test_sink.h"
20 #include "ppapi/shared_impl/test_globals.h"
21 #include "testing/gtest/include/gtest/gtest.h"
26 // Base class for plugin and host test harnesses. Tests will not use this
27 // directly. Instead, use the PluginProxyTest, HostProxyTest, or TwoWayTest.
28 class ProxyTestHarnessBase
{
30 ProxyTestHarnessBase();
31 virtual ~ProxyTestHarnessBase();
33 PP_Module
pp_module() const { return pp_module_
; }
34 PP_Instance
pp_instance() const { return pp_instance_
; }
35 ResourceMessageTestSink
& sink() { return sink_
; }
37 virtual PpapiGlobals
* GetGlobals() = 0;
38 // Returns either the plugin or host dispatcher, depending on the test.
39 virtual Dispatcher
* GetDispatcher() = 0;
41 // Set up the harness using an IPC::TestSink to capture messages.
42 virtual void SetUpHarness() = 0;
44 // Set up the harness using a real IPC channel.
45 virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle
& channel_handle
,
46 base::MessageLoopProxy
* ipc_message_loop
,
47 base::WaitableEvent
* shutdown_event
,
50 virtual void TearDownHarness() = 0;
52 // Implementation of GetInterface for the dispatcher. This will
53 // return NULL for all interfaces unless one is registered by calling
54 // RegisterTestInterface();
55 const void* GetInterface(const char* name
);
57 // Allows the test to specify an interface implementation for a given
58 // interface name. This will be returned when any of the proxy logic
59 // requests a local interface.
60 void RegisterTestInterface(const char* name
, const void* test_interface
);
62 // Sends a "supports interface" message to the current dispatcher and returns
63 // true if it's supported. This is just for the convenience of tests.
64 bool SupportsInterface(const char* name
);
67 // Destination for IPC messages sent by the test.
68 ResourceMessageTestSink sink_
;
70 // The module and instance ID associated with the plugin dispatcher.
72 PP_Instance pp_instance_
;
74 // Stores the data for GetInterface/RegisterTestInterface.
75 std::map
<std::string
, const void*> registered_interfaces_
;
78 // Test harness for the plugin side of the proxy.
79 class PluginProxyTestHarness
: public ProxyTestHarnessBase
{
81 PluginProxyTestHarness();
82 virtual ~PluginProxyTestHarness();
84 PluginDispatcher
* plugin_dispatcher() { return plugin_dispatcher_
.get(); }
85 PluginResourceTracker
& resource_tracker() {
86 return *plugin_globals_
->plugin_resource_tracker();
88 PluginVarTracker
& var_tracker() {
89 return *plugin_globals_
->plugin_var_tracker();
92 // ProxyTestHarnessBase implementation.
93 virtual PpapiGlobals
* GetGlobals();
94 virtual Dispatcher
* GetDispatcher();
95 virtual void SetUpHarness();
96 virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle
& channel_handle
,
97 base::MessageLoopProxy
* ipc_message_loop
,
98 base::WaitableEvent
* shutdown_event
,
100 virtual void TearDownHarness();
102 class PluginDelegateMock
: public PluginDispatcher::PluginDelegate
,
103 public PluginProxyDelegate
{
105 PluginDelegateMock() : ipc_message_loop_(NULL
), shutdown_event_() {}
106 virtual ~PluginDelegateMock() {}
108 void Init(base::MessageLoopProxy
* ipc_message_loop
,
109 base::WaitableEvent
* shutdown_event
) {
110 ipc_message_loop_
= ipc_message_loop
;
111 shutdown_event_
= shutdown_event
;
114 void set_browser_sender(IPC::Sender
* browser_sender
) {
115 browser_sender_
= browser_sender
;
118 // ProxyChannel::Delegate implementation.
119 virtual base::MessageLoopProxy
* GetIPCMessageLoop() OVERRIDE
;
120 virtual base::WaitableEvent
* GetShutdownEvent() OVERRIDE
;
121 virtual IPC::PlatformFileForTransit
ShareHandleWithRemote(
122 base::PlatformFile handle
,
123 const IPC::SyncChannel
& /* channel */,
124 bool should_close_source
) OVERRIDE
;
126 // PluginDispatcher::PluginDelegate implementation.
127 virtual std::set
<PP_Instance
>* GetGloballySeenInstanceIDSet() OVERRIDE
;
128 virtual uint32
Register(PluginDispatcher
* plugin_dispatcher
) OVERRIDE
;
129 virtual void Unregister(uint32 plugin_dispatcher_id
) OVERRIDE
;
131 // PluginProxyDelegate implementation.
132 virtual IPC::Sender
* GetBrowserSender() OVERRIDE
;
133 virtual std::string
GetUILanguage() OVERRIDE
;
134 virtual void PreCacheFont(const void* logfontw
) OVERRIDE
;
135 virtual void SetActiveURL(const std::string
& url
) OVERRIDE
;
138 base::MessageLoopProxy
* ipc_message_loop_
; // Weak
139 base::WaitableEvent
* shutdown_event_
; // Weak
140 std::set
<PP_Instance
> instance_id_set_
;
141 IPC::Sender
* browser_sender_
;
143 DISALLOW_COPY_AND_ASSIGN(PluginDelegateMock
);
147 scoped_ptr
<PluginGlobals
> plugin_globals_
;
149 scoped_ptr
<PluginDispatcher
> plugin_dispatcher_
;
150 PluginDelegateMock plugin_delegate_mock_
;
153 class PluginProxyTest
: public PluginProxyTestHarness
, public testing::Test
{
156 virtual ~PluginProxyTest();
158 // testing::Test implementation.
159 virtual void SetUp();
160 virtual void TearDown();
162 MessageLoop message_loop_
;
165 class HostProxyTestHarness
: public ProxyTestHarnessBase
{
167 HostProxyTestHarness();
168 virtual ~HostProxyTestHarness();
170 HostDispatcher
* host_dispatcher() { return host_dispatcher_
.get(); }
171 ResourceTracker
& resource_tracker() {
172 return *host_globals_
->GetResourceTracker();
174 VarTracker
& var_tracker() {
175 return *host_globals_
->GetVarTracker();
178 // ProxyTestBase implementation.
179 virtual PpapiGlobals
* GetGlobals();
180 virtual Dispatcher
* GetDispatcher();
181 virtual void SetUpHarness();
182 virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle
& channel_handle
,
183 base::MessageLoopProxy
* ipc_message_loop
,
184 base::WaitableEvent
* shutdown_event
,
186 virtual void TearDownHarness();
188 class DelegateMock
: public ProxyChannel::Delegate
{
190 DelegateMock() : ipc_message_loop_(NULL
), shutdown_event_(NULL
) {
192 virtual ~DelegateMock() {}
194 void Init(base::MessageLoopProxy
* ipc_message_loop
,
195 base::WaitableEvent
* shutdown_event
) {
196 ipc_message_loop_
= ipc_message_loop
;
197 shutdown_event_
= shutdown_event
;
200 // ProxyChannel::Delegate implementation.
201 virtual base::MessageLoopProxy
* GetIPCMessageLoop();
202 virtual base::WaitableEvent
* GetShutdownEvent();
203 virtual IPC::PlatformFileForTransit
ShareHandleWithRemote(
204 base::PlatformFile handle
,
205 const IPC::SyncChannel
& /* channel */,
206 bool should_close_source
) OVERRIDE
;
209 base::MessageLoopProxy
* ipc_message_loop_
; // Weak
210 base::WaitableEvent
* shutdown_event_
; // Weak
212 DISALLOW_COPY_AND_ASSIGN(DelegateMock
);
216 class MockSyncMessageStatusReceiver
;
218 scoped_ptr
<ppapi::TestGlobals
> host_globals_
;
219 scoped_ptr
<HostDispatcher
> host_dispatcher_
;
220 DelegateMock delegate_mock_
;
222 scoped_ptr
<MockSyncMessageStatusReceiver
> status_receiver_
;
225 class HostProxyTest
: public HostProxyTestHarness
, public testing::Test
{
228 virtual ~HostProxyTest();
230 // testing::Test implementation.
231 virtual void SetUp();
232 virtual void TearDown();
234 MessageLoop message_loop_
;
237 // Use this base class to test both sides of a proxy.
238 class TwoWayTest
: public testing::Test
{
240 enum TwoWayTestMode
{
244 TwoWayTest(TwoWayTestMode test_mode
);
245 virtual ~TwoWayTest();
247 HostProxyTestHarness
& host() { return host_
; }
248 PluginProxyTestHarness
& plugin() { return plugin_
; }
249 PP_Module
pp_module() const { return host_
.pp_module(); }
250 PP_Instance
pp_instance() const { return host_
.pp_instance(); }
251 TwoWayTestMode
test_mode() { return test_mode_
; }
253 // testing::Test implementation.
254 virtual void SetUp();
255 virtual void TearDown();
258 // Post a task to the thread where the remote harness lives. This
259 // is typically used to test the state of the var tracker on the plugin
260 // thread. This runs the task synchronously for convenience.
261 void PostTaskOnRemoteHarness(const base::Closure
& task
);
264 TwoWayTestMode test_mode_
;
265 HostProxyTestHarness host_
;
266 PluginProxyTestHarness plugin_
;
267 // In order to use sync IPC, we need to have an IO thread.
268 base::Thread io_thread_
;
269 // The plugin side of the proxy runs on its own thread.
270 base::Thread plugin_thread_
;
271 // The message loop for the main (host) thread.
272 MessageLoop message_loop_
;
274 // Aliases for the host and plugin harnesses; if we're testing a PPP
275 // interface, remote_harness will point to plugin_, and local_harness
276 // will point to host_. This makes it convenient when we're starting and
277 // stopping the harnesses.
278 ProxyTestHarnessBase
* remote_harness_
;
279 ProxyTestHarnessBase
* local_harness_
;
281 base::WaitableEvent channel_created_
;
282 base::WaitableEvent shutdown_event_
;
285 // Used during Gtests when you have a PP_Var that you want to EXPECT is equal
286 // to a certain constant string value:
288 // EXPECT_VAR_IS_STRING("foo", my_var);
289 #define EXPECT_VAR_IS_STRING(str, var) { \
290 StringVar* sv = StringVar::FromPPVar(var); \
293 EXPECT_EQ(str, sv->value()); \