| Index: ppapi/shared_impl/var_value_conversions_unittest.cc
|
| 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 0000000000000000000000000000000000000000..d9a276992afa5f3cfdc070a24b57e29a84c945b1
|
| --- /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
|
|
|