diff options
Diffstat (limited to 'ppapi/shared_impl/var_value_conversions_unittest.cc')
-rw-r--r-- | ppapi/shared_impl/var_value_conversions_unittest.cc | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/ppapi/shared_impl/var_value_conversions_unittest.cc b/ppapi/shared_impl/var_value_conversions_unittest.cc new file mode 100644 index 0000000..d9a2769 --- /dev/null +++ b/ppapi/shared_impl/var_value_conversions_unittest.cc @@ -0,0 +1,241 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/shared_impl/var_value_conversions.h" + +#include <cmath> +#include <cstring> + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "ppapi/c/pp_bool.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/shared_impl/dictionary_var.h" +#include "ppapi/shared_impl/ppapi_globals.h" +#include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/shared_impl/scoped_pp_var.h" +#include "ppapi/shared_impl/test_globals.h" +#include "ppapi/shared_impl/var.h" +#include "ppapi/shared_impl/var_tracker.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ppapi { +namespace { + +bool Equals(const base::Value& value, const PP_Var& var) { + switch (value.GetType()) { + case base::Value::TYPE_NULL: { + return var.type == PP_VARTYPE_NULL || var.type == PP_VARTYPE_UNDEFINED; + } + case base::Value::TYPE_BOOLEAN: { + bool result = false; + return var.type == PP_VARTYPE_BOOL && + value.GetAsBoolean(&result) && + result == PP_ToBool(var.value.as_bool); + } + case base::Value::TYPE_INTEGER: { + int result = 0; + return var.type == PP_VARTYPE_INT32 && + value.GetAsInteger(&result) && + result == var.value.as_int; + } + case base::Value::TYPE_DOUBLE: { + double result = 0; + return var.type == PP_VARTYPE_DOUBLE && + value.GetAsDouble(&result) && + fabs(result - var.value.as_double) < 1.0e-4; + } + case base::Value::TYPE_STRING: { + std::string result; + StringVar* string_var = StringVar::FromPPVar(var); + return string_var && + value.GetAsString(&result) && + result == string_var->value(); + } + case base::Value::TYPE_BINARY: { + const base::BinaryValue& binary_value = + static_cast<const base::BinaryValue&>(value); + ArrayBufferVar* array_buffer_var = ArrayBufferVar::FromPPVar(var); + if (!array_buffer_var || + binary_value.GetSize() != array_buffer_var->ByteLength()) { + return false; + } + + bool result = !memcmp(binary_value.GetBuffer(), array_buffer_var->Map(), + binary_value.GetSize()); + array_buffer_var->Unmap(); + return result; + } + case base::Value::TYPE_DICTIONARY: { + const base::DictionaryValue& dict_value = + static_cast<const base::DictionaryValue&>(value); + DictionaryVar* dict_var = DictionaryVar::FromPPVar(var); + if (!dict_var) + return false; + + size_t non_undefined_count = 0; + for (DictionaryVar::KeyValueMap::const_iterator iter = + dict_var->key_value_map().begin(); + iter != dict_var->key_value_map().end(); + ++iter) { + if (iter->second.get().type == PP_VARTYPE_UNDEFINED) + continue; + + ++non_undefined_count; + const base::Value* sub_value = NULL; + if (!dict_value.GetWithoutPathExpansion(iter->first, &sub_value) || + !Equals(*sub_value, iter->second.get())) { + return false; + } + } + return non_undefined_count == dict_value.size(); + } + case base::Value::TYPE_LIST: { + // TODO(yzshen): add support once array var is supported. + return false; + } + } + NOTREACHED(); + return false; +} + +class VarValueConversionsTest : public testing::Test { + public: + VarValueConversionsTest() { + } + virtual ~VarValueConversionsTest() { + } + + // testing::Test implementation. + virtual void SetUp() { + ProxyLock::Acquire(); + } + virtual void TearDown() { + ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); + ProxyLock::Release(); + } + + private: + TestGlobals globals_; +}; + +} // namespace + +TEST_F(VarValueConversionsTest, CreateValueFromVar) { + { + // Var holding a ref to itself is not a valid input. + scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar()); + ScopedPPVar var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar()); + scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar()); + ScopedPPVar var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar()); + + ASSERT_TRUE(dict_var_1->SetWithStringKey("key_1", var_2.get())); + scoped_ptr<base::Value> value(CreateValueFromVar(var_1.get())); + ASSERT_TRUE(value.get()); + + ASSERT_TRUE(dict_var_2->SetWithStringKey("key_2", var_1.get())); + value.reset(CreateValueFromVar(var_1.get())); + ASSERT_EQ(NULL, value.get()); + + // Make sure |var_1| doesn't indirectly hold a ref to itself, otherwise it + // is leaked. + dict_var_1->DeleteWithStringKey("key_1"); + } + + // Vars of null or undefined type are converted to null values. + { + scoped_ptr<base::Value> value(CreateValueFromVar(PP_MakeNull())); + ASSERT_TRUE(value.get()); + ASSERT_TRUE(Equals(*value, PP_MakeNull())); + + value.reset(CreateValueFromVar(PP_MakeUndefined())); + ASSERT_TRUE(value.get()); + ASSERT_TRUE(Equals(*value, PP_MakeUndefined())); + } + + { + // Key-value pairs whose value is undefined are ignored. + scoped_refptr<DictionaryVar> dict_var(new DictionaryVar()); + ASSERT_TRUE(dict_var->SetWithStringKey("key_1", PP_MakeUndefined())); + ASSERT_TRUE(dict_var->SetWithStringKey("key_2", PP_MakeInt32(1))); + ScopedPPVar var(ScopedPPVar::PassRef(), dict_var->GetPPVar()); + + scoped_ptr<base::Value> value(CreateValueFromVar(var.get())); + ASSERT_TRUE(value.get()); + ASSERT_TRUE(Equals(*value, var.get())); + } + + { + // The same PP_Var is allowed to appear multiple times. + scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar()); + ScopedPPVar dict_pp_var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar()); + scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar()); + ScopedPPVar dict_pp_var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar()); + scoped_refptr<StringVar> string_var(new StringVar("string_value")); + ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar()); + + ASSERT_TRUE(dict_var_1->SetWithStringKey("key_1", dict_pp_var_2.get())); + ASSERT_TRUE(dict_var_1->SetWithStringKey("key_2", dict_pp_var_2.get())); + ASSERT_TRUE(dict_var_1->SetWithStringKey("key_3", string_pp_var.get())); + ASSERT_TRUE(dict_var_2->SetWithStringKey("key_4", string_pp_var.get())); + + scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var_1.get())); + ASSERT_TRUE(value.get()); + ASSERT_TRUE(Equals(*value, dict_pp_var_1.get())); + } + + { + // Test more complex inputs. + scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar()); + ScopedPPVar dict_pp_var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar()); + scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar()); + ScopedPPVar dict_pp_var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar()); + scoped_refptr<StringVar> string_var(new StringVar("string_value")); + ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar()); + + ASSERT_TRUE(dict_var_1->SetWithStringKey("null_key", PP_MakeNull())); + ASSERT_TRUE(dict_var_1->SetWithStringKey("string_key", + string_pp_var.get())); + ASSERT_TRUE(dict_var_1->SetWithStringKey("dict_key", dict_pp_var_2.get())); + + ASSERT_TRUE(dict_var_2->SetWithStringKey("undefined_key", + PP_MakeUndefined())); + ASSERT_TRUE(dict_var_2->SetWithStringKey("double_key", PP_MakeDouble(1))); + ASSERT_TRUE(dict_var_2->SetWithStringKey("int_key", PP_MakeInt32(2))); + ASSERT_TRUE(dict_var_2->SetWithStringKey("bool_key", PP_MakeBool(PP_TRUE))); + + scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var_1.get())); + ASSERT_TRUE(value.get()); + ASSERT_TRUE(Equals(*value, dict_pp_var_1.get())); + } + + { + // Test that dictionary keys containing '.' are handled correctly. + scoped_refptr<DictionaryVar> dict_var(new DictionaryVar()); + ScopedPPVar dict_pp_var(ScopedPPVar::PassRef(), dict_var->GetPPVar()); + + ASSERT_TRUE(dict_var->SetWithStringKey("double.key", PP_MakeDouble(1))); + ASSERT_TRUE(dict_var->SetWithStringKey("int.key..name", PP_MakeInt32(2))); + + scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var.get())); + ASSERT_TRUE(value.get()); + ASSERT_TRUE(Equals(*value, dict_pp_var.get())); + } +} + +TEST_F(VarValueConversionsTest, CreateVarFromValue) { + base::DictionaryValue dict_value; + dict_value.Set("null_key", base::Value::CreateNullValue()); + dict_value.SetString("string_key", "string_value"); + dict_value.SetDouble("dict_key.double_key", 1); + dict_value.SetInteger("dict_key.int_key", 2); + dict_value.SetBoolean("dict_key.bool_key", true); + + ScopedPPVar var(ScopedPPVar::PassRef(), CreateVarFromValue(dict_value)); + ASSERT_TRUE(Equals(dict_value, var.get())); +} + +} // namespace ppapi |