Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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. | |
| 4 | |
| 5 #include "ppapi/shared_impl/var_value_conversions.h" | |
| 6 | |
| 7 #include <cmath> | |
| 8 #include <cstring> | |
| 9 | |
| 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/dictionary_var.h" | |
| 17 #include "ppapi/shared_impl/proxy_lock.h" | |
| 18 #include "ppapi/shared_impl/scoped_pp_var.h" | |
| 19 #include "ppapi/shared_impl/test_globals.h" | |
| 20 #include "ppapi/shared_impl/var.h" | |
| 21 #include "testing/gtest/include/gtest/gtest.h" | |
| 22 | |
| 23 namespace ppapi { | |
| 24 namespace { | |
| 25 | |
| 26 bool Equals(const base::Value& value, const PP_Var& var) { | |
| 27 switch (value.GetType()) { | |
| 28 case base::Value::TYPE_NULL: { | |
| 29 return var.type == PP_VARTYPE_NULL; | |
| 30 } | |
| 31 case base::Value::TYPE_BOOLEAN: { | |
| 32 bool result = false; | |
| 33 return var.type == PP_VARTYPE_BOOL && | |
| 34 value.GetAsBoolean(&result) && | |
| 35 result == PP_ToBool(var.value.as_bool); | |
| 36 } | |
| 37 case base::Value::TYPE_INTEGER: { | |
| 38 int result = 0; | |
| 39 return var.type == PP_VARTYPE_INT32 && | |
| 40 value.GetAsInteger(&result) && | |
| 41 result == var.value.as_int; | |
| 42 } | |
| 43 case base::Value::TYPE_DOUBLE: { | |
| 44 double result = 0; | |
| 45 return var.type == PP_VARTYPE_DOUBLE && | |
| 46 value.GetAsDouble(&result) && | |
| 47 fabs(result - var.value.as_double) < 1.0e-4; | |
| 48 } | |
| 49 case base::Value::TYPE_STRING: { | |
| 50 std::string result; | |
| 51 StringVar* string_var = StringVar::FromPPVar(var); | |
| 52 return string_var && | |
| 53 value.GetAsString(&result) && | |
| 54 result == string_var->value(); | |
| 55 } | |
| 56 case base::Value::TYPE_BINARY: { | |
| 57 const base::BinaryValue& binary_value = | |
| 58 static_cast<const base::BinaryValue&>(value); | |
| 59 ArrayBufferVar* array_buffer_var = ArrayBufferVar::FromPPVar(var); | |
| 60 if (!array_buffer_var || | |
| 61 binary_value.GetSize() != array_buffer_var->ByteLength()) { | |
| 62 return false; | |
| 63 } | |
| 64 | |
| 65 bool result = !memcmp(binary_value.GetBuffer(), array_buffer_var->Map(), | |
| 66 binary_value.GetSize()); | |
| 67 array_buffer_var->Unmap(); | |
| 68 return result; | |
| 69 } | |
| 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 || dict_value.size() != dict_var->key_value_map().size()) | |
| 75 return false; | |
| 76 | |
| 77 for (base::DictionaryValue::Iterator value_iter(dict_value); | |
| 78 !value_iter.IsAtEnd(); value_iter.Advance()) { | |
|
dmichael (off chromium)
2013/03/05 22:01:03
nit: I prefer 1 statement per line if they don't f
yzshen1
2013/03/14 05:38:21
Done.
| |
| 79 DictionaryVar::KeyValueMap::const_iterator var_iter = | |
| 80 dict_var->key_value_map().find(value_iter.key()); | |
| 81 if (var_iter == dict_var->key_value_map().end() || | |
| 82 !Equals(value_iter.value(), var_iter->second.get())) | |
| 83 return false; | |
| 84 } | |
| 85 return true; | |
| 86 } | |
| 87 case base::Value::TYPE_LIST: { | |
| 88 // TODO(yzshen): add support once array var is supported. | |
| 89 return false; | |
| 90 } | |
| 91 } | |
| 92 NOTREACHED(); | |
| 93 return false; | |
| 94 } | |
| 95 | |
| 96 class VarValueConversionsTest : public testing::Test { | |
| 97 public: | |
| 98 VarValueConversionsTest() { | |
| 99 } | |
| 100 virtual ~VarValueConversionsTest() { | |
| 101 } | |
| 102 | |
| 103 // testing::Test implementation. | |
| 104 virtual void SetUp() { | |
| 105 ProxyLock::Acquire(); | |
| 106 } | |
| 107 virtual void TearDown() { | |
| 108 ProxyLock::Release(); | |
| 109 } | |
| 110 | |
| 111 private: | |
| 112 TestGlobals globals_; | |
| 113 }; | |
| 114 | |
| 115 } // namespace | |
| 116 | |
| 117 TEST_F(VarValueConversionsTest, CreateValueFromVar) { | |
| 118 // Undefined var is not a valid input. | |
| 119 ASSERT_EQ(NULL, CreateValueFromVar(PP_MakeUndefined())); | |
| 120 | |
| 121 { | |
| 122 // Undefined var is not allowed even if it is stored in a dictionary var. | |
|
dmichael (off chromium)
2013/03/05 22:01:03
FWIW, I would consider this overly restrictive for
yzshen1
2013/03/14 05:38:21
Thanks! I looked at the relevant code more closely
| |
| 123 scoped_refptr<DictionaryVar> dict_var(new DictionaryVar()); | |
| 124 ASSERT_TRUE(dict_var->SetWithStringKey("key_1", PP_MakeUndefined())); | |
| 125 ScopedPPVar var(ScopedPPVar::PassRef(), dict_var->GetPPVar()); | |
| 126 ASSERT_EQ(NULL, CreateValueFromVar(var.get())); | |
| 127 } | |
| 128 | |
| 129 { | |
| 130 // Var holding a ref to itself is not a valid input. | |
| 131 scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar()); | |
| 132 ScopedPPVar var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar()); | |
| 133 scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar()); | |
| 134 ScopedPPVar var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar()); | |
| 135 | |
| 136 ASSERT_TRUE(dict_var_1->SetWithStringKey("key_1", var_2.get())); | |
| 137 scoped_ptr<base::Value> value(CreateValueFromVar(var_1.get())); | |
| 138 ASSERT_TRUE(value.get() != NULL); | |
| 139 | |
| 140 ASSERT_TRUE(dict_var_2->SetWithStringKey("key_2", var_1.get())); | |
| 141 value.reset(CreateValueFromVar(var_1.get())); | |
| 142 ASSERT_EQ(NULL, value.get()); | |
| 143 | |
| 144 // Make sure |var_1| doesn't indirectly hold a ref to itself, otherwise it | |
| 145 // is leaked. | |
| 146 dict_var_1->DeleteWithStringKey("key_1"); | |
|
dmichael (off chromium)
2013/03/05 22:01:03
Maybe assert at the end of all of these that the v
yzshen1
2013/03/14 05:38:21
Done. I added a check in TearDown().
On 2013/03/05
| |
| 147 } | |
| 148 | |
| 149 { | |
| 150 // Test valid inputs. | |
| 151 scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar()); | |
| 152 ScopedPPVar dict_pp_var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar()); | |
| 153 scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar()); | |
| 154 ScopedPPVar dict_pp_var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar()); | |
| 155 scoped_refptr<StringVar> string_var(new StringVar("string_value")); | |
| 156 ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar()); | |
| 157 | |
| 158 ASSERT_TRUE(dict_var_1->SetWithStringKey("null_key", PP_MakeNull())); | |
| 159 ASSERT_TRUE(dict_var_1->SetWithStringKey("string_key", | |
| 160 string_pp_var.get())); | |
| 161 ASSERT_TRUE(dict_var_1->SetWithStringKey("dict_key", dict_pp_var_2.get())); | |
| 162 | |
| 163 ASSERT_TRUE(dict_var_2->SetWithStringKey("double_key", PP_MakeDouble(1))); | |
| 164 ASSERT_TRUE(dict_var_2->SetWithStringKey("int_key", PP_MakeInt32(2))); | |
| 165 ASSERT_TRUE(dict_var_2->SetWithStringKey("bool_key", PP_MakeBool(PP_TRUE))); | |
| 166 | |
| 167 scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var_1.get())); | |
| 168 ASSERT_TRUE(value.get() != NULL); | |
| 169 ASSERT_TRUE(Equals(*value, dict_pp_var_1.get())); | |
| 170 } | |
| 171 | |
| 172 { | |
| 173 // Test that dictionary keys containing '.' are handled correctly. | |
| 174 scoped_refptr<DictionaryVar> dict_var(new DictionaryVar()); | |
| 175 ScopedPPVar dict_pp_var(ScopedPPVar::PassRef(), dict_var->GetPPVar()); | |
| 176 | |
| 177 ASSERT_TRUE(dict_var->SetWithStringKey("double.key", PP_MakeDouble(1))); | |
| 178 ASSERT_TRUE(dict_var->SetWithStringKey("int.key..name", PP_MakeInt32(2))); | |
| 179 | |
| 180 scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var.get())); | |
| 181 ASSERT_TRUE(value.get() != NULL); | |
| 182 ASSERT_TRUE(Equals(*value, dict_pp_var.get())); | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 TEST_F(VarValueConversionsTest, CreateVarFromValue) { | |
| 187 base::DictionaryValue dict_value; | |
| 188 dict_value.Set("null_key", base::Value::CreateNullValue()); | |
| 189 dict_value.SetString("string_key", "string_value"); | |
| 190 dict_value.SetDouble("dict_key.double_key", 1); | |
| 191 dict_value.SetInteger("dict_key.int_key", 2); | |
| 192 dict_value.SetBoolean("dict_key.bool_key", true); | |
| 193 | |
| 194 ScopedPPVar var(ScopedPPVar::PassRef(), CreateVarFromValue(dict_value)); | |
| 195 ASSERT_TRUE(Equals(dict_value, var.get())); | |
| 196 } | |
| 197 | |
| 198 } // namespace ppapi | |
| OLD | NEW |