Refactor android test results logging.
[chromium-blink-merge.git] / ppapi / proxy / ppapi_proxy_test.cc
blob5f38908358ae8ad5ef00a6ce82643bd842195834
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/compiler_specific.h"
11 #include "base/message_loop_proxy.h"
12 #include "base/observer_list.h"
13 #include "base/process_util.h"
14 #include "ipc/ipc_sync_channel.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/private/ppb_proxy_private.h"
17 #include "ppapi/proxy/ppapi_messages.h"
19 namespace ppapi {
20 namespace proxy {
22 namespace {
23 // HostDispatcher requires a PPB_Proxy_Private, so we always provide a fallback
24 // do-nothing implementation.
25 void PluginCrashed(PP_Module module) {
26 NOTREACHED();
29 PP_Instance GetInstanceForResource(PP_Resource resource) {
30 // If a test relies on this, we need to implement it.
31 NOTREACHED();
32 return 0;
35 void SetReserveInstanceIDCallback(PP_Module module,
36 PP_Bool (*is_seen)(PP_Module, PP_Instance)) {
37 // This function gets called in HostDispatcher's constructor. We simply don't
38 // worry about Instance uniqueness in tests, so we can ignore the call.
41 int32_t GetURLLoaderBufferedBytes(PP_Resource url_loader) {
42 NOTREACHED();
43 return 0;
46 void AddRefModule(PP_Module module) {}
47 void ReleaseModule(PP_Module module) {}
48 PP_Bool IsInModuleDestructor(PP_Module module) { return PP_FALSE; }
50 PPB_Proxy_Private ppb_proxy_private = {
51 &PluginCrashed,
52 &GetInstanceForResource,
53 &SetReserveInstanceIDCallback,
54 &GetURLLoaderBufferedBytes,
55 &AddRefModule,
56 &ReleaseModule,
57 &IsInModuleDestructor
60 // We allow multiple harnesses at a time to respond to 'GetInterface' calls.
61 // We assume that only 1 harness's GetInterface function will ever support a
62 // given interface name. In practice, there will either be only 1 GetInterface
63 // handler (for PluginProxyTest or HostProxyTest), or there will be only 2
64 // GetInterface handlers (for TwoWayTest). In the latter case, one handler is
65 // for the PluginProxyTestHarness and should only respond for PPP interfaces,
66 // and the other handler is for the HostProxyTestHarness which should only
67 // ever respond for PPB interfaces.
68 ObserverList<ProxyTestHarnessBase> get_interface_handlers_;
70 const void* MockGetInterface(const char* name) {
71 ObserverList<ProxyTestHarnessBase>::Iterator it =
72 get_interface_handlers_;
73 while (ProxyTestHarnessBase* observer = it.GetNext()) {
74 const void* interface = observer->GetInterface(name);
75 if (interface)
76 return interface;
78 if (strcmp(name, PPB_PROXY_PRIVATE_INTERFACE) == 0)
79 return &ppb_proxy_private;
80 return NULL;
83 void SetUpRemoteHarness(ProxyTestHarnessBase* harness,
84 const IPC::ChannelHandle& handle,
85 base::MessageLoopProxy* ipc_message_loop_proxy,
86 base::WaitableEvent* shutdown_event,
87 base::WaitableEvent* harness_set_up) {
88 harness->SetUpHarnessWithChannel(handle, ipc_message_loop_proxy,
89 shutdown_event, false);
90 harness_set_up->Signal();
93 void TearDownRemoteHarness(ProxyTestHarnessBase* harness,
94 base::WaitableEvent* harness_torn_down) {
95 harness->TearDownHarness();
96 harness_torn_down->Signal();
99 void RunTaskOnRemoteHarness(const base::Closure& task,
100 base::WaitableEvent* task_complete) {
101 task.Run();
102 task_complete->Signal();
105 } // namespace
107 // ProxyTestHarnessBase --------------------------------------------------------
109 ProxyTestHarnessBase::ProxyTestHarnessBase() : pp_module_(0x98765),
110 pp_instance_(0x12345) {
111 get_interface_handlers_.AddObserver(this);
114 ProxyTestHarnessBase::~ProxyTestHarnessBase() {
115 get_interface_handlers_.RemoveObserver(this);
118 const void* ProxyTestHarnessBase::GetInterface(const char* name) {
119 return registered_interfaces_[name];
122 void ProxyTestHarnessBase::RegisterTestInterface(const char* name,
123 const void* test_interface) {
124 registered_interfaces_[name] = test_interface;
127 bool ProxyTestHarnessBase::SupportsInterface(const char* name) {
128 sink().ClearMessages();
130 // IPC doesn't actually write to this when we send a message manually
131 // not actually using IPC.
132 bool unused_result = false;
133 PpapiMsg_SupportsInterface msg(name, &unused_result);
134 GetDispatcher()->OnMessageReceived(msg);
136 const IPC::Message* reply_msg =
137 sink().GetUniqueMessageMatching(IPC_REPLY_ID);
138 EXPECT_TRUE(reply_msg);
139 if (!reply_msg)
140 return false;
142 TupleTypes<PpapiMsg_SupportsInterface::ReplyParam>::ValueTuple reply_data;
143 EXPECT_TRUE(PpapiMsg_SupportsInterface::ReadReplyParam(
144 reply_msg, &reply_data));
146 sink().ClearMessages();
147 return reply_data.a;
150 // PluginProxyTestHarness ------------------------------------------------------
152 PluginProxyTestHarness::PluginProxyTestHarness() {
155 PluginProxyTestHarness::~PluginProxyTestHarness() {
158 PpapiGlobals* PluginProxyTestHarness::GetGlobals() {
159 return plugin_globals_.get();
162 Dispatcher* PluginProxyTestHarness::GetDispatcher() {
163 return plugin_dispatcher_.get();
166 void PluginProxyTestHarness::SetUpHarness() {
167 plugin_globals_.reset(new PluginGlobals(PpapiGlobals::ForTest()));
169 // These must be first since the dispatcher set-up uses them.
170 PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
171 resource_tracker().DidCreateInstance(pp_instance());
173 plugin_dispatcher_.reset(new PluginDispatcher(
174 &MockGetInterface,
175 PpapiPermissions(),
176 false));
177 plugin_dispatcher_->InitWithTestSink(&sink());
178 // The plugin proxy delegate is needed for
179 // |PluginProxyDelegate::GetBrowserSender| which is used
180 // in |ResourceCreationProxy::GetConnection| to get the channel to the
181 // browser. In this case we just use the |plugin_dispatcher_| as the channel
182 // for test purposes.
183 plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
184 PluginGlobals::Get()->set_plugin_proxy_delegate(&plugin_delegate_mock_);
185 plugin_dispatcher_->DidCreateInstance(pp_instance());
188 void PluginProxyTestHarness::SetUpHarnessWithChannel(
189 const IPC::ChannelHandle& channel_handle,
190 base::MessageLoopProxy* ipc_message_loop,
191 base::WaitableEvent* shutdown_event,
192 bool is_client) {
193 plugin_globals_.reset(new PluginGlobals(PpapiGlobals::ForTest()));
195 // These must be first since the dispatcher set-up uses them.
196 PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
197 resource_tracker().DidCreateInstance(pp_instance());
198 plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event);
200 plugin_dispatcher_.reset(new PluginDispatcher(
201 &MockGetInterface,
202 PpapiPermissions(),
203 false));
204 plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_,
205 channel_handle,
206 is_client);
207 plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
208 PluginGlobals::Get()->set_plugin_proxy_delegate(&plugin_delegate_mock_);
209 plugin_dispatcher_->DidCreateInstance(pp_instance());
212 void PluginProxyTestHarness::TearDownHarness() {
213 plugin_dispatcher_->DidDestroyInstance(pp_instance());
214 plugin_dispatcher_.reset();
216 resource_tracker().DidDeleteInstance(pp_instance());
217 plugin_globals_.reset();
220 base::MessageLoopProxy*
221 PluginProxyTestHarness::PluginDelegateMock::GetIPCMessageLoop() {
222 return ipc_message_loop_;
225 base::WaitableEvent*
226 PluginProxyTestHarness::PluginDelegateMock::GetShutdownEvent() {
227 return shutdown_event_;
230 IPC::PlatformFileForTransit
231 PluginProxyTestHarness::PluginDelegateMock::ShareHandleWithRemote(
232 base::PlatformFile handle,
233 const IPC::SyncChannel& /* channel */,
234 bool should_close_source) {
235 return IPC::GetFileHandleForProcess(handle,
236 base::Process::Current().handle(),
237 should_close_source);
240 std::set<PP_Instance>*
241 PluginProxyTestHarness::PluginDelegateMock::GetGloballySeenInstanceIDSet() {
242 return &instance_id_set_;
245 uint32 PluginProxyTestHarness::PluginDelegateMock::Register(
246 PluginDispatcher* plugin_dispatcher) {
247 return 0;
250 void PluginProxyTestHarness::PluginDelegateMock::Unregister(
251 uint32 plugin_dispatcher_id) {
254 IPC::Sender* PluginProxyTestHarness::PluginDelegateMock::GetBrowserSender() {
255 return browser_sender_;
258 std::string PluginProxyTestHarness::PluginDelegateMock::GetUILanguage() {
259 return std::string("en-US");
262 void PluginProxyTestHarness::PluginDelegateMock::PreCacheFont(
263 const void* logfontw) {
266 void PluginProxyTestHarness::PluginDelegateMock::SetActiveURL(
267 const std::string& url) {
270 // PluginProxyTest -------------------------------------------------------------
272 PluginProxyTest::PluginProxyTest() {
275 PluginProxyTest::~PluginProxyTest() {
278 void PluginProxyTest::SetUp() {
279 SetUpHarness();
282 void PluginProxyTest::TearDown() {
283 TearDownHarness();
286 // HostProxyTestHarness --------------------------------------------------------
288 class HostProxyTestHarness::MockSyncMessageStatusReceiver
289 : public HostDispatcher::SyncMessageStatusReceiver {
290 public:
291 virtual void BeginBlockOnSyncMessage() OVERRIDE {}
292 virtual void EndBlockOnSyncMessage() OVERRIDE {}
295 HostProxyTestHarness::HostProxyTestHarness()
296 : status_receiver_(new MockSyncMessageStatusReceiver) {
299 HostProxyTestHarness::~HostProxyTestHarness() {
302 PpapiGlobals* HostProxyTestHarness::GetGlobals() {
303 return host_globals_.get();
306 Dispatcher* HostProxyTestHarness::GetDispatcher() {
307 return host_dispatcher_.get();
310 void HostProxyTestHarness::SetUpHarness() {
311 host_globals_.reset(new ppapi::TestGlobals(PpapiGlobals::ForTest()));
313 // These must be first since the dispatcher set-up uses them.
314 PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
315 host_dispatcher_.reset(new HostDispatcher(
316 pp_module(),
317 &MockGetInterface,
318 status_receiver_.release(),
319 PpapiPermissions::AllPermissions()));
320 host_dispatcher_->InitWithTestSink(&sink());
321 HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
324 void HostProxyTestHarness::SetUpHarnessWithChannel(
325 const IPC::ChannelHandle& channel_handle,
326 base::MessageLoopProxy* ipc_message_loop,
327 base::WaitableEvent* shutdown_event,
328 bool is_client) {
329 host_globals_.reset(new ppapi::TestGlobals(PpapiGlobals::ForTest()));
331 // These must be first since the dispatcher set-up uses them.
332 PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
333 delegate_mock_.Init(ipc_message_loop, shutdown_event);
335 host_dispatcher_.reset(new HostDispatcher(
336 pp_module(),
337 &MockGetInterface,
338 status_receiver_.release(),
339 PpapiPermissions::AllPermissions()));
340 ppapi::Preferences preferences;
341 host_dispatcher_->InitHostWithChannel(&delegate_mock_, channel_handle,
342 is_client, preferences);
343 HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
346 void HostProxyTestHarness::TearDownHarness() {
347 HostDispatcher::RemoveForInstance(pp_instance());
348 host_dispatcher_.reset();
349 host_globals_.reset();
352 base::MessageLoopProxy*
353 HostProxyTestHarness::DelegateMock::GetIPCMessageLoop() {
354 return ipc_message_loop_;
357 base::WaitableEvent* HostProxyTestHarness::DelegateMock::GetShutdownEvent() {
358 return shutdown_event_;
361 IPC::PlatformFileForTransit
362 HostProxyTestHarness::DelegateMock::ShareHandleWithRemote(
363 base::PlatformFile handle,
364 const IPC::SyncChannel& /* channel */,
365 bool should_close_source) {
366 return IPC::GetFileHandleForProcess(handle,
367 base::Process::Current().handle(),
368 should_close_source);
372 // HostProxyTest ---------------------------------------------------------------
374 HostProxyTest::HostProxyTest() {
377 HostProxyTest::~HostProxyTest() {
380 void HostProxyTest::SetUp() {
381 SetUpHarness();
384 void HostProxyTest::TearDown() {
385 TearDownHarness();
388 // TwoWayTest ---------------------------------------------------------------
390 TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode)
391 : test_mode_(test_mode),
392 io_thread_("TwoWayTest_IOThread"),
393 plugin_thread_("TwoWayTest_PluginThread"),
394 remote_harness_(NULL),
395 local_harness_(NULL),
396 channel_created_(true, false),
397 shutdown_event_(true, false) {
398 if (test_mode == TEST_PPP_INTERFACE) {
399 remote_harness_ = &plugin_;
400 local_harness_ = &host_;
401 } else {
402 remote_harness_ = &host_;
403 local_harness_ = &plugin_;
407 TwoWayTest::~TwoWayTest() {
408 shutdown_event_.Signal();
411 void TwoWayTest::SetUp() {
412 base::Thread::Options options;
413 options.message_loop_type = MessageLoop::TYPE_IO;
414 io_thread_.StartWithOptions(options);
415 plugin_thread_.Start();
417 // Construct the IPC handle name using the process ID so we can safely run
418 // multiple |TwoWayTest|s concurrently.
419 std::ostringstream handle_name;
420 handle_name << "TwoWayTestChannel" << base::GetCurrentProcId();
421 IPC::ChannelHandle handle(handle_name.str());
422 base::WaitableEvent remote_harness_set_up(true, false);
423 plugin_thread_.message_loop_proxy()->PostTask(
424 FROM_HERE,
425 base::Bind(&SetUpRemoteHarness,
426 remote_harness_,
427 handle,
428 io_thread_.message_loop_proxy(),
429 &shutdown_event_,
430 &remote_harness_set_up));
431 remote_harness_set_up.Wait();
432 local_harness_->SetUpHarnessWithChannel(handle,
433 io_thread_.message_loop_proxy(),
434 &shutdown_event_,
435 true); // is_client
438 void TwoWayTest::TearDown() {
439 base::WaitableEvent remote_harness_torn_down(true, false);
440 plugin_thread_.message_loop_proxy()->PostTask(
441 FROM_HERE,
442 base::Bind(&TearDownRemoteHarness,
443 remote_harness_,
444 &remote_harness_torn_down));
445 remote_harness_torn_down.Wait();
447 local_harness_->TearDownHarness();
449 io_thread_.Stop();
452 void TwoWayTest::PostTaskOnRemoteHarness(const base::Closure& task) {
453 base::WaitableEvent task_complete(true, false);
454 plugin_thread_.message_loop_proxy()->PostTask(FROM_HERE,
455 base::Bind(&RunTaskOnRemoteHarness,
456 task,
457 &task_complete));
458 task_complete.Wait();
462 } // namespace proxy
463 } // namespace ppapi