OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/proxy/ppapi_proxy_test.h" | 5 #include "ppapi/proxy/ppapi_proxy_test.h" |
6 | 6 |
7 #include "ppapi/proxy/serialized_var.h" | 7 #include "ppapi/proxy/serialized_var.h" |
8 | 8 |
9 namespace ppapi { | 9 namespace ppapi { |
10 namespace proxy { | 10 namespace proxy { |
11 | 11 |
12 namespace { | 12 namespace { |
13 | 13 |
14 PP_Var MakeStringVar(int64_t string_id) { | |
15 PP_Var ret; | |
16 ret.type = PP_VARTYPE_STRING; | |
17 ret.value.as_id = string_id; | |
18 return ret; | |
19 } | |
20 | |
21 PP_Var MakeObjectVar(int64_t object_id) { | 14 PP_Var MakeObjectVar(int64_t object_id) { |
22 PP_Var ret; | 15 PP_Var ret; |
23 ret.type = PP_VARTYPE_OBJECT; | 16 ret.type = PP_VARTYPE_OBJECT; |
24 ret.value.as_id = object_id; | 17 ret.value.as_id = object_id; |
25 return ret; | 18 return ret; |
26 } | 19 } |
27 | 20 |
28 class SerializedVarTest : public PluginProxyTest { | 21 class SerializedVarTest : public PluginProxyTest { |
29 public: | 22 public: |
30 SerializedVarTest() {} | 23 SerializedVarTest() {} |
31 }; | 24 }; |
32 | 25 |
33 } // namespace | 26 } // namespace |
34 | 27 |
35 // Tests output arguments in the plugin. This is when the host calls into the | 28 // Tests output arguments in the plugin. This is when the host calls into the |
36 // plugin and the plugin returns something via an out param, like an exception. | 29 // plugin and the plugin returns something via an out param, like an exception. |
| 30 TEST_F(SerializedVarTest, PluginSerializedVarInOutParam) { |
| 31 PP_Var host_object = MakeObjectVar(0x31337); |
| 32 |
| 33 PP_Var plugin_object; |
| 34 { |
| 35 // Receive the object param, we should be tracking it with no refcount, and |
| 36 // no messages sent. |
| 37 SerializedVarTestConstructor input(host_object); |
| 38 SerializedVarReceiveInput receive_input(input); |
| 39 plugin_object = receive_input.Get(plugin_dispatcher()); |
| 40 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object)); |
| 41 EXPECT_EQ(0u, sink().message_count()); |
| 42 |
| 43 SerializedVar sv; |
| 44 { |
| 45 // The "OutParam" does its work in its destructor, it will write the |
| 46 // information to the SerializedVar we passed in the constructor. |
| 47 SerializedVarOutParam out_param(&sv); |
| 48 // An out-param needs to pass a reference to the caller, so it's the |
| 49 // responsibility of the plugin to bump the ref-count on an input |
| 50 // parameter. |
| 51 var_tracker().AddRefVar(plugin_object); |
| 52 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object)); |
| 53 // We should have informed the host that a reference was taken. |
| 54 EXPECT_EQ(1u, sink().message_count()); |
| 55 *out_param.OutParam(plugin_dispatcher()) = plugin_object; |
| 56 } |
| 57 |
| 58 // The object should have transformed the plugin object back to the host |
| 59 // object ID. Nothing in the var tracker should have changed yet, and no |
| 60 // messages should have been sent. |
| 61 SerializedVarTestReader reader(sv); |
| 62 EXPECT_EQ(host_object.value.as_id, reader.GetIncompleteVar().value.as_id); |
| 63 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object)); |
| 64 EXPECT_EQ(1u, sink().message_count()); |
| 65 } |
| 66 |
| 67 // The out param should have done an "end receive caller owned" on the plugin |
| 68 // var serialization rules, which should have released the "track-with-no- |
| 69 // reference" count in the var tracker as well as the 1 reference we passed |
| 70 // back to the host, so the object should no longer be in the tracker. The |
| 71 // reference we added has been removed, so another message should be sent to |
| 72 // the host to tell it we're done with the object. |
| 73 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object)); |
| 74 EXPECT_EQ(2u, sink().message_count()); |
| 75 } |
| 76 |
| 77 // Tests output strings in the plugin. This is when the host calls into the |
| 78 // plugin with a string and the plugin returns it via an out param. |
| 79 TEST_F(SerializedVarTest, PluginSerializedStringVarInOutParam) { |
| 80 PP_Var plugin_string; |
| 81 const std::string kTestString("elite"); |
| 82 { |
| 83 // Receive the string param. We should track it with 1 refcount. |
| 84 SerializedVarTestConstructor input(kTestString); |
| 85 SerializedVarReceiveInput receive_input(input); |
| 86 plugin_string = receive_input.Get(plugin_dispatcher()); |
| 87 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_string)); |
| 88 EXPECT_EQ(0u, sink().message_count()); |
| 89 |
| 90 SerializedVar sv; |
| 91 { |
| 92 // The "OutParam" does its work in its destructor, it will write the |
| 93 // information to the SerializedVar we passed in the constructor. |
| 94 SerializedVarOutParam out_param(&sv); |
| 95 // An out-param needs to pass a reference to the caller, so it's the |
| 96 // responsibility of the plugin to bump the ref-count of an input |
| 97 // parameter. |
| 98 var_tracker().AddRefVar(plugin_string); |
| 99 EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string)); |
| 100 EXPECT_EQ(0u, sink().message_count()); |
| 101 *out_param.OutParam(plugin_dispatcher()) = plugin_string; |
| 102 } |
| 103 |
| 104 // The SerializedVar should have set the string value internally. Nothing in |
| 105 // the var tracker should have changed yet, and no messages should have been |
| 106 // sent. |
| 107 SerializedVarTestReader reader(sv); |
| 108 EXPECT_EQ(kTestString, reader.GetString()); |
| 109 EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string)); |
| 110 EXPECT_EQ(0u, sink().message_count()); |
| 111 } |
| 112 // The reference the string had initially should be gone, and the reference we |
| 113 // passed to the host should also be gone, so the string should be removed. |
| 114 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_string)); |
| 115 EXPECT_EQ(0u, sink().message_count()); |
| 116 } |
| 117 |
| 118 // Tests receiving an argument and passing it back out as an output parameter. |
37 TEST_F(SerializedVarTest, PluginSerializedVarOutParam) { | 119 TEST_F(SerializedVarTest, PluginSerializedVarOutParam) { |
38 PP_Var host_object = MakeObjectVar(0x31337); | 120 PP_Var host_object = MakeObjectVar(0x31337); |
39 | 121 |
40 // Start tracking this object in the plugin. | 122 // Start tracking this object in the plugin. |
41 PP_Var plugin_object = var_tracker().ReceiveObjectPassRef( | 123 PP_Var plugin_object = var_tracker().ReceiveObjectPassRef( |
42 host_object, plugin_dispatcher()); | 124 host_object, plugin_dispatcher()); |
43 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object)); | 125 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object)); |
44 | 126 |
45 { | 127 { |
46 SerializedVar sv; | 128 SerializedVar sv; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 var_tracker().ReleaseVar(plugin_object); | 186 var_tracker().ReleaseVar(plugin_object); |
105 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object)); | 187 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object)); |
106 EXPECT_EQ(2u, sink().message_count()); | 188 EXPECT_EQ(2u, sink().message_count()); |
107 } | 189 } |
108 | 190 |
109 // Since we didn't keep any refs to the objects, it should have freed the | 191 // Since we didn't keep any refs to the objects, it should have freed the |
110 // object. | 192 // object. |
111 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object)); | 193 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object)); |
112 } | 194 } |
113 | 195 |
| 196 // Tests the case that the plugin receives the same vars twice as an input |
| 197 // parameter (not passing ownership) within a vector. |
| 198 TEST_F(SerializedVarTest, PluginVectorReceiveInput) { |
| 199 PP_Var host_object = MakeObjectVar(0x31337); |
| 200 |
| 201 PP_Var* plugin_objects; |
| 202 PP_Var* plugin_objects2; |
| 203 { |
| 204 // Receive the params. The object should be tracked with no refcount and |
| 205 // no messages sent. The string should is plugin-side only and should have |
| 206 // a reference-count of 1. |
| 207 std::vector<SerializedVar> input1; |
| 208 input1.push_back(SerializedVarTestConstructor(host_object)); |
| 209 input1.push_back(SerializedVarTestConstructor("elite")); |
| 210 SerializedVarVectorReceiveInput receive_input(input1); |
| 211 uint32_t array_size = 0; |
| 212 plugin_objects = receive_input.Get(plugin_dispatcher(), &array_size); |
| 213 ASSERT_EQ(2u, array_size); |
| 214 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0])); |
| 215 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[1])); |
| 216 EXPECT_EQ(0u, sink().message_count()); |
| 217 |
| 218 // Receive the second param, it should be resolved to the same plugin |
| 219 // object and there should still be no refcount. |
| 220 std::vector<SerializedVar> input2; |
| 221 input2.push_back(SerializedVarTestConstructor(host_object)); |
| 222 input2.push_back(SerializedVarTestConstructor("elite")); |
| 223 SerializedVarVectorReceiveInput receive_input2(input2); |
| 224 uint32_t array_size2 = 0; |
| 225 plugin_objects2 = receive_input2.Get(plugin_dispatcher(), &array_size2); |
| 226 ASSERT_EQ(2u, array_size2); |
| 227 EXPECT_EQ(plugin_objects[0].value.as_id, plugin_objects2[0].value.as_id); |
| 228 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0])); |
| 229 // Strings get re-created with a new ID. We don't try to reuse strings in |
| 230 // the tracker, so the string should get a new ID. |
| 231 EXPECT_NE(plugin_objects[1].value.as_id, plugin_objects2[1].value.as_id); |
| 232 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects2[1])); |
| 233 EXPECT_EQ(0u, sink().message_count()); |
| 234 |
| 235 // Take a reference to the object, as if the plugin was using it, and then |
| 236 // release it, we should still be tracking the object since the |
| 237 // ReceiveInputs keep the "track_with_no_reference_count" alive until |
| 238 // they're destroyed. |
| 239 var_tracker().AddRefVar(plugin_objects[0]); |
| 240 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[0])); |
| 241 var_tracker().ReleaseVar(plugin_objects[0]); |
| 242 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0])); |
| 243 EXPECT_EQ(2u, sink().message_count()); |
| 244 |
| 245 // Take a reference to a string and then release it. Make sure no messages |
| 246 // are sent. |
| 247 uint32_t old_message_count = sink().message_count(); |
| 248 var_tracker().AddRefVar(plugin_objects[1]); |
| 249 EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_objects[1])); |
| 250 var_tracker().ReleaseVar(plugin_objects[1]); |
| 251 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[1])); |
| 252 EXPECT_EQ(old_message_count, sink().message_count()); |
| 253 } |
| 254 |
| 255 // Since we didn't keep any refs to the objects or strings, so they should |
| 256 // have been freed. |
| 257 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects[0])); |
| 258 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects[1])); |
| 259 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects2[1])); |
| 260 } |
| 261 |
114 // Tests the plugin receiving a var as a return value from the browser | 262 // Tests the plugin receiving a var as a return value from the browser |
115 // two different times (passing ownership). | 263 // two different times (passing ownership). |
116 TEST_F(SerializedVarTest, PluginReceiveReturn) { | 264 TEST_F(SerializedVarTest, PluginReceiveReturn) { |
117 PP_Var host_object = MakeObjectVar(0x31337); | 265 PP_Var host_object = MakeObjectVar(0x31337); |
118 | 266 |
119 PP_Var plugin_object; | 267 PP_Var plugin_object; |
120 { | 268 { |
121 // Receive the first param, we should be tracking it with a refcount of 1. | 269 // Receive the first param, we should be tracking it with a refcount of 1. |
122 SerializedVarTestConstructor input1(host_object); | 270 SerializedVarTestConstructor input1(host_object); |
123 ReceiveSerializedVarReturnValue receive_input(input1); | 271 ReceiveSerializedVarReturnValue receive_input(input1); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 } | 330 } |
183 | 331 |
184 // When the ReturnValue object goes out of scope, it should have sent a | 332 // When the ReturnValue object goes out of scope, it should have sent a |
185 // release message to the browser. | 333 // release message to the browser. |
186 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object)); | 334 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object)); |
187 EXPECT_EQ(1u, sink().message_count()); | 335 EXPECT_EQ(1u, sink().message_count()); |
188 } | 336 } |
189 | 337 |
190 } // namespace proxy | 338 } // namespace proxy |
191 } // namespace ppapi | 339 } // namespace ppapi |
OLD | NEW |