Fix race in WebRTC logging.
[chromium-blink-merge.git] / ppapi / shared_impl / var_value_conversions_unittest.cc
blob8a6fc1918ed80c91a6ec1785df05729070b2b6ee
1 // Copyright (c) 2013 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/shared_impl/var_value_conversions.h"
7 #include <cmath>
8 #include <cstring>
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/values.h"
14 #include "ppapi/c/pp_bool.h"
15 #include "ppapi/c/pp_var.h"
16 #include "ppapi/shared_impl/array_var.h"
17 #include "ppapi/shared_impl/dictionary_var.h"
18 #include "ppapi/shared_impl/ppapi_globals.h"
19 #include "ppapi/shared_impl/proxy_lock.h"
20 #include "ppapi/shared_impl/scoped_pp_var.h"
21 #include "ppapi/shared_impl/test_globals.h"
22 #include "ppapi/shared_impl/var.h"
23 #include "ppapi/shared_impl/var_tracker.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 namespace ppapi {
27 namespace {
29 bool Equals(const base::Value& value, const PP_Var& var) {
30 switch (value.GetType()) {
31 case base::Value::TYPE_NULL: {
32 return var.type == PP_VARTYPE_NULL || var.type == PP_VARTYPE_UNDEFINED;
34 case base::Value::TYPE_BOOLEAN: {
35 bool result = false;
36 return var.type == PP_VARTYPE_BOOL && value.GetAsBoolean(&result) &&
37 result == PP_ToBool(var.value.as_bool);
39 case base::Value::TYPE_INTEGER: {
40 int result = 0;
41 return var.type == PP_VARTYPE_INT32 && value.GetAsInteger(&result) &&
42 result == var.value.as_int;
44 case base::Value::TYPE_DOUBLE: {
45 double result = 0;
46 return var.type == PP_VARTYPE_DOUBLE && value.GetAsDouble(&result) &&
47 fabs(result - var.value.as_double) < 1.0e-4;
49 case base::Value::TYPE_STRING: {
50 std::string result;
51 StringVar* string_var = StringVar::FromPPVar(var);
52 return string_var && value.GetAsString(&result) &&
53 result == string_var->value();
55 case base::Value::TYPE_BINARY: {
56 const base::BinaryValue& binary_value =
57 static_cast<const base::BinaryValue&>(value);
58 ArrayBufferVar* array_buffer_var = ArrayBufferVar::FromPPVar(var);
59 if (!array_buffer_var ||
60 binary_value.GetSize() != array_buffer_var->ByteLength()) {
61 return false;
64 bool result = !memcmp(binary_value.GetBuffer(),
65 array_buffer_var->Map(),
66 binary_value.GetSize());
67 array_buffer_var->Unmap();
68 return result;
70 case base::Value::TYPE_DICTIONARY: {
71 const base::DictionaryValue& dict_value =
72 static_cast<const base::DictionaryValue&>(value);
73 DictionaryVar* dict_var = DictionaryVar::FromPPVar(var);
74 if (!dict_var)
75 return false;
77 size_t count = 0;
78 for (DictionaryVar::KeyValueMap::const_iterator iter =
79 dict_var->key_value_map().begin();
80 iter != dict_var->key_value_map().end();
81 ++iter) {
82 if (iter->second.get().type == PP_VARTYPE_UNDEFINED ||
83 iter->second.get().type == PP_VARTYPE_NULL) {
84 continue;
87 ++count;
88 const base::Value* sub_value = NULL;
89 if (!dict_value.GetWithoutPathExpansion(iter->first, &sub_value) ||
90 !Equals(*sub_value, iter->second.get())) {
91 return false;
94 return count == dict_value.size();
96 case base::Value::TYPE_LIST: {
97 const base::ListValue& list_value =
98 static_cast<const base::ListValue&>(value);
99 ArrayVar* array_var = ArrayVar::FromPPVar(var);
100 if (!array_var || list_value.GetSize() != array_var->elements().size())
101 return false;
103 base::ListValue::const_iterator value_iter = list_value.begin();
104 ArrayVar::ElementVector::const_iterator var_iter =
105 array_var->elements().begin();
106 for (; value_iter != list_value.end() &&
107 var_iter != array_var->elements().end();
108 ++value_iter, ++var_iter) {
109 if (!Equals(**value_iter, var_iter->get()))
110 return false;
112 return true;
115 NOTREACHED();
116 return false;
119 bool ConvertVarAndVerify(const PP_Var& var) {
120 scoped_ptr<base::Value> value(CreateValueFromVar(var));
121 if (value.get())
122 return Equals(*value, var);
123 return false;
126 bool ConvertValueAndVerify(const base::Value& value) {
127 ScopedPPVar var(ScopedPPVar::PassRef(), CreateVarFromValue(value));
128 if (var.get().type != PP_VARTYPE_UNDEFINED)
129 return Equals(value, var.get());
130 return false;
133 class VarValueConversionsTest : public testing::Test {
134 public:
135 VarValueConversionsTest() {}
136 virtual ~VarValueConversionsTest() {}
138 // testing::Test implementation.
139 virtual void SetUp() {
140 ProxyLock::EnableLockingOnThreadForTest();
141 ProxyLock::Acquire();
143 virtual void TearDown() {
144 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
145 ProxyLock::Release();
148 private:
149 TestGlobals globals_;
152 } // namespace
154 TEST_F(VarValueConversionsTest, CreateValueFromVar) {
156 // Var holding a ref to itself is not a valid input.
157 scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
158 ScopedPPVar var_1(ScopedPPVar::PassRef(), dict_var->GetPPVar());
159 scoped_refptr<ArrayVar> array_var(new ArrayVar());
160 ScopedPPVar var_2(ScopedPPVar::PassRef(), array_var->GetPPVar());
162 ASSERT_TRUE(dict_var->SetWithStringKey("key_1", var_2.get()));
163 ASSERT_TRUE(ConvertVarAndVerify(var_1.get()));
165 ASSERT_TRUE(array_var->Set(0, var_1.get()));
166 scoped_ptr<base::Value> value(CreateValueFromVar(var_1.get()));
167 ASSERT_EQ(NULL, value.get());
169 // Make sure |var_1| doesn't indirectly hold a ref to itself, otherwise it
170 // is leaked.
171 dict_var->DeleteWithStringKey("key_1");
174 // Vars of null or undefined type are converted to null values.
176 ASSERT_TRUE(ConvertVarAndVerify(PP_MakeNull()));
177 ASSERT_TRUE(ConvertVarAndVerify(PP_MakeUndefined()));
181 // Test empty dictionary.
182 scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
183 ScopedPPVar var(ScopedPPVar::PassRef(), dict_var->GetPPVar());
185 ASSERT_TRUE(ConvertVarAndVerify(var.get()));
189 // Key-value pairs whose value is undefined or null are ignored.
190 scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
191 ASSERT_TRUE(dict_var->SetWithStringKey("key_1", PP_MakeUndefined()));
192 ASSERT_TRUE(dict_var->SetWithStringKey("key_2", PP_MakeInt32(1)));
193 ASSERT_TRUE(dict_var->SetWithStringKey("key_3", PP_MakeNull()));
194 ScopedPPVar var(ScopedPPVar::PassRef(), dict_var->GetPPVar());
196 ASSERT_TRUE(ConvertVarAndVerify(var.get()));
200 // The same PP_Var is allowed to appear multiple times.
201 scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar());
202 ScopedPPVar dict_pp_var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar());
203 scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar());
204 ScopedPPVar dict_pp_var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar());
205 scoped_refptr<StringVar> string_var(new StringVar("string_value"));
206 ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar());
208 ASSERT_TRUE(dict_var_1->SetWithStringKey("key_1", dict_pp_var_2.get()));
209 ASSERT_TRUE(dict_var_1->SetWithStringKey("key_2", dict_pp_var_2.get()));
210 ASSERT_TRUE(dict_var_1->SetWithStringKey("key_3", string_pp_var.get()));
211 ASSERT_TRUE(dict_var_2->SetWithStringKey("key_4", string_pp_var.get()));
213 ASSERT_TRUE(ConvertVarAndVerify(dict_pp_var_1.get()));
217 // Test basic cases for array.
218 scoped_refptr<ArrayVar> array_var(new ArrayVar());
219 ScopedPPVar var(ScopedPPVar::PassRef(), array_var->GetPPVar());
221 ASSERT_TRUE(ConvertVarAndVerify(var.get()));
223 ASSERT_TRUE(array_var->Set(0, PP_MakeDouble(1)));
225 ASSERT_TRUE(ConvertVarAndVerify(var.get()));
229 // Test more complex inputs.
230 scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar());
231 ScopedPPVar dict_pp_var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar());
232 scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar());
233 ScopedPPVar dict_pp_var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar());
234 scoped_refptr<ArrayVar> array_var(new ArrayVar());
235 ScopedPPVar array_pp_var(ScopedPPVar::PassRef(), array_var->GetPPVar());
236 scoped_refptr<StringVar> string_var(new StringVar("string_value"));
237 ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar());
239 ASSERT_TRUE(dict_var_1->SetWithStringKey("null_key", PP_MakeNull()));
240 ASSERT_TRUE(
241 dict_var_1->SetWithStringKey("string_key", string_pp_var.get()));
242 ASSERT_TRUE(dict_var_1->SetWithStringKey("dict_key", dict_pp_var_2.get()));
244 ASSERT_TRUE(
245 dict_var_2->SetWithStringKey("undefined_key", PP_MakeUndefined()));
246 ASSERT_TRUE(dict_var_2->SetWithStringKey("double_key", PP_MakeDouble(1)));
247 ASSERT_TRUE(dict_var_2->SetWithStringKey("array_key", array_pp_var.get()));
249 ASSERT_TRUE(array_var->Set(0, PP_MakeInt32(2)));
250 ASSERT_TRUE(array_var->Set(1, PP_MakeBool(PP_TRUE)));
251 ASSERT_TRUE(array_var->SetLength(4));
253 ASSERT_TRUE(ConvertVarAndVerify(dict_pp_var_1.get()));
257 // Test that dictionary keys containing '.' are handled correctly.
258 scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
259 ScopedPPVar dict_pp_var(ScopedPPVar::PassRef(), dict_var->GetPPVar());
261 ASSERT_TRUE(dict_var->SetWithStringKey("double.key", PP_MakeDouble(1)));
262 ASSERT_TRUE(dict_var->SetWithStringKey("int.key..name", PP_MakeInt32(2)));
264 ASSERT_TRUE(ConvertVarAndVerify(dict_pp_var.get()));
268 TEST_F(VarValueConversionsTest, CreateVarFromValue) {
270 // Test basic cases for dictionary.
271 base::DictionaryValue dict_value;
272 ASSERT_TRUE(ConvertValueAndVerify(dict_value));
274 dict_value.SetInteger("int_key", 1);
275 ASSERT_TRUE(ConvertValueAndVerify(dict_value));
279 // Test basic cases for array.
280 base::ListValue list_value;
281 ASSERT_TRUE(ConvertValueAndVerify(list_value));
283 list_value.AppendInteger(1);
284 ASSERT_TRUE(ConvertValueAndVerify(list_value));
288 // Test more complex inputs.
289 base::DictionaryValue dict_value;
290 dict_value.SetString("string_key", "string_value");
291 dict_value.SetDouble("dict_key.double_key", 1);
293 scoped_ptr<base::ListValue> list_value(new base::ListValue());
294 list_value->AppendInteger(2);
295 list_value->AppendBoolean(true);
296 list_value->Append(base::Value::CreateNullValue());
298 dict_value.Set("dict_key.array_key", list_value.release());
300 ASSERT_TRUE(ConvertValueAndVerify(dict_value));
304 TEST_F(VarValueConversionsTest, CreateListValueFromVarVector) {
306 // Test empty var vector.
307 scoped_ptr<base::ListValue> list_value(
308 CreateListValueFromVarVector(std::vector<PP_Var>()));
309 ASSERT_TRUE(list_value.get());
310 ASSERT_EQ(0u, list_value->GetSize());
314 // Test more complex inputs.
315 scoped_refptr<StringVar> string_var(new StringVar("string_value"));
316 ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar());
318 scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
319 ScopedPPVar dict_pp_var(ScopedPPVar::PassRef(), dict_var->GetPPVar());
320 ASSERT_TRUE(dict_var->SetWithStringKey("null_key", PP_MakeNull()));
321 ASSERT_TRUE(dict_var->SetWithStringKey("string_key", string_pp_var.get()));
323 scoped_refptr<ArrayVar> array_var(new ArrayVar());
324 ScopedPPVar array_pp_var(ScopedPPVar::PassRef(), array_var->GetPPVar());
325 ASSERT_TRUE(array_var->Set(0, PP_MakeInt32(2)));
326 ASSERT_TRUE(array_var->Set(1, PP_MakeBool(PP_TRUE)));
327 ASSERT_TRUE(array_var->SetLength(4));
329 std::vector<PP_Var> vars;
330 vars.push_back(dict_pp_var.get());
331 vars.push_back(string_pp_var.get());
332 vars.push_back(array_pp_var.get());
333 vars.push_back(PP_MakeDouble(1));
334 vars.push_back(PP_MakeUndefined());
335 vars.push_back(PP_MakeNull());
337 scoped_ptr<base::ListValue> list_value(CreateListValueFromVarVector(vars));
339 ASSERT_TRUE(list_value.get());
340 ASSERT_EQ(vars.size(), list_value->GetSize());
342 for (size_t i = 0; i < list_value->GetSize(); ++i) {
343 const base::Value* value = NULL;
344 ASSERT_TRUE(list_value->Get(i, &value));
345 ASSERT_TRUE(Equals(*value, vars[i]));
350 TEST_F(VarValueConversionsTest, CreateVarVectorFromListValue) {
352 // Test empty list.
353 base::ListValue list_value;
354 std::vector<PP_Var> vars;
355 ASSERT_TRUE(CreateVarVectorFromListValue(list_value, &vars));
356 ASSERT_EQ(0u, vars.size());
360 // Test more complex inputs.
361 base::ListValue list_value;
363 scoped_ptr<base::DictionaryValue> dict_value(new base::DictionaryValue());
364 dict_value->SetString("string_key", "string_value");
366 scoped_ptr<base::ListValue> sub_list_value(new base::ListValue());
367 sub_list_value->AppendInteger(2);
368 sub_list_value->AppendBoolean(true);
370 list_value.Append(dict_value.release());
371 list_value.AppendString("string_value");
372 list_value.Append(sub_list_value.release());
373 list_value.AppendDouble(1);
374 list_value.Append(base::Value::CreateNullValue());
376 std::vector<PP_Var> vars;
377 ASSERT_TRUE(CreateVarVectorFromListValue(list_value, &vars));
379 ASSERT_EQ(list_value.GetSize(), vars.size());
381 for (size_t i = 0; i < list_value.GetSize(); ++i) {
382 const base::Value* value = NULL;
383 ASSERT_TRUE(list_value.Get(i, &value));
384 ASSERT_TRUE(Equals(*value, vars[i]));
386 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(vars[i]);
391 } // namespace ppapi