Disable flaky AnimatedContentSamplerParameterizedTest.FrameTimestampsConvergeTowardsE...
[chromium-blink-merge.git] / ppapi / proxy / ppapi_proxy_test.cc
blobfdd16043515d1bf506a78238cb84746146e22bb9
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.
5 #include "ppapi/proxy/ppapi_proxy_test.h"
7 #include <sstream>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/observer_list.h"
13 #include "base/process/process_handle.h"
14 #include "base/run_loop.h"
15 #include "ipc/ipc_sync_channel.h"
16 #include "ipc/message_filter.h"
17 #include "ppapi/c/pp_errors.h"
18 #include "ppapi/c/private/ppb_proxy_private.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/proxy/ppb_message_loop_proxy.h"
22 namespace ppapi {
23 namespace proxy {
25 namespace {
26 // HostDispatcher requires a PPB_Proxy_Private, so we always provide a fallback
27 // do-nothing implementation.
28 void PluginCrashed(PP_Module module) {
29 NOTREACHED();
32 PP_Instance GetInstanceForResource(PP_Resource resource) {
33 // If a test relies on this, we need to implement it.
34 NOTREACHED();
35 return 0;
38 void SetReserveInstanceIDCallback(PP_Module module,
39 PP_Bool (*is_seen)(PP_Module, PP_Instance)) {
40 // This function gets called in HostDispatcher's constructor. We simply don't
41 // worry about Instance uniqueness in tests, so we can ignore the call.
44 void AddRefModule(PP_Module module) {}
45 void ReleaseModule(PP_Module module) {}
46 PP_Bool IsInModuleDestructor(PP_Module module) { return PP_FALSE; }
48 PPB_Proxy_Private ppb_proxy_private = {
49 &PluginCrashed,
50 &GetInstanceForResource,
51 &SetReserveInstanceIDCallback,
52 &AddRefModule,
53 &ReleaseModule,
54 &IsInModuleDestructor
57 // We allow multiple harnesses at a time to respond to 'GetInterface' calls.
58 // We assume that only 1 harness's GetInterface function will ever support a
59 // given interface name. In practice, there will either be only 1 GetInterface
60 // handler (for PluginProxyTest or HostProxyTest), or there will be only 2
61 // GetInterface handlers (for TwoWayTest). In the latter case, one handler is
62 // for the PluginProxyTestHarness and should only respond for PPP interfaces,
63 // and the other handler is for the HostProxyTestHarness which should only
64 // ever respond for PPB interfaces.
65 ObserverList<ProxyTestHarnessBase> get_interface_handlers_;
67 const void* MockGetInterface(const char* name) {
68 ObserverList<ProxyTestHarnessBase>::Iterator it(&get_interface_handlers_);
69 while (ProxyTestHarnessBase* observer = it.GetNext()) {
70 const void* interface = observer->GetInterface(name);
71 if (interface)
72 return interface;
74 if (strcmp(name, PPB_PROXY_PRIVATE_INTERFACE) == 0)
75 return &ppb_proxy_private;
76 return NULL;
79 void SetUpRemoteHarness(ProxyTestHarnessBase* harness,
80 const IPC::ChannelHandle& handle,
81 base::MessageLoopProxy* ipc_message_loop_proxy,
82 base::WaitableEvent* shutdown_event,
83 base::WaitableEvent* harness_set_up) {
84 harness->SetUpHarnessWithChannel(handle, ipc_message_loop_proxy,
85 shutdown_event, false);
86 harness_set_up->Signal();
89 void TearDownRemoteHarness(ProxyTestHarnessBase* harness,
90 base::WaitableEvent* harness_torn_down) {
91 harness->TearDownHarness();
92 harness_torn_down->Signal();
95 void RunTaskOnRemoteHarness(const base::Closure& task,
96 base::WaitableEvent* task_complete) {
97 task.Run();
98 task_complete->Signal();
101 } // namespace
103 // ProxyTestHarnessBase --------------------------------------------------------
105 ProxyTestHarnessBase::ProxyTestHarnessBase() : pp_module_(0x98765),
106 pp_instance_(0x12345) {
107 get_interface_handlers_.AddObserver(this);
110 ProxyTestHarnessBase::~ProxyTestHarnessBase() {
111 get_interface_handlers_.RemoveObserver(this);
114 const void* ProxyTestHarnessBase::GetInterface(const char* name) {
115 return registered_interfaces_[name];
118 void ProxyTestHarnessBase::RegisterTestInterface(const char* name,
119 const void* test_interface) {
120 registered_interfaces_[name] = test_interface;
123 bool ProxyTestHarnessBase::SupportsInterface(const char* name) {
124 sink().ClearMessages();
126 // IPC doesn't actually write to this when we send a message manually
127 // not actually using IPC.
128 bool unused_result = false;
129 PpapiMsg_SupportsInterface msg(name, &unused_result);
130 GetDispatcher()->OnMessageReceived(msg);
132 const IPC::Message* reply_msg =
133 sink().GetUniqueMessageMatching(IPC_REPLY_ID);
134 EXPECT_TRUE(reply_msg);
135 if (!reply_msg)
136 return false;
138 TupleTypes<PpapiMsg_SupportsInterface::ReplyParam>::ValueTuple reply_data;
139 EXPECT_TRUE(PpapiMsg_SupportsInterface::ReadReplyParam(
140 reply_msg, &reply_data));
142 sink().ClearMessages();
143 return get<0>(reply_data);
146 // PluginProxyTestHarness ------------------------------------------------------
148 PluginProxyTestHarness::PluginProxyTestHarness(
149 GlobalsConfiguration globals_config)
150 : globals_config_(globals_config) {
153 PluginProxyTestHarness::~PluginProxyTestHarness() {
156 PpapiGlobals* PluginProxyTestHarness::GetGlobals() {
157 return plugin_globals_.get();
160 Dispatcher* PluginProxyTestHarness::GetDispatcher() {
161 return plugin_dispatcher_.get();
164 void PluginProxyTestHarness::SetUpHarness() {
165 // These must be first since the dispatcher set-up uses them.
166 CreatePluginGlobals(nullptr /* ipc_task_runner */);
167 // Some of the methods called during set-up check that the lock is held.
168 ProxyAutoLock lock;
170 resource_tracker().DidCreateInstance(pp_instance());
172 plugin_dispatcher_.reset(new PluginDispatcher(
173 &MockGetInterface,
174 PpapiPermissions(),
175 false));
176 plugin_dispatcher_->InitWithTestSink(&sink());
177 // The plugin proxy delegate is needed for
178 // |PluginProxyDelegate::GetBrowserSender| which is used
179 // in |ResourceCreationProxy::GetConnection| to get the channel to the
180 // browser. In this case we just use the |plugin_dispatcher_| as the channel
181 // for test purposes.
182 plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
183 PluginGlobals::Get()->SetPluginProxyDelegate(&plugin_delegate_mock_);
184 plugin_dispatcher_->DidCreateInstance(pp_instance());
187 void PluginProxyTestHarness::SetUpHarnessWithChannel(
188 const IPC::ChannelHandle& channel_handle,
189 base::MessageLoopProxy* ipc_message_loop,
190 base::WaitableEvent* shutdown_event,
191 bool is_client) {
192 // These must be first since the dispatcher set-up uses them.
193 scoped_refptr<base::TaskRunner> ipc_task_runner(ipc_message_loop);
194 CreatePluginGlobals(ipc_message_loop);
195 // Some of the methods called during set-up check that the lock is held.
196 ProxyAutoLock lock;
198 resource_tracker().DidCreateInstance(pp_instance());
199 plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event);
201 plugin_dispatcher_.reset(new PluginDispatcher(
202 &MockGetInterface,
203 PpapiPermissions(),
204 false));
205 plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_,
206 base::kNullProcessId,
207 channel_handle,
208 is_client);
209 plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
210 PluginGlobals::Get()->SetPluginProxyDelegate(&plugin_delegate_mock_);
211 plugin_dispatcher_->DidCreateInstance(pp_instance());
214 void PluginProxyTestHarness::TearDownHarness() {
216 // Some of the methods called during tear-down check that the lock is held.
217 ProxyAutoLock lock;
219 plugin_dispatcher_->DidDestroyInstance(pp_instance());
220 plugin_dispatcher_.reset();
222 resource_tracker().DidDeleteInstance(pp_instance());
224 plugin_globals_.reset();
227 void PluginProxyTestHarness::CreatePluginGlobals(
228 const scoped_refptr<base::TaskRunner>& ipc_task_runner) {
229 if (globals_config_ == PER_THREAD_GLOBALS) {
230 plugin_globals_.reset(new PluginGlobals(PpapiGlobals::PerThreadForTest(),
231 ipc_task_runner));
232 PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
233 } else {
234 plugin_globals_.reset(new PluginGlobals(ipc_task_runner));
238 base::MessageLoopProxy*
239 PluginProxyTestHarness::PluginDelegateMock::GetIPCMessageLoop() {
240 return ipc_message_loop_;
243 base::WaitableEvent*
244 PluginProxyTestHarness::PluginDelegateMock::GetShutdownEvent() {
245 return shutdown_event_;
248 IPC::PlatformFileForTransit
249 PluginProxyTestHarness::PluginDelegateMock::ShareHandleWithRemote(
250 base::PlatformFile handle,
251 base::ProcessId /* remote_pid */,
252 bool should_close_source) {
253 return IPC::GetFileHandleForProcess(handle,
254 base::GetCurrentProcessHandle(),
255 should_close_source);
258 std::set<PP_Instance>*
259 PluginProxyTestHarness::PluginDelegateMock::GetGloballySeenInstanceIDSet() {
260 return &instance_id_set_;
263 uint32 PluginProxyTestHarness::PluginDelegateMock::Register(
264 PluginDispatcher* plugin_dispatcher) {
265 return 0;
268 void PluginProxyTestHarness::PluginDelegateMock::Unregister(
269 uint32 plugin_dispatcher_id) {
272 IPC::Sender* PluginProxyTestHarness::PluginDelegateMock::GetBrowserSender() {
273 return browser_sender_;
276 std::string PluginProxyTestHarness::PluginDelegateMock::GetUILanguage() {
277 return std::string("en-US");
280 void PluginProxyTestHarness::PluginDelegateMock::PreCacheFont(
281 const void* logfontw) {
284 void PluginProxyTestHarness::PluginDelegateMock::SetActiveURL(
285 const std::string& url) {
288 PP_Resource PluginProxyTestHarness::PluginDelegateMock::CreateBrowserFont(
289 Connection connection,
290 PP_Instance instance,
291 const PP_BrowserFont_Trusted_Description& desc,
292 const Preferences& prefs) {
293 return 0;
296 // PluginProxyTest -------------------------------------------------------------
298 PluginProxyTest::PluginProxyTest() : PluginProxyTestHarness(SINGLETON_GLOBALS) {
301 PluginProxyTest::~PluginProxyTest() {
304 void PluginProxyTest::SetUp() {
305 SetUpHarness();
308 void PluginProxyTest::TearDown() {
309 TearDownHarness();
312 // PluginProxyMultiThreadTest --------------------------------------------------
314 PluginProxyMultiThreadTest::PluginProxyMultiThreadTest() {
317 PluginProxyMultiThreadTest::~PluginProxyMultiThreadTest() {
320 void PluginProxyMultiThreadTest::RunTest() {
321 main_thread_message_loop_proxy_ =
322 PpapiGlobals::Get()->GetMainThreadMessageLoop();
323 ASSERT_EQ(main_thread_message_loop_proxy_.get(),
324 base::MessageLoopProxy::current().get());
325 nested_main_thread_message_loop_.reset(new base::RunLoop());
327 secondary_thread_.reset(new base::DelegateSimpleThread(
328 this, "PluginProxyMultiThreadTest"));
331 ProxyAutoLock auto_lock;
333 // MessageLoopResource assumes that the proxy lock has been acquired.
334 secondary_thread_message_loop_ = new MessageLoopResource(pp_instance());
336 ASSERT_EQ(PP_OK,
337 secondary_thread_message_loop_->PostWork(
338 PP_MakeCompletionCallback(
339 &PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread,
340 this),
341 0));
344 SetUpTestOnMainThread();
346 secondary_thread_->Start();
347 nested_main_thread_message_loop_->Run();
348 secondary_thread_->Join();
351 ProxyAutoLock auto_lock;
353 // The destruction requires a valid PpapiGlobals instance, so we should
354 // explicitly release it.
355 secondary_thread_message_loop_ = NULL;
358 secondary_thread_.reset(NULL);
359 nested_main_thread_message_loop_.reset(NULL);
360 main_thread_message_loop_proxy_ = NULL;
363 void PluginProxyMultiThreadTest::CheckOnThread(ThreadType thread_type) {
364 ProxyAutoLock auto_lock;
365 if (thread_type == MAIN_THREAD) {
366 ASSERT_TRUE(MessageLoopResource::GetCurrent()->is_main_thread_loop());
367 } else {
368 ASSERT_EQ(secondary_thread_message_loop_.get(),
369 MessageLoopResource::GetCurrent());
373 void PluginProxyMultiThreadTest::PostQuitForMainThread() {
374 main_thread_message_loop_proxy_->PostTask(
375 FROM_HERE,
376 base::Bind(&PluginProxyMultiThreadTest::QuitNestedLoop,
377 base::Unretained(this)));
380 void PluginProxyMultiThreadTest::PostQuitForSecondaryThread() {
381 ProxyAutoLock auto_lock;
382 secondary_thread_message_loop_->PostQuit(PP_TRUE);
385 void PluginProxyMultiThreadTest::Run() {
386 ProxyAutoLock auto_lock;
387 ASSERT_EQ(PP_OK, secondary_thread_message_loop_->AttachToCurrentThread());
388 ASSERT_EQ(PP_OK, secondary_thread_message_loop_->Run());
389 secondary_thread_message_loop_->DetachFromThread();
392 void PluginProxyMultiThreadTest::QuitNestedLoop() {
393 nested_main_thread_message_loop_->Quit();
396 // static
397 void PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread(
398 void* user_data,
399 int32_t result) {
400 EXPECT_EQ(PP_OK, result);
401 PluginProxyMultiThreadTest* thiz =
402 static_cast<PluginProxyMultiThreadTest*>(user_data);
403 thiz->CheckOnThread(SECONDARY_THREAD);
404 thiz->SetUpTestOnSecondaryThread();
407 // HostProxyTestHarness --------------------------------------------------------
409 HostProxyTestHarness::HostProxyTestHarness(GlobalsConfiguration globals_config)
410 : globals_config_(globals_config) {
413 HostProxyTestHarness::~HostProxyTestHarness() {
416 PpapiGlobals* HostProxyTestHarness::GetGlobals() {
417 return host_globals_.get();
420 Dispatcher* HostProxyTestHarness::GetDispatcher() {
421 return host_dispatcher_.get();
424 void HostProxyTestHarness::SetUpHarness() {
425 // These must be first since the dispatcher set-up uses them.
426 CreateHostGlobals();
428 host_dispatcher_.reset(new HostDispatcher(
429 pp_module(),
430 &MockGetInterface,
431 PpapiPermissions::AllPermissions()));
432 host_dispatcher_->InitWithTestSink(&sink());
433 HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
436 void HostProxyTestHarness::SetUpHarnessWithChannel(
437 const IPC::ChannelHandle& channel_handle,
438 base::MessageLoopProxy* ipc_message_loop,
439 base::WaitableEvent* shutdown_event,
440 bool is_client) {
441 // These must be first since the dispatcher set-up uses them.
442 CreateHostGlobals();
444 delegate_mock_.Init(ipc_message_loop, shutdown_event);
446 host_dispatcher_.reset(new HostDispatcher(
447 pp_module(),
448 &MockGetInterface,
449 PpapiPermissions::AllPermissions()));
450 ppapi::Preferences preferences;
451 host_dispatcher_->InitHostWithChannel(&delegate_mock_,
452 base::kNullProcessId, channel_handle,
453 is_client, preferences);
454 HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
457 void HostProxyTestHarness::TearDownHarness() {
458 HostDispatcher::RemoveForInstance(pp_instance());
459 host_dispatcher_.reset();
460 host_globals_.reset();
463 void HostProxyTestHarness::CreateHostGlobals() {
464 disable_locking_.reset(new ProxyLock::LockingDisablerForTest);
465 if (globals_config_ == PER_THREAD_GLOBALS) {
466 host_globals_.reset(new TestGlobals(PpapiGlobals::PerThreadForTest()));
467 PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
468 } else {
469 host_globals_.reset(new TestGlobals());
473 base::MessageLoopProxy*
474 HostProxyTestHarness::DelegateMock::GetIPCMessageLoop() {
475 return ipc_message_loop_;
478 base::WaitableEvent* HostProxyTestHarness::DelegateMock::GetShutdownEvent() {
479 return shutdown_event_;
482 IPC::PlatformFileForTransit
483 HostProxyTestHarness::DelegateMock::ShareHandleWithRemote(
484 base::PlatformFile handle,
485 base::ProcessId /* remote_pid */,
486 bool should_close_source) {
487 return IPC::GetFileHandleForProcess(handle,
488 base::GetCurrentProcessHandle(),
489 should_close_source);
493 // HostProxyTest ---------------------------------------------------------------
495 HostProxyTest::HostProxyTest() : HostProxyTestHarness(SINGLETON_GLOBALS) {
498 HostProxyTest::~HostProxyTest() {
501 void HostProxyTest::SetUp() {
502 SetUpHarness();
505 void HostProxyTest::TearDown() {
506 TearDownHarness();
509 // TwoWayTest ---------------------------------------------------------------
511 TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode)
512 : test_mode_(test_mode),
513 host_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
514 plugin_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
515 io_thread_("TwoWayTest_IOThread"),
516 plugin_thread_("TwoWayTest_PluginThread"),
517 remote_harness_(NULL),
518 local_harness_(NULL),
519 channel_created_(true, false),
520 shutdown_event_(true, false) {
521 if (test_mode == TEST_PPP_INTERFACE) {
522 remote_harness_ = &plugin_;
523 local_harness_ = &host_;
524 } else {
525 remote_harness_ = &host_;
526 local_harness_ = &plugin_;
530 TwoWayTest::~TwoWayTest() {
531 shutdown_event_.Signal();
534 void TwoWayTest::SetUp() {
535 base::Thread::Options options;
536 options.message_loop_type = base::MessageLoop::TYPE_IO;
537 io_thread_.StartWithOptions(options);
538 plugin_thread_.Start();
540 // Construct the IPC handle name using the process ID so we can safely run
541 // multiple |TwoWayTest|s concurrently.
542 std::ostringstream handle_name;
543 handle_name << "TwoWayTestChannel" << base::GetCurrentProcId();
544 IPC::ChannelHandle handle(handle_name.str());
545 base::WaitableEvent remote_harness_set_up(true, false);
546 plugin_thread_.message_loop_proxy()->PostTask(
547 FROM_HERE,
548 base::Bind(&SetUpRemoteHarness,
549 remote_harness_,
550 handle,
551 io_thread_.message_loop_proxy(),
552 &shutdown_event_,
553 &remote_harness_set_up));
554 remote_harness_set_up.Wait();
555 local_harness_->SetUpHarnessWithChannel(handle,
556 io_thread_.message_loop_proxy().get(),
557 &shutdown_event_,
558 true); // is_client
561 void TwoWayTest::TearDown() {
562 base::WaitableEvent remote_harness_torn_down(true, false);
563 plugin_thread_.message_loop_proxy()->PostTask(
564 FROM_HERE,
565 base::Bind(&TearDownRemoteHarness,
566 remote_harness_,
567 &remote_harness_torn_down));
568 remote_harness_torn_down.Wait();
570 local_harness_->TearDownHarness();
572 io_thread_.Stop();
575 void TwoWayTest::PostTaskOnRemoteHarness(const base::Closure& task) {
576 base::WaitableEvent task_complete(true, false);
577 plugin_thread_.message_loop_proxy()->PostTask(FROM_HERE,
578 base::Bind(&RunTaskOnRemoteHarness,
579 task,
580 &task_complete));
581 task_complete.Wait();
585 } // namespace proxy
586 } // namespace ppapi