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.
4
5#include <cstring>
6
7#include "base/synchronization/waitable_event.h"
8#include "ppapi/c/pp_var.h"
9#include "ppapi/c/ppb_var.h"
10#include "ppapi/c/ppp_messaging.h"
11#include "ppapi/proxy/ppapi_messages.h"
12#include "ppapi/proxy/ppapi_proxy_test.h"
13#include "ppapi/proxy/serialized_var.h"
14#include "ppapi/shared_impl/api_id.h"
15#include "ppapi/shared_impl/proxy_lock.h"
16#include "ppapi/shared_impl/var.h"
17
18namespace ppapi {
19namespace proxy {
20
21namespace {
22
23// This is a poor man's mock of PPP_Messaging using global variables. Eventually
24// we should generalize making PPAPI interface mocks by using IDL or macro/
25// template magic.
26PP_Instance received_instance;
27PP_Var received_var;
28base::WaitableEvent handle_message_called(false, false);
29
30void HandleMessage(PP_Instance instance, PP_Var message_data) {
31  received_instance = instance;
32  received_var = message_data;
33  handle_message_called.Signal();
34}
35
36// Clear all the 'received' values for our mock.  Call this before you expect
37// one of the functions to be invoked.
38void ResetReceived() {
39  received_instance = 0;
40  received_var.type = PP_VARTYPE_UNDEFINED;
41  received_var.value.as_id = 0;
42}
43
44PPP_Messaging ppp_messaging_mock = {
45  &HandleMessage
46};
47
48// CallHandleMessage does the host-side work to cause HandleMessage to be called
49// in the plugin side.
50void CallHandleMessage(Dispatcher* dispatcher,
51                       PP_Instance instance,
52                       PP_Var message) {
53  dispatcher->Send(new PpapiMsg_PPPMessaging_HandleMessage(
54      API_ID_PPP_MESSAGING,
55      instance,
56      SerializedVarSendInputShmem(dispatcher, message, instance)));
57}
58
59class PPP_Messaging_ProxyTest : public TwoWayTest {
60 public:
61  PPP_Messaging_ProxyTest()
62      : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) {
63    plugin().RegisterTestInterface(PPP_MESSAGING_INTERFACE,
64                                   &ppp_messaging_mock);
65  }
66};
67
68void CompareAndReleaseStringVar(PluginProxyTestHarness* plugin_harness,
69                                PP_Var received_var,
70                                const std::string& test_string) {
71  ProxyAutoLock lock;
72  Var* received_string = plugin_harness->var_tracker().GetVar(received_var);
73  ASSERT_TRUE(received_string);
74  ASSERT_TRUE(received_string->AsStringVar());
75  EXPECT_EQ(test_string, received_string->AsStringVar()->value());
76  // Now release the var, and the string should go away (because the ref
77  // count should be one).
78  plugin_harness->var_tracker().ReleaseVar(received_var);
79  EXPECT_FALSE(StringVar::FromPPVar(received_var));
80}
81
82}  // namespace
83
84TEST_F(PPP_Messaging_ProxyTest, SendMessages) {
85  PP_Instance expected_instance = pp_instance();
86  PP_Var expected_var = PP_MakeUndefined();
87  ResetReceived();
88  Dispatcher* host_dispatcher = host().GetDispatcher();
89  CallHandleMessage(host_dispatcher, expected_instance, expected_var);
90  handle_message_called.Wait();
91  EXPECT_EQ(expected_instance, received_instance);
92  EXPECT_EQ(expected_var.type, received_var.type);
93
94  expected_var = PP_MakeNull();
95  ResetReceived();
96  CallHandleMessage(host_dispatcher, expected_instance, expected_var);
97  handle_message_called.Wait();
98  EXPECT_EQ(expected_instance, received_instance);
99  EXPECT_EQ(expected_var.type, received_var.type);
100
101  expected_var = PP_MakeBool(PP_TRUE);
102  ResetReceived();
103  CallHandleMessage(host_dispatcher, expected_instance, expected_var);
104  handle_message_called.Wait();
105  EXPECT_EQ(expected_instance, received_instance);
106  EXPECT_EQ(expected_var.type, received_var.type);
107  EXPECT_EQ(expected_var.value.as_bool, received_var.value.as_bool);
108
109  expected_var = PP_MakeInt32(12345);
110  ResetReceived();
111  CallHandleMessage(host_dispatcher, expected_instance, expected_var);
112  handle_message_called.Wait();
113  EXPECT_EQ(expected_instance, received_instance);
114  EXPECT_EQ(expected_var.type, received_var.type);
115  EXPECT_EQ(expected_var.value.as_int, received_var.value.as_int);
116
117  expected_var = PP_MakeDouble(3.1415);
118  ResetReceived();
119  CallHandleMessage(host_dispatcher, expected_instance, expected_var);
120  handle_message_called.Wait();
121  EXPECT_EQ(expected_instance, received_instance);
122  EXPECT_EQ(expected_var.type, received_var.type);
123  EXPECT_EQ(expected_var.value.as_double, received_var.value.as_double);
124
125  const std::string kTestString("Hello world!");
126  expected_var = StringVar::StringToPPVar(kTestString);
127  ResetReceived();
128  CallHandleMessage(host_dispatcher, expected_instance, expected_var);
129  // Now release the var, and the string should go away (because the ref
130  // count should be one).
131  host().var_tracker().ReleaseVar(expected_var);
132  EXPECT_FALSE(StringVar::FromPPVar(expected_var));
133
134  handle_message_called.Wait();
135  EXPECT_EQ(expected_instance, received_instance);
136  EXPECT_EQ(expected_var.type, received_var.type);
137  PostTaskOnRemoteHarness(
138      base::Bind(CompareAndReleaseStringVar,
139                 &plugin(),
140                 received_var,
141                 kTestString));
142}
143
144}  // namespace proxy
145}  // namespace ppapi
146
147