blob: 670753ede63eed31d39760363a2c981573f6a894 [file] [log] [blame]
[email protected]73097562012-01-12 19:38:551// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]f24448db2011-01-27 20:40:392// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avie029c4132015-12-23 06:45:225#include <stdint.h>
6
[email protected]465faa22011-02-08 16:31:467#include <map>
dchengced92242016-04-07 00:00:128#include <memory>
[email protected]465faa22011-02-08 16:31:469#include <string>
10
[email protected]7ef6b79b2013-01-17 02:38:2411#include "base/compiler_specific.h"
avie029c4132015-12-23 06:45:2212#include "base/macros.h"
[email protected]7ef6b79b2013-01-17 02:38:2413#include "base/memory/ref_counted.h"
[email protected]912f3d6c2011-06-29 18:26:3614#include "base/synchronization/waitable_event.h"
dmichaelb11ca7b2015-04-02 16:59:4015#include "base/task_runner.h"
[email protected]7ef6b79b2013-01-17 02:38:2416#include "base/threading/simple_thread.h"
[email protected]912f3d6c2011-06-29 18:26:3617#include "base/threading/thread.h"
[email protected]f24448db2011-01-27 20:40:3918#include "ppapi/c/pp_instance.h"
[email protected]465faa22011-02-08 16:31:4619#include "ppapi/proxy/host_dispatcher.h"
[email protected]f24448db2011-01-27 20:40:3920#include "ppapi/proxy/plugin_dispatcher.h"
[email protected]794d83cd2011-10-20 19:09:2021#include "ppapi/proxy/plugin_globals.h"
[email protected]6fc87e02011-12-20 19:18:4522#include "ppapi/proxy/plugin_proxy_delegate.h"
[email protected]f24448db2011-01-27 20:40:3923#include "ppapi/proxy/plugin_resource_tracker.h"
24#include "ppapi/proxy/plugin_var_tracker.h"
[email protected]eccf80312012-07-14 15:43:4225#include "ppapi/proxy/resource_message_test_sink.h"
dmichaelbd96c1e2015-02-12 00:58:0826#include "ppapi/shared_impl/proxy_lock.h"
[email protected]73097562012-01-12 19:38:5527#include "ppapi/shared_impl/test_globals.h"
[email protected]f24448db2011-01-27 20:40:3928#include "testing/gtest/include/gtest/gtest.h"
29
[email protected]7ef6b79b2013-01-17 02:38:2430namespace base {
[email protected]7ef6b79b2013-01-17 02:38:2431class RunLoop;
skyostil23490d42015-06-12 12:54:2632class SingleThreadTaskRunner;
[email protected]7ef6b79b2013-01-17 02:38:2433}
34
[email protected]4d2efd22011-08-18 21:58:0235namespace ppapi {
[email protected]f24448db2011-01-27 20:40:3936namespace proxy {
37
[email protected]7ef6b79b2013-01-17 02:38:2438class MessageLoopResource;
39
[email protected]912f3d6c2011-06-29 18:26:3640// Base class for plugin and host test harnesses. Tests will not use this
41// directly. Instead, use the PluginProxyTest, HostProxyTest, or TwoWayTest.
42class ProxyTestHarnessBase {
[email protected]465faa22011-02-08 16:31:4643 public:
[email protected]7ef6b79b2013-01-17 02:38:2444 enum GlobalsConfiguration {
45 PER_THREAD_GLOBALS,
46 SINGLETON_GLOBALS
47 };
48
[email protected]912f3d6c2011-06-29 18:26:3649 ProxyTestHarnessBase();
50 virtual ~ProxyTestHarnessBase();
[email protected]465faa22011-02-08 16:31:4651
52 PP_Module pp_module() const { return pp_module_; }
53 PP_Instance pp_instance() const { return pp_instance_; }
[email protected]eccf80312012-07-14 15:43:4254 ResourceMessageTestSink& sink() { return sink_; }
[email protected]465faa22011-02-08 16:31:4655
[email protected]73097562012-01-12 19:38:5556 virtual PpapiGlobals* GetGlobals() = 0;
[email protected]465faa22011-02-08 16:31:4657 // Returns either the plugin or host dispatcher, depending on the test.
58 virtual Dispatcher* GetDispatcher() = 0;
59
[email protected]912f3d6c2011-06-29 18:26:3660 // Set up the harness using an IPC::TestSink to capture messages.
61 virtual void SetUpHarness() = 0;
62
63 // Set up the harness using a real IPC channel.
skyostil23490d42015-06-12 12:54:2664 virtual void SetUpHarnessWithChannel(
65 const IPC::ChannelHandle& channel_handle,
66 base::SingleThreadTaskRunner* ipc_task_runner,
67 base::WaitableEvent* shutdown_event,
68 bool is_client) = 0;
[email protected]912f3d6c2011-06-29 18:26:3669
70 virtual void TearDownHarness() = 0;
71
[email protected]465faa22011-02-08 16:31:4672 // Implementation of GetInterface for the dispatcher. This will
73 // return NULL for all interfaces unless one is registered by calling
74 // RegisterTestInterface();
75 const void* GetInterface(const char* name);
76
77 // Allows the test to specify an interface implementation for a given
78 // interface name. This will be returned when any of the proxy logic
79 // requests a local interface.
[email protected]99ff9932011-09-07 14:14:5480 void RegisterTestInterface(const char* name, const void* test_interface);
[email protected]465faa22011-02-08 16:31:4681
82 // Sends a "supports interface" message to the current dispatcher and returns
83 // true if it's supported. This is just for the convenience of tests.
kareng1c62eeb2014-11-08 16:35:0384 bool SupportsInterface(const char* name);
[email protected]465faa22011-02-08 16:31:4685
86 private:
87 // Destination for IPC messages sent by the test.
[email protected]eccf80312012-07-14 15:43:4288 ResourceMessageTestSink sink_;
[email protected]465faa22011-02-08 16:31:4689
90 // The module and instance ID associated with the plugin dispatcher.
91 PP_Module pp_module_;
92 PP_Instance pp_instance_;
93
94 // Stores the data for GetInterface/RegisterTestInterface.
95 std::map<std::string, const void*> registered_interfaces_;
96};
97
[email protected]f24448db2011-01-27 20:40:3998// Test harness for the plugin side of the proxy.
[email protected]912f3d6c2011-06-29 18:26:3699class PluginProxyTestHarness : public ProxyTestHarnessBase {
[email protected]f24448db2011-01-27 20:40:39100 public:
[email protected]7ef6b79b2013-01-17 02:38:24101 explicit PluginProxyTestHarness(GlobalsConfiguration globals_config);
[email protected]912f3d6c2011-06-29 18:26:36102 virtual ~PluginProxyTestHarness();
[email protected]f24448db2011-01-27 20:40:39103
104 PluginDispatcher* plugin_dispatcher() { return plugin_dispatcher_.get(); }
[email protected]794d83cd2011-10-20 19:09:20105 PluginResourceTracker& resource_tracker() {
[email protected]d57fd382012-09-19 00:55:42106 return *plugin_globals_->plugin_resource_tracker();
[email protected]794d83cd2011-10-20 19:09:20107 }
108 PluginVarTracker& var_tracker() {
[email protected]d57fd382012-09-19 00:55:42109 return *plugin_globals_->plugin_var_tracker();
[email protected]794d83cd2011-10-20 19:09:20110 }
[email protected]f24448db2011-01-27 20:40:39111
[email protected]912f3d6c2011-06-29 18:26:36112 // ProxyTestHarnessBase implementation.
[email protected]d57fd382012-09-19 00:55:42113 virtual PpapiGlobals* GetGlobals();
[email protected]465faa22011-02-08 16:31:46114 virtual Dispatcher* GetDispatcher();
[email protected]912f3d6c2011-06-29 18:26:36115 virtual void SetUpHarness();
skyostil23490d42015-06-12 12:54:26116 virtual void SetUpHarnessWithChannel(
117 const IPC::ChannelHandle& channel_handle,
118 base::SingleThreadTaskRunner* ipc_task_runner,
119 base::WaitableEvent* shutdown_event,
120 bool is_client);
[email protected]912f3d6c2011-06-29 18:26:36121 virtual void TearDownHarness();
[email protected]465faa22011-02-08 16:31:46122
[email protected]6fc87e02011-12-20 19:18:45123 class PluginDelegateMock : public PluginDispatcher::PluginDelegate,
124 public PluginProxyDelegate {
[email protected]912f3d6c2011-06-29 18:26:36125 public:
skyostil23490d42015-06-12 12:54:26126 PluginDelegateMock() : ipc_task_runner_(NULL), shutdown_event_() {}
nickb05b81d2015-04-23 14:00:50127 ~PluginDelegateMock() override {}
[email protected]912f3d6c2011-06-29 18:26:36128
skyostil23490d42015-06-12 12:54:26129 void Init(base::SingleThreadTaskRunner* ipc_task_runner,
[email protected]912f3d6c2011-06-29 18:26:36130 base::WaitableEvent* shutdown_event) {
skyostil23490d42015-06-12 12:54:26131 ipc_task_runner_ = ipc_task_runner;
[email protected]912f3d6c2011-06-29 18:26:36132 shutdown_event_ = shutdown_event;
133 }
134
[email protected]d57fd382012-09-19 00:55:42135 void set_browser_sender(IPC::Sender* browser_sender) {
136 browser_sender_ = browser_sender;
137 }
138
[email protected]912f3d6c2011-06-29 18:26:36139 // ProxyChannel::Delegate implementation.
skyostil12262cf2015-05-21 14:49:31140 base::SingleThreadTaskRunner* GetIPCTaskRunner() override;
nickb05b81d2015-04-23 14:00:50141 base::WaitableEvent* GetShutdownEvent() override;
142 IPC::PlatformFileForTransit ShareHandleWithRemote(
[email protected]f0ecb552012-05-11 22:09:11143 base::PlatformFile handle,
[email protected]108fd342013-01-04 20:46:54144 base::ProcessId remote_pid,
mostynb699af3c2014-10-06 18:03:34145 bool should_close_source) override;
erikchen4fc32d52015-06-02 02:16:38146 base::SharedMemoryHandle ShareSharedMemoryHandleWithRemote(
147 const base::SharedMemoryHandle& handle,
148 base::ProcessId remote_pid) override;
[email protected]912f3d6c2011-06-29 18:26:36149
150 // PluginDispatcher::PluginDelegate implementation.
nickb05b81d2015-04-23 14:00:50151 std::set<PP_Instance>* GetGloballySeenInstanceIDSet() override;
avie029c4132015-12-23 06:45:22152 uint32_t Register(PluginDispatcher* plugin_dispatcher) override;
153 void Unregister(uint32_t plugin_dispatcher_id) override;
[email protected]6fc87e02011-12-20 19:18:45154
[email protected]d57fd382012-09-19 00:55:42155 // PluginProxyDelegate implementation.
nickb05b81d2015-04-23 14:00:50156 IPC::Sender* GetBrowserSender() override;
157 std::string GetUILanguage() override;
mgiuca8ca59182015-07-08 02:10:21158 void PreCacheFontForFlash(const void* logfontw) override;
nickb05b81d2015-04-23 14:00:50159 void SetActiveURL(const std::string& url) override;
160 PP_Resource CreateBrowserFont(
[email protected]1d148062013-07-25 20:25:45161 Connection connection,
162 PP_Instance instance,
163 const PP_BrowserFont_Trusted_Description& desc,
mostynb699af3c2014-10-06 18:03:34164 const Preferences& prefs) override;
[email protected]912f3d6c2011-06-29 18:26:36165
166 private:
skyostil23490d42015-06-12 12:54:26167 base::SingleThreadTaskRunner* ipc_task_runner_; // Weak
[email protected]912f3d6c2011-06-29 18:26:36168 base::WaitableEvent* shutdown_event_; // Weak
169 std::set<PP_Instance> instance_id_set_;
[email protected]d57fd382012-09-19 00:55:42170 IPC::Sender* browser_sender_;
[email protected]912f3d6c2011-06-29 18:26:36171
172 DISALLOW_COPY_AND_ASSIGN(PluginDelegateMock);
173 };
[email protected]f24448db2011-01-27 20:40:39174
175 private:
dmichaelb11ca7b2015-04-02 16:59:40176 void CreatePluginGlobals(
177 const scoped_refptr<base::TaskRunner>& ipc_task_runner);
[email protected]7ef6b79b2013-01-17 02:38:24178
179 GlobalsConfiguration globals_config_;
dchengced92242016-04-07 00:00:12180 std::unique_ptr<PluginGlobals> plugin_globals_;
[email protected]794d83cd2011-10-20 19:09:20181
dchengced92242016-04-07 00:00:12182 std::unique_ptr<PluginDispatcher> plugin_dispatcher_;
[email protected]912f3d6c2011-06-29 18:26:36183 PluginDelegateMock plugin_delegate_mock_;
[email protected]465faa22011-02-08 16:31:46184};
[email protected]f24448db2011-01-27 20:40:39185
[email protected]912f3d6c2011-06-29 18:26:36186class PluginProxyTest : public PluginProxyTestHarness, public testing::Test {
[email protected]465faa22011-02-08 16:31:46187 public:
[email protected]912f3d6c2011-06-29 18:26:36188 PluginProxyTest();
189 virtual ~PluginProxyTest();
190
191 // testing::Test implementation.
192 virtual void SetUp();
193 virtual void TearDown();
[email protected]657f4ef2011-07-14 16:39:23194 private:
[email protected]d2881d82013-05-06 19:23:08195 base::MessageLoop message_loop_;
[email protected]912f3d6c2011-06-29 18:26:36196};
197
[email protected]7ef6b79b2013-01-17 02:38:24198// This class provides support for multi-thread testing. A secondary thread is
199// created with a Pepper message loop.
200// Subclasses need to implement the two SetUpTestOn*Thread() methods to do the
201// actual testing work; and call both PostQuitFor*Thread() when testing is
202// done.
203class PluginProxyMultiThreadTest
204 : public PluginProxyTest,
205 public base::DelegateSimpleThread::Delegate {
206 public:
207 PluginProxyMultiThreadTest();
nickb05b81d2015-04-23 14:00:50208 ~PluginProxyMultiThreadTest() override;
[email protected]7ef6b79b2013-01-17 02:38:24209
210 // Called before the secondary thread is started, but after all the member
211 // variables, including |secondary_thread_| and
212 // |secondary_thread_message_loop_|, are initialized.
213 virtual void SetUpTestOnMainThread() = 0;
214
215 virtual void SetUpTestOnSecondaryThread() = 0;
216
217 // TEST_F() should call this method.
218 void RunTest();
219
220 enum ThreadType {
221 MAIN_THREAD,
222 SECONDARY_THREAD
223 };
224 void CheckOnThread(ThreadType thread_type);
225
226 // These can be called on any thread.
227 void PostQuitForMainThread();
228 void PostQuitForSecondaryThread();
229
230 protected:
231 scoped_refptr<MessageLoopResource> secondary_thread_message_loop_;
skyostil23490d42015-06-12 12:54:26232 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
[email protected]7ef6b79b2013-01-17 02:38:24233
234 private:
235 // base::DelegateSimpleThread::Delegate implementation.
nickb05b81d2015-04-23 14:00:50236 void Run() override;
[email protected]7ef6b79b2013-01-17 02:38:24237
238 void QuitNestedLoop();
239
240 static void InternalSetUpTestOnSecondaryThread(void* user_data,
241 int32_t result);
242
dchengced92242016-04-07 00:00:12243 std::unique_ptr<base::DelegateSimpleThread> secondary_thread_;
244 std::unique_ptr<base::RunLoop> nested_main_thread_message_loop_;
[email protected]7ef6b79b2013-01-17 02:38:24245};
246
[email protected]912f3d6c2011-06-29 18:26:36247class HostProxyTestHarness : public ProxyTestHarnessBase {
248 public:
[email protected]7ef6b79b2013-01-17 02:38:24249 explicit HostProxyTestHarness(GlobalsConfiguration globals_config);
[email protected]912f3d6c2011-06-29 18:26:36250 virtual ~HostProxyTestHarness();
[email protected]465faa22011-02-08 16:31:46251
252 HostDispatcher* host_dispatcher() { return host_dispatcher_.get(); }
[email protected]73097562012-01-12 19:38:55253 ResourceTracker& resource_tracker() {
[email protected]d57fd382012-09-19 00:55:42254 return *host_globals_->GetResourceTracker();
[email protected]73097562012-01-12 19:38:55255 }
256 VarTracker& var_tracker() {
[email protected]d57fd382012-09-19 00:55:42257 return *host_globals_->GetVarTracker();
[email protected]73097562012-01-12 19:38:55258 }
[email protected]465faa22011-02-08 16:31:46259
260 // ProxyTestBase implementation.
[email protected]d57fd382012-09-19 00:55:42261 virtual PpapiGlobals* GetGlobals();
[email protected]465faa22011-02-08 16:31:46262 virtual Dispatcher* GetDispatcher();
[email protected]912f3d6c2011-06-29 18:26:36263 virtual void SetUpHarness();
skyostil23490d42015-06-12 12:54:26264 virtual void SetUpHarnessWithChannel(
265 const IPC::ChannelHandle& channel_handle,
266 base::SingleThreadTaskRunner* ipc_task_runner,
267 base::WaitableEvent* shutdown_event,
268 bool is_client);
[email protected]912f3d6c2011-06-29 18:26:36269 virtual void TearDownHarness();
270
271 class DelegateMock : public ProxyChannel::Delegate {
272 public:
skyostil23490d42015-06-12 12:54:26273 DelegateMock() : ipc_task_runner_(NULL), shutdown_event_(NULL) {}
nickb05b81d2015-04-23 14:00:50274 ~DelegateMock() override {}
[email protected]912f3d6c2011-06-29 18:26:36275
skyostil23490d42015-06-12 12:54:26276 void Init(base::SingleThreadTaskRunner* ipc_task_runner,
[email protected]912f3d6c2011-06-29 18:26:36277 base::WaitableEvent* shutdown_event) {
skyostil23490d42015-06-12 12:54:26278 ipc_task_runner_ = ipc_task_runner;
[email protected]912f3d6c2011-06-29 18:26:36279 shutdown_event_ = shutdown_event;
280 }
281
282 // ProxyChannel::Delegate implementation.
skyostil23490d42015-06-12 12:54:26283 base::SingleThreadTaskRunner* GetIPCTaskRunner() override;
nickb05b81d2015-04-23 14:00:50284 base::WaitableEvent* GetShutdownEvent() override;
285 IPC::PlatformFileForTransit ShareHandleWithRemote(
[email protected]f0ecb552012-05-11 22:09:11286 base::PlatformFile handle,
[email protected]108fd342013-01-04 20:46:54287 base::ProcessId remote_pid,
mostynb699af3c2014-10-06 18:03:34288 bool should_close_source) override;
erikchen4fc32d52015-06-02 02:16:38289 base::SharedMemoryHandle ShareSharedMemoryHandleWithRemote(
290 const base::SharedMemoryHandle& handle,
291 base::ProcessId remote_pid) override;
[email protected]912f3d6c2011-06-29 18:26:36292
293 private:
skyostil23490d42015-06-12 12:54:26294 base::SingleThreadTaskRunner* ipc_task_runner_; // Weak
[email protected]912f3d6c2011-06-29 18:26:36295 base::WaitableEvent* shutdown_event_; // Weak
296
297 DISALLOW_COPY_AND_ASSIGN(DelegateMock);
298 };
299
300 private:
[email protected]7ef6b79b2013-01-17 02:38:24301 void CreateHostGlobals();
302
303 GlobalsConfiguration globals_config_;
dchengced92242016-04-07 00:00:12304 std::unique_ptr<ppapi::TestGlobals> host_globals_;
305 std::unique_ptr<HostDispatcher> host_dispatcher_;
dmichaelbd96c1e2015-02-12 00:58:08306 // The host side of the real proxy doesn't lock, so this disables locking for
307 // the thread the host side of the test runs on.
dchengced92242016-04-07 00:00:12308 std::unique_ptr<ProxyLock::LockingDisablerForTest> disable_locking_;
[email protected]912f3d6c2011-06-29 18:26:36309 DelegateMock delegate_mock_;
310};
311
312class HostProxyTest : public HostProxyTestHarness, public testing::Test {
313 public:
314 HostProxyTest();
315 virtual ~HostProxyTest();
316
317 // testing::Test implementation.
318 virtual void SetUp();
319 virtual void TearDown();
[email protected]657f4ef2011-07-14 16:39:23320 private:
[email protected]d2881d82013-05-06 19:23:08321 base::MessageLoop message_loop_;
[email protected]912f3d6c2011-06-29 18:26:36322};
323
324// Use this base class to test both sides of a proxy.
325class TwoWayTest : public testing::Test {
326 public:
327 enum TwoWayTestMode {
328 TEST_PPP_INTERFACE,
329 TEST_PPB_INTERFACE
330 };
331 TwoWayTest(TwoWayTestMode test_mode);
332 virtual ~TwoWayTest();
333
334 HostProxyTestHarness& host() { return host_; }
335 PluginProxyTestHarness& plugin() { return plugin_; }
336 PP_Module pp_module() const { return host_.pp_module(); }
337 PP_Instance pp_instance() const { return host_.pp_instance(); }
338 TwoWayTestMode test_mode() { return test_mode_; }
[email protected]465faa22011-02-08 16:31:46339
340 // testing::Test implementation.
341 virtual void SetUp();
342 virtual void TearDown();
343
[email protected]d57fd382012-09-19 00:55:42344 protected:
345 // Post a task to the thread where the remote harness lives. This
346 // is typically used to test the state of the var tracker on the plugin
347 // thread. This runs the task synchronously for convenience.
348 void PostTaskOnRemoteHarness(const base::Closure& task);
349
[email protected]465faa22011-02-08 16:31:46350 private:
[email protected]912f3d6c2011-06-29 18:26:36351 TwoWayTestMode test_mode_;
352 HostProxyTestHarness host_;
353 PluginProxyTestHarness plugin_;
354 // In order to use sync IPC, we need to have an IO thread.
355 base::Thread io_thread_;
356 // The plugin side of the proxy runs on its own thread.
357 base::Thread plugin_thread_;
358 // The message loop for the main (host) thread.
[email protected]d2881d82013-05-06 19:23:08359 base::MessageLoop message_loop_;
[email protected]912f3d6c2011-06-29 18:26:36360
361 // Aliases for the host and plugin harnesses; if we're testing a PPP
362 // interface, remote_harness will point to plugin_, and local_harness
363 // will point to host_. This makes it convenient when we're starting and
364 // stopping the harnesses.
365 ProxyTestHarnessBase* remote_harness_;
366 ProxyTestHarnessBase* local_harness_;
367
368 base::WaitableEvent channel_created_;
369 base::WaitableEvent shutdown_event_;
[email protected]f24448db2011-01-27 20:40:39370};
371
[email protected]eccf80312012-07-14 15:43:42372// Used during Gtests when you have a PP_Var that you want to EXPECT is equal
373// to a certain constant string value:
374//
375// EXPECT_VAR_IS_STRING("foo", my_var);
376#define EXPECT_VAR_IS_STRING(str, var) { \
377 StringVar* sv = StringVar::FromPPVar(var); \
378 EXPECT_TRUE(sv); \
379 if (sv) \
380 EXPECT_EQ(str, sv->value()); \
381}
382
[email protected]f24448db2011-01-27 20:40:39383} // namespace proxy
[email protected]4d2efd22011-08-18 21:58:02384} // namespace ppapi