Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: ppapi/proxy/raw_var_data_unittest.cc

Issue 13887007: Introduce RawVarData and associated classes for serializing PP_Vars (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/raw_var_data.cc ('k') | ppapi/shared_impl/var_tracker.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "ppapi/proxy/raw_var_data.h"
6
7 #include <cmath>
8
9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/values.h"
13 #include "ppapi/c/pp_bool.h"
14 #include "ppapi/c/pp_var.h"
15 #include "ppapi/shared_impl/array_var.h"
16 #include "ppapi/shared_impl/dictionary_var.h"
17 #include "ppapi/shared_impl/ppapi_globals.h"
18 #include "ppapi/shared_impl/proxy_lock.h"
19 #include "ppapi/shared_impl/scoped_pp_var.h"
20 #include "ppapi/shared_impl/test_globals.h"
21 #include "ppapi/shared_impl/var.h"
22 #include "ppapi/shared_impl/var_tracker.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 namespace ppapi {
26 namespace proxy {
27
28 namespace {
29
30 class RawVarDataTest : public testing::Test {
31 public:
32 RawVarDataTest() {}
33 ~RawVarDataTest() {}
34
35 // testing::Test implementation.
36 virtual void SetUp() {
37 ProxyLock::Acquire();
38 }
39 virtual void TearDown() {
40 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
41 ProxyLock::Release();
42 }
43
44 private:
45 TestGlobals globals_;
46 };
47
48 // Compares two vars for equality. When two vars are found to be equal, an entry
49 // is inserted into |visited_map| with (expected id, actual id). When comparing
50 // two PP_Vars that have a graph of references, this avoids following reference
51 // cycles. It also ensures that a var with ID x in the graph is always equal
52 // to a var with ID y. This guarantees that the topology of the two graphs
53 // being compared is identical.
54 bool Equals(const PP_Var& expected,
55 const PP_Var& actual,
56 base::hash_map<int64_t, int64_t>* visited_map) {
57 if (expected.type != actual.type) {
58 LOG(ERROR) << "expected type: " << expected.type <<
59 " actual type: " << actual.type;
60 return false;
61 }
62 if (VarTracker::IsVarTypeRefcounted(expected.type)) {
63 base::hash_map<int64_t, int64_t>::iterator it =
64 visited_map->find(expected.value.as_id);
65 if (it != visited_map->end()) {
66 if (it->second != actual.value.as_id) {
67 LOG(ERROR) << "expected id: " << it->second << " actual id: " <<
68 actual.value.as_id;
69 return false;
70 } else {
71 return true;
72 }
73 } else {
74 (*visited_map)[expected.value.as_id] = actual.value.as_id;
75 }
76 }
77 switch (expected.type) {
78 case PP_VARTYPE_UNDEFINED:
79 return true;
80 case PP_VARTYPE_NULL:
81 return true;
82 case PP_VARTYPE_BOOL:
83 if (expected.value.as_bool != actual.value.as_bool) {
84 LOG(ERROR) << "expected: " << expected.value.as_bool << " actual: " <<
85 actual.value.as_bool;
86 return false;
87 }
88 return true;
89 case PP_VARTYPE_INT32:
90 if (expected.value.as_int != actual.value.as_int) {
91 LOG(ERROR) << "expected: " << expected.value.as_int << " actual: " <<
92 actual.value.as_int;
93 return false;
94 }
95 return true;
96 case PP_VARTYPE_DOUBLE:
97 if (fabs(expected.value.as_double - actual.value.as_double) > 1.0e-4) {
98 LOG(ERROR) << "expected: " << expected.value.as_double <<
99 " actual: " << actual.value.as_double;
100 return false;
101 }
102 return true;
103 case PP_VARTYPE_OBJECT:
104 if (expected.value.as_id != actual.value.as_id) {
105 LOG(ERROR) << "expected: " << expected.value.as_id << " actual: " <<
106 actual.value.as_id;
107 return false;
108 }
109 return true;
110 case PP_VARTYPE_STRING: {
111 StringVar* expected_var = StringVar::FromPPVar(expected);
112 StringVar* actual_var = StringVar::FromPPVar(actual);
113 DCHECK(expected_var && actual_var);
114 if (expected_var->value() != actual_var->value()) {
115 LOG(ERROR) << "expected: " << expected_var->value() << " actual: " <<
116 actual_var->value();
117 return false;
118 }
119 return true;
120 }
121 case PP_VARTYPE_ARRAY_BUFFER: {
122 ArrayBufferVar* expected_var = ArrayBufferVar::FromPPVar(expected);
123 ArrayBufferVar* actual_var = ArrayBufferVar::FromPPVar(actual);
124 DCHECK(expected_var && actual_var);
125 if (expected_var->ByteLength() != actual_var->ByteLength()) {
126 LOG(ERROR) << "expected: " << expected_var->ByteLength() <<
127 " actual: " << actual_var->ByteLength();
128 return false;
129 }
130 if (memcmp(expected_var->Map(), actual_var->Map(),
131 expected_var->ByteLength()) != 0) {
132 LOG(ERROR) << "expected array buffer does not match actual.";
133 return false;
134 }
135 return true;
136 }
137 case PP_VARTYPE_ARRAY: {
138 ArrayVar* expected_var = ArrayVar::FromPPVar(expected);
139 ArrayVar* actual_var = ArrayVar::FromPPVar(actual);
140 DCHECK(expected_var && actual_var);
141 if (expected_var->elements().size() != actual_var->elements().size()) {
142 LOG(ERROR) << "expected: " << expected_var->elements().size() <<
143 " actual: " << actual_var->elements().size();
144 return false;
145 }
146 for (size_t i = 0; i < expected_var->elements().size(); ++i) {
147 if (!Equals(expected_var->elements()[i].get(),
148 actual_var->elements()[i].get(),
149 visited_map)) {
150 return false;
151 }
152 }
153 return true;
154 }
155 case PP_VARTYPE_DICTIONARY: {
156 DictionaryVar* expected_var = DictionaryVar::FromPPVar(expected);
157 DictionaryVar* actual_var = DictionaryVar::FromPPVar(actual);
158 DCHECK(expected_var && actual_var);
159 if (expected_var->key_value_map().size() !=
160 actual_var->key_value_map().size()) {
161 LOG(ERROR) << "expected: " << expected_var->key_value_map().size() <<
162 " actual: " << actual_var->key_value_map().size();
163 return false;
164 }
165 DictionaryVar::KeyValueMap::const_iterator expected_iter =
166 expected_var->key_value_map().begin();
167 DictionaryVar::KeyValueMap::const_iterator actual_iter =
168 actual_var->key_value_map().begin();
169 for ( ; expected_iter != expected_var->key_value_map().end();
170 ++expected_iter, ++actual_iter) {
171 if (expected_iter->first != actual_iter->first) {
172 LOG(ERROR) << "expected: " << expected_iter->first <<
173 " actual: " << actual_iter->first;
174 return false;
175 }
176 if (!Equals(expected_iter->second.get(),
177 actual_iter->second.get(),
178 visited_map)) {
179 return false;
180 }
181 }
182 return true;
183 }
184 }
185 NOTREACHED();
186 return false;
187 }
188
189 bool Equals(const PP_Var& expected,
190 const PP_Var& actual) {
191 base::hash_map<int64_t, int64_t> visited_map;
192 return Equals(expected, actual, &visited_map);
193 }
194
195 PP_Var WriteAndRead(const PP_Var& var) {
196 PP_Instance dummy_instance = 1234;
197 scoped_ptr<RawVarDataGraph> expected_data(RawVarDataGraph::Create(
198 var, dummy_instance));
199 IPC::Message m;
200 expected_data->Write(&m);
201 PickleIterator iter(m);
202 scoped_ptr<RawVarDataGraph> actual_data(RawVarDataGraph::Read(&m, &iter));
203 return actual_data->CreatePPVar(dummy_instance);
204 }
205
206 // Assumes a ref for var.
207 bool WriteReadAndCompare(const PP_Var& var) {
208 ScopedPPVar expected(ScopedPPVar::PassRef(), var);
209 ScopedPPVar actual(ScopedPPVar::PassRef(), WriteAndRead(expected.get()));
210 return Equals(expected.get(), actual.get());
211 }
212
213 } // namespace
214
215 TEST_F(RawVarDataTest, SimpleTest) {
216 EXPECT_TRUE(WriteReadAndCompare(PP_MakeUndefined()));
217 EXPECT_TRUE(WriteReadAndCompare(PP_MakeNull()));
218 EXPECT_TRUE(WriteReadAndCompare(PP_MakeInt32(100)));
219 EXPECT_TRUE(WriteReadAndCompare(PP_MakeBool(PP_TRUE)));
220 EXPECT_TRUE(WriteReadAndCompare(PP_MakeDouble(53.75)));
221 PP_Var object;
222 object.type = PP_VARTYPE_OBJECT;
223 object.value.as_id = 10;
224 EXPECT_TRUE(WriteReadAndCompare(object));
225 }
226
227 TEST_F(RawVarDataTest, StringTest) {
228 EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("")));
229 EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("hello world!")));
230 }
231
232 TEST_F(RawVarDataTest, ArrayBufferTest) {
233 std::string data = "hello world!";
234 PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
235 data.size(), data.data());
236 EXPECT_TRUE(WriteReadAndCompare(var));
237 var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
238 0, static_cast<void*>(NULL));
239 EXPECT_TRUE(WriteReadAndCompare(var));
240 // TODO(raymes): add tests for shmem type array buffers.
241 }
242
243 TEST_F(RawVarDataTest, DictionaryArrayTest) {
244 // Empty array.
245 scoped_refptr<ArrayVar> array(new ArrayVar);
246 ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar());
247 EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
248
249 size_t index = 0;
250
251 // Array with primitives.
252 array->Set(index++, PP_MakeUndefined());
253 array->Set(index++, PP_MakeNull());
254 array->Set(index++, PP_MakeInt32(100));
255 array->Set(index++, PP_MakeBool(PP_FALSE));
256 array->Set(index++, PP_MakeDouble(0.123));
257 EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
258
259 // Array with 2 references to the same string.
260 ScopedPPVar release_string(
261 ScopedPPVar::PassRef(), StringVar::StringToPPVar("abc"));
262 array->Set(index++, release_string.get());
263 array->Set(index++, release_string.get());
264 EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
265
266 // Array with nested array that references the same string.
267 scoped_refptr<ArrayVar> array2(new ArrayVar);
268 ScopedPPVar release_array2(ScopedPPVar::PassRef(), array2->GetPPVar());
269 array2->Set(0, release_string.get());
270 array->Set(index++, release_array2.get());
271 EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
272
273 // Empty dictionary.
274 scoped_refptr<DictionaryVar> dictionary(new DictionaryVar);
275 ScopedPPVar release_dictionary(ScopedPPVar::PassRef(),
276 dictionary->GetPPVar());
277 EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
278
279 // Dictionary with primitives.
280 dictionary->SetWithStringKey("1", PP_MakeUndefined());
281 dictionary->SetWithStringKey("2", PP_MakeNull());
282 dictionary->SetWithStringKey("3", PP_MakeInt32(-100));
283 dictionary->SetWithStringKey("4", PP_MakeBool(PP_TRUE));
284 dictionary->SetWithStringKey("5", PP_MakeDouble(-103.52));
285 EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
286
287 // Dictionary with 2 references to the same string.
288 dictionary->SetWithStringKey("6", release_string.get());
289 dictionary->SetWithStringKey("7", release_string.get());
290 EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
291
292 // Dictionary with nested dictionary that references the same string.
293 scoped_refptr<DictionaryVar> dictionary2(new DictionaryVar);
294 ScopedPPVar release_dictionary2(ScopedPPVar::PassRef(),
295 dictionary2->GetPPVar());
296 dictionary2->SetWithStringKey("abc", release_string.get());
297 dictionary->SetWithStringKey("8", release_dictionary2.get());
298 EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
299
300 // Array with dictionary.
301 array->Set(index++, release_dictionary.get());
302 EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
303
304 // Array with dictionary with array.
305 array2->Set(0, PP_MakeInt32(100));
306 dictionary->SetWithStringKey("9", release_array2.get());
307 EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
308
309 // Array <-> dictionary cycle.
310 dictionary->SetWithStringKey("10", release_array.get());
311 ScopedPPVar result = ScopedPPVar(ScopedPPVar::PassRef(),
312 WriteAndRead(release_dictionary.get()));
313 EXPECT_TRUE(Equals(release_dictionary.get(), result.get()));
314 // Break the cycle.
315 // TODO(raymes): We need some better machinery for releasing vars with
316 // cycles. Remove the code below once we have that.
317 dictionary->DeleteWithStringKey("10");
318 DictionaryVar* result_dictionary = DictionaryVar::FromPPVar(result.get());
319 result_dictionary->DeleteWithStringKey("10");
320
321 // Array with self references.
322 array->Set(index, release_array.get());
323 result = ScopedPPVar(ScopedPPVar::PassRef(),
324 WriteAndRead(release_array.get()));
325 EXPECT_TRUE(Equals(release_array.get(), result.get()));
326 // Break the self reference.
327 array->Set(index, PP_MakeUndefined());
328 ArrayVar* result_array = ArrayVar::FromPPVar(result.get());
329 result_array->Set(index, PP_MakeUndefined());
330 }
331
332 } // namespace proxy
333 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/raw_var_data.cc ('k') | ppapi/shared_impl/var_tracker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698