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 "ipc/ipc_test_sink.h" | 5 #include "ipc/ipc_test_sink.h" |
6 #include "ppapi/proxy/plugin_var_tracker.h" | 6 #include "ppapi/proxy/plugin_var_tracker.h" |
7 #include "ppapi/proxy/ppapi_messages.h" | 7 #include "ppapi/proxy/ppapi_messages.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "ppapi/proxy/ppapi_proxy_test.h" |
9 | 9 |
10 namespace pp { | 10 namespace pp { |
11 namespace proxy { | 11 namespace proxy { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 PP_Var MakeObject(PluginVarTracker::VarID object_id) { | 15 PP_Var MakeObject(PluginVarTracker::VarID object_id) { |
16 PP_Var ret; | 16 PP_Var ret; |
17 ret.type = PP_VARTYPE_OBJECT; | 17 ret.type = PP_VARTYPE_OBJECT; |
18 ret.value.as_id = object_id; | 18 ret.value.as_id = object_id; |
19 return ret; | 19 return ret; |
20 } | 20 } |
21 | 21 |
22 // Creates a PP_Var from the given string ID. | 22 // Creates a PP_Var from the given string ID. |
23 PP_Var MakeString(PluginVarTracker::VarID string_id) { | 23 PP_Var MakeString(PluginVarTracker::VarID string_id) { |
24 PP_Var ret; | 24 PP_Var ret; |
25 ret.type = PP_VARTYPE_STRING; | 25 ret.type = PP_VARTYPE_STRING; |
26 ret.value.as_id = string_id; | 26 ret.value.as_id = string_id; |
27 return ret; | 27 return ret; |
28 } | 28 } |
29 | 29 |
30 } // namespace | 30 } // namespace |
31 | 31 |
32 class PluginVarTrackerTest : public testing::Test { | 32 class PluginVarTrackerTest : public PluginProxyTest { |
33 public: | 33 public: |
34 PluginVarTrackerTest() {} | 34 PluginVarTrackerTest() {} |
35 | 35 |
36 protected: | 36 protected: |
37 // Asserts that there is a unique "release object" IPC message in the test | 37 // Asserts that there is a unique "release object" IPC message in the test |
38 // sink. This will return the var ID from the message or -1 if none found. | 38 // sink. This will return the var ID from the message or -1 if none found. |
39 PluginVarTracker::VarID GetObjectIDForUniqueReleaseObject() { | 39 PluginVarTracker::VarID GetObjectIDForUniqueReleaseObject() { |
40 const IPC::Message* release_msg = sink_.GetUniqueMessageMatching( | 40 const IPC::Message* release_msg = sink().GetUniqueMessageMatching( |
41 PpapiHostMsg_PPBVar_ReleaseObject::ID); | 41 PpapiHostMsg_PPBVar_ReleaseObject::ID); |
42 if (!release_msg) | 42 if (!release_msg) |
43 return -1; | 43 return -1; |
44 | 44 |
45 Tuple1<int64> id; | 45 Tuple1<int64> id; |
46 PpapiHostMsg_PPBVar_ReleaseObject::Read(release_msg, &id); | 46 PpapiHostMsg_PPBVar_ReleaseObject::Read(release_msg, &id); |
47 return id.a; | 47 return id.a; |
48 } | 48 } |
49 | |
50 PluginVarTracker tracker_; | |
51 | |
52 IPC::TestSink sink_; | |
53 }; | 49 }; |
54 | 50 |
55 TEST_F(PluginVarTrackerTest, Strings) { | 51 TEST_F(PluginVarTrackerTest, Strings) { |
56 std::string str("Hello"); | 52 std::string str("Hello"); |
57 PluginVarTracker::VarID str_id1 = tracker_.MakeString(str); | 53 PluginVarTracker::VarID str_id1 = var_tracker().MakeString(str); |
58 EXPECT_NE(0, str_id1); | 54 EXPECT_NE(0, str_id1); |
59 | 55 |
60 PluginVarTracker::VarID str_id2 = tracker_.MakeString( | 56 PluginVarTracker::VarID str_id2 = var_tracker().MakeString( |
61 str.c_str(), static_cast<uint32_t>(str.size())); | 57 str.c_str(), static_cast<uint32_t>(str.size())); |
62 EXPECT_NE(0, str_id2); | 58 EXPECT_NE(0, str_id2); |
63 | 59 |
64 // Make sure the strings come out the other end. | 60 // Make sure the strings come out the other end. |
65 std::string result = tracker_.GetString(MakeString(str_id1)); | 61 std::string result = var_tracker().GetString(MakeString(str_id1)); |
66 EXPECT_EQ(str, result); | 62 EXPECT_EQ(str, result); |
67 result = tracker_.GetString(MakeString(str_id2)); | 63 result = var_tracker().GetString(MakeString(str_id2)); |
68 EXPECT_EQ(str, result); | 64 EXPECT_EQ(str, result); |
69 } | 65 } |
70 | 66 |
71 TEST_F(PluginVarTrackerTest, GetHostObject) { | 67 TEST_F(PluginVarTrackerTest, GetHostObject) { |
72 PP_Var host_object = MakeObject(12345); | 68 PP_Var host_object = MakeObject(12345); |
73 | 69 |
74 // Round-trip through the tracker to make sure the host object comes out the | 70 // Round-trip through the tracker to make sure the host object comes out the |
75 // other end. | 71 // other end. |
76 PP_Var plugin_object = tracker_.ReceiveObjectPassRef(host_object, &sink_); | 72 PP_Var plugin_object = var_tracker().ReceiveObjectPassRef(host_object, |
77 PP_Var host_object2 = tracker_.GetHostObject(plugin_object); | 73 &sink()); |
| 74 PP_Var host_object2 = var_tracker().GetHostObject(plugin_object); |
78 EXPECT_EQ(PP_VARTYPE_OBJECT, host_object2.type); | 75 EXPECT_EQ(PP_VARTYPE_OBJECT, host_object2.type); |
79 EXPECT_EQ(host_object.value.as_id, host_object2.value.as_id); | 76 EXPECT_EQ(host_object.value.as_id, host_object2.value.as_id); |
80 | 77 |
81 tracker_.Release(plugin_object); | 78 var_tracker().Release(plugin_object); |
82 } | 79 } |
83 | 80 |
84 TEST_F(PluginVarTrackerTest, ReceiveObjectPassRef) { | 81 TEST_F(PluginVarTrackerTest, ReceiveObjectPassRef) { |
85 PP_Var host_object = MakeObject(12345); | 82 PP_Var host_object = MakeObject(12345); |
86 | 83 |
87 // Receive the object, we should have one ref and no messages. | 84 // Receive the object, we should have one ref and no messages. |
88 PP_Var plugin_object = tracker_.ReceiveObjectPassRef(host_object, &sink_); | 85 PP_Var plugin_object = var_tracker().ReceiveObjectPassRef(host_object, |
89 EXPECT_EQ(0u, sink_.message_count()); | 86 &sink()); |
90 EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_object)); | 87 EXPECT_EQ(0u, sink().message_count()); |
| 88 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object)); |
91 EXPECT_EQ(0, | 89 EXPECT_EQ(0, |
92 tracker_.GetTrackedWithNoReferenceCountForObject(plugin_object)); | 90 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_object)); |
93 | 91 |
94 // Receive the same object again, we should get the same plugin ID out. | 92 // Receive the same object again, we should get the same plugin ID out. |
95 PP_Var plugin_object2 = tracker_.ReceiveObjectPassRef(host_object, &sink_); | 93 PP_Var plugin_object2 = var_tracker().ReceiveObjectPassRef(host_object, |
| 94 &sink()); |
96 EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id); | 95 EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id); |
97 EXPECT_EQ(2, tracker_.GetRefCountForObject(plugin_object)); | 96 EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_object)); |
98 EXPECT_EQ(0, | 97 EXPECT_EQ(0, |
99 tracker_.GetTrackedWithNoReferenceCountForObject(plugin_object)); | 98 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_object)); |
100 | 99 |
101 // It should have sent one message to decerment the refcount in the host. | 100 // It should have sent one message to decerment the refcount in the host. |
102 // This is because it only maintains one host refcount for all references | 101 // This is because it only maintains one host refcount for all references |
103 // in the plugin, but the host just sent the second one. | 102 // in the plugin, but the host just sent the second one. |
104 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); | 103 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); |
105 sink_.ClearMessages(); | 104 sink().ClearMessages(); |
106 | 105 |
107 // Release the object, one ref at a time. The second release should free | 106 // Release the object, one ref at a time. The second release should free |
108 // the tracking data and send a release message to the browser. | 107 // the tracking data and send a release message to the browser. |
109 tracker_.Release(plugin_object); | 108 var_tracker().Release(plugin_object); |
110 EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_object)); | 109 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object)); |
111 tracker_.Release(plugin_object); | 110 var_tracker().Release(plugin_object); |
112 EXPECT_EQ(-1, tracker_.GetRefCountForObject(plugin_object)); | 111 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object)); |
113 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); | 112 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); |
114 } | 113 } |
115 | 114 |
116 // Tests freeing objects that have both refcounts and "tracked with no ref". | 115 // Tests freeing objects that have both refcounts and "tracked with no ref". |
117 TEST_F(PluginVarTrackerTest, FreeTrackedAndReferencedObject) { | 116 TEST_F(PluginVarTrackerTest, FreeTrackedAndReferencedObject) { |
118 PP_Var host_object = MakeObject(12345); | 117 PP_Var host_object = MakeObject(12345); |
119 | 118 |
120 // Phase one: First receive via a "pass ref", then a tracked with no ref. | 119 // Phase one: First receive via a "pass ref", then a tracked with no ref. |
121 PP_Var plugin_var = tracker_.ReceiveObjectPassRef(host_object, &sink_); | 120 PP_Var plugin_var = var_tracker().ReceiveObjectPassRef(host_object, &sink()); |
122 PP_Var plugin_var2 = tracker_.TrackObjectWithNoReference(host_object, &sink_); | 121 PP_Var plugin_var2 = |
| 122 var_tracker().TrackObjectWithNoReference(host_object, &sink()); |
123 EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id); | 123 EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id); |
124 EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_var)); | 124 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_var)); |
125 EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var)); | 125 EXPECT_EQ(1, |
| 126 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var)); |
126 | 127 |
127 // Free via the refcount, this should release the object to the browser but | 128 // Free via the refcount, this should release the object to the browser but |
128 // maintain the tracked object. | 129 // maintain the tracked object. |
129 tracker_.Release(plugin_var); | 130 var_tracker().Release(plugin_var); |
130 EXPECT_EQ(0, tracker_.GetRefCountForObject(plugin_var)); | 131 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_var)); |
131 EXPECT_EQ(1u, sink_.message_count()); | 132 EXPECT_EQ(1u, sink().message_count()); |
132 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); | 133 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); |
133 | 134 |
134 // Now free via the tracked object, this should free it. | 135 // Now free via the tracked object, this should free it. |
135 tracker_.StopTrackingObjectWithNoReference(plugin_var); | 136 var_tracker().StopTrackingObjectWithNoReference(plugin_var); |
136 EXPECT_EQ(-1, tracker_.GetRefCountForObject(plugin_var)); | 137 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_var)); |
137 | 138 |
138 // Phase two: Receive via a tracked, then get an addref. | 139 // Phase two: Receive via a tracked, then get an addref. |
139 sink_.ClearMessages(); | 140 sink().ClearMessages(); |
140 plugin_var = tracker_.TrackObjectWithNoReference(host_object, &sink_); | 141 plugin_var = var_tracker().TrackObjectWithNoReference(host_object, &sink()); |
141 plugin_var2 = tracker_.ReceiveObjectPassRef(host_object, &sink_); | 142 plugin_var2 = var_tracker().ReceiveObjectPassRef(host_object, &sink()); |
142 EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id); | 143 EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id); |
143 EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_var)); | 144 EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_var)); |
144 EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var)); | 145 EXPECT_EQ(1, |
| 146 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var)); |
145 | 147 |
146 // Free via the tracked object, this should have no effect. | 148 // Free via the tracked object, this should have no effect. |
147 tracker_.StopTrackingObjectWithNoReference(plugin_var); | 149 var_tracker().StopTrackingObjectWithNoReference(plugin_var); |
148 EXPECT_EQ(0, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var)); | 150 EXPECT_EQ(0, |
149 EXPECT_EQ(0u, sink_.message_count()); | 151 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var)); |
| 152 EXPECT_EQ(0u, sink().message_count()); |
150 | 153 |
151 // Now free via the refcount, this should delete it. | 154 // Now free via the refcount, this should delete it. |
152 tracker_.Release(plugin_var); | 155 var_tracker().Release(plugin_var); |
153 EXPECT_EQ(-1, tracker_.GetRefCountForObject(plugin_var)); | 156 EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_var)); |
154 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); | 157 EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject()); |
155 } | 158 } |
156 | 159 |
157 TEST_F(PluginVarTrackerTest, RecursiveTrackWithNoRef) { | 160 TEST_F(PluginVarTrackerTest, RecursiveTrackWithNoRef) { |
158 PP_Var host_object = MakeObject(12345); | 161 PP_Var host_object = MakeObject(12345); |
159 | 162 |
160 // Receive a tracked object twice. | 163 // Receive a tracked object twice. |
161 PP_Var plugin_var = tracker_.TrackObjectWithNoReference(host_object, &sink_); | 164 PP_Var plugin_var = var_tracker().TrackObjectWithNoReference( |
162 EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var)); | 165 host_object, &sink()); |
163 PP_Var plugin_var2 = tracker_.TrackObjectWithNoReference(host_object, &sink_); | 166 EXPECT_EQ(1, |
| 167 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var)); |
| 168 PP_Var plugin_var2 = var_tracker().TrackObjectWithNoReference(host_object, |
| 169 &sink()); |
164 EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id); | 170 EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id); |
165 EXPECT_EQ(0, tracker_.GetRefCountForObject(plugin_var)); | 171 EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_var)); |
166 EXPECT_EQ(2, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var)); | 172 EXPECT_EQ(2, |
| 173 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var)); |
167 | 174 |
168 // Now release those tracked items, the reference should be freed. | 175 // Now release those tracked items, the reference should be freed. |
169 tracker_.StopTrackingObjectWithNoReference(plugin_var); | 176 var_tracker().StopTrackingObjectWithNoReference(plugin_var); |
170 EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var)); | 177 EXPECT_EQ(1, |
171 tracker_.StopTrackingObjectWithNoReference(plugin_var); | 178 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var)); |
172 EXPECT_EQ(-1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var)); | 179 var_tracker().StopTrackingObjectWithNoReference(plugin_var); |
| 180 EXPECT_EQ(-1, |
| 181 var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var)); |
173 } | 182 } |
174 | 183 |
175 } // namespace proxy | 184 } // namespace proxy |
176 } // namespace pp | 185 } // namespace pp |
OLD | NEW |