diff options
author | raymes@chromium.org <raymes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-15 16:16:54 +0000 |
---|---|---|
committer | raymes@chromium.org <raymes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-15 16:16:54 +0000 |
commit | 687998e618ef6759b6423170030719967bceee62 (patch) | |
tree | 6829ccb405f317cd35cf7aa68a0f10a3d42b9ccf /ppapi | |
parent | 60f537751e6f7ca01fdf12c860cfa4a71a696506 (diff) | |
download | chromium_src-687998e618ef6759b6423170030719967bceee62.zip chromium_src-687998e618ef6759b6423170030719967bceee62.tar.gz chromium_src-687998e618ef6759b6423170030719967bceee62.tar.bz2 |
Revert 200283 "Implement a V8 value<->PP_Var converter"
> Implement a V8 value<->PP_Var converter
>
> NOTE: This patch is being relanded after it was reverted in 199944 due to a unittest breakage, fixed by 200279.
>
> This implements a converter for transforming between V8 values and PP_Vars. This is needed to support transferring arrays/dictionaries (or arrays/objects in javascript) to and from the plugin using the pepper Post/HandleMessage APIs. The entire object graph is converted in the process.
>
> TBR=darin@chromium.org
>
> BUG=236958
>
> Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=199938
>
> Review URL: https://chromiumcodereview.appspot.com/14424006
TBR=raymes@chromium.org
Review URL: https://codereview.chromium.org/15001042
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200288 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/ppapi_tests.gypi | 2 | ||||
-rw-r--r-- | ppapi/proxy/raw_var_data_unittest.cc | 156 | ||||
-rw-r--r-- | ppapi/shared_impl/unittest_utils.cc | 166 | ||||
-rw-r--r-- | ppapi/shared_impl/unittest_utils.h | 19 |
4 files changed, 152 insertions, 191 deletions
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi index 3e5dbf1..ffd577f 100644 --- a/ppapi/ppapi_tests.gypi +++ b/ppapi/ppapi_tests.gypi @@ -101,8 +101,6 @@ 'proxy/resource_message_test_sink.h', 'shared_impl/test_globals.cc', 'shared_impl/test_globals.h', - 'shared_impl/unittest_utils.cc', - 'shared_impl/unittest_utils.h', ], }, diff --git a/ppapi/proxy/raw_var_data_unittest.cc b/ppapi/proxy/raw_var_data_unittest.cc index 2b134af..8a00d21 100644 --- a/ppapi/proxy/raw_var_data_unittest.cc +++ b/ppapi/proxy/raw_var_data_unittest.cc @@ -4,6 +4,8 @@ #include "ppapi/proxy/raw_var_data.h" +#include <cmath> + #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -16,7 +18,6 @@ #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/unittest_utils.h" #include "ppapi/shared_impl/var.h" #include "ppapi/shared_impl/var_tracker.h" #include "testing/gtest/include/gtest/gtest.h" @@ -44,6 +45,153 @@ class RawVarDataTest : public testing::Test { TestGlobals globals_; }; +// Compares two vars for equality. When two vars are found to be equal, an entry +// is inserted into |visited_map| with (expected id, actual id). When comparing +// two PP_Vars that have a graph of references, this avoids following reference +// cycles. It also ensures that a var with ID x in the graph is always equal +// to a var with ID y. This guarantees that the topology of the two graphs +// being compared is identical. +bool Equals(const PP_Var& expected, + const PP_Var& actual, + base::hash_map<int64_t, int64_t>* visited_map) { + if (expected.type != actual.type) { + LOG(ERROR) << "expected type: " << expected.type << + " actual type: " << actual.type; + return false; + } + if (VarTracker::IsVarTypeRefcounted(expected.type)) { + base::hash_map<int64_t, int64_t>::iterator it = + visited_map->find(expected.value.as_id); + if (it != visited_map->end()) { + if (it->second != actual.value.as_id) { + LOG(ERROR) << "expected id: " << it->second << " actual id: " << + actual.value.as_id; + return false; + } else { + return true; + } + } else { + (*visited_map)[expected.value.as_id] = actual.value.as_id; + } + } + switch (expected.type) { + case PP_VARTYPE_UNDEFINED: + return true; + case PP_VARTYPE_NULL: + return true; + case PP_VARTYPE_BOOL: + if (expected.value.as_bool != actual.value.as_bool) { + LOG(ERROR) << "expected: " << expected.value.as_bool << " actual: " << + actual.value.as_bool; + return false; + } + return true; + case PP_VARTYPE_INT32: + if (expected.value.as_int != actual.value.as_int) { + LOG(ERROR) << "expected: " << expected.value.as_int << " actual: " << + actual.value.as_int; + return false; + } + return true; + case PP_VARTYPE_DOUBLE: + if (fabs(expected.value.as_double - actual.value.as_double) > 1.0e-4) { + LOG(ERROR) << "expected: " << expected.value.as_double << + " actual: " << actual.value.as_double; + return false; + } + return true; + case PP_VARTYPE_OBJECT: + if (expected.value.as_id != actual.value.as_id) { + LOG(ERROR) << "expected: " << expected.value.as_id << " actual: " << + actual.value.as_id; + return false; + } + return true; + case PP_VARTYPE_STRING: { + StringVar* expected_var = StringVar::FromPPVar(expected); + StringVar* actual_var = StringVar::FromPPVar(actual); + DCHECK(expected_var && actual_var); + if (expected_var->value() != actual_var->value()) { + LOG(ERROR) << "expected: " << expected_var->value() << " actual: " << + actual_var->value(); + return false; + } + return true; + } + case PP_VARTYPE_ARRAY_BUFFER: { + ArrayBufferVar* expected_var = ArrayBufferVar::FromPPVar(expected); + ArrayBufferVar* actual_var = ArrayBufferVar::FromPPVar(actual); + DCHECK(expected_var && actual_var); + if (expected_var->ByteLength() != actual_var->ByteLength()) { + LOG(ERROR) << "expected: " << expected_var->ByteLength() << + " actual: " << actual_var->ByteLength(); + return false; + } + if (memcmp(expected_var->Map(), actual_var->Map(), + expected_var->ByteLength()) != 0) { + LOG(ERROR) << "expected array buffer does not match actual."; + return false; + } + return true; + } + case PP_VARTYPE_ARRAY: { + ArrayVar* expected_var = ArrayVar::FromPPVar(expected); + ArrayVar* actual_var = ArrayVar::FromPPVar(actual); + DCHECK(expected_var && actual_var); + if (expected_var->elements().size() != actual_var->elements().size()) { + LOG(ERROR) << "expected: " << expected_var->elements().size() << + " actual: " << actual_var->elements().size(); + return false; + } + for (size_t i = 0; i < expected_var->elements().size(); ++i) { + if (!Equals(expected_var->elements()[i].get(), + actual_var->elements()[i].get(), + visited_map)) { + return false; + } + } + return true; + } + case PP_VARTYPE_DICTIONARY: { + DictionaryVar* expected_var = DictionaryVar::FromPPVar(expected); + DictionaryVar* actual_var = DictionaryVar::FromPPVar(actual); + DCHECK(expected_var && actual_var); + if (expected_var->key_value_map().size() != + actual_var->key_value_map().size()) { + LOG(ERROR) << "expected: " << expected_var->key_value_map().size() << + " actual: " << actual_var->key_value_map().size(); + return false; + } + DictionaryVar::KeyValueMap::const_iterator expected_iter = + expected_var->key_value_map().begin(); + DictionaryVar::KeyValueMap::const_iterator actual_iter = + actual_var->key_value_map().begin(); + for ( ; expected_iter != expected_var->key_value_map().end(); + ++expected_iter, ++actual_iter) { + if (expected_iter->first != actual_iter->first) { + LOG(ERROR) << "expected: " << expected_iter->first << + " actual: " << actual_iter->first; + return false; + } + if (!Equals(expected_iter->second.get(), + actual_iter->second.get(), + visited_map)) { + return false; + } + } + return true; + } + } + NOTREACHED(); + return false; +} + +bool Equals(const PP_Var& expected, + const PP_Var& actual) { + base::hash_map<int64_t, int64_t> visited_map; + return Equals(expected, actual, &visited_map); +} + PP_Var WriteAndRead(const PP_Var& var) { PP_Instance dummy_instance = 1234; scoped_ptr<RawVarDataGraph> expected_data(RawVarDataGraph::Create( @@ -59,7 +207,7 @@ PP_Var WriteAndRead(const PP_Var& var) { bool WriteReadAndCompare(const PP_Var& var) { ScopedPPVar expected(ScopedPPVar::PassRef(), var); ScopedPPVar actual(ScopedPPVar::PassRef(), WriteAndRead(expected.get())); - return TestEqual(expected.get(), actual.get()); + return Equals(expected.get(), actual.get()); } } // namespace @@ -162,7 +310,7 @@ TEST_F(RawVarDataTest, DictionaryArrayTest) { dictionary->SetWithStringKey("10", release_array.get()); ScopedPPVar result = ScopedPPVar(ScopedPPVar::PassRef(), WriteAndRead(release_dictionary.get())); - EXPECT_TRUE(TestEqual(release_dictionary.get(), result.get())); + EXPECT_TRUE(Equals(release_dictionary.get(), result.get())); // Break the cycle. // TODO(raymes): We need some better machinery for releasing vars with // cycles. Remove the code below once we have that. @@ -174,7 +322,7 @@ TEST_F(RawVarDataTest, DictionaryArrayTest) { array->Set(index, release_array.get()); result = ScopedPPVar(ScopedPPVar::PassRef(), WriteAndRead(release_array.get())); - EXPECT_TRUE(TestEqual(release_array.get(), result.get())); + EXPECT_TRUE(Equals(release_array.get(), result.get())); // Break the self reference. array->Set(index, PP_MakeUndefined()); ArrayVar* result_array = ArrayVar::FromPPVar(result.get()); diff --git a/ppapi/shared_impl/unittest_utils.cc b/ppapi/shared_impl/unittest_utils.cc deleted file mode 100644 index 2c32b30..0000000 --- a/ppapi/shared_impl/unittest_utils.cc +++ /dev/null @@ -1,166 +0,0 @@ -// 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/unittest_utils.h" - -#include <cmath> - -#include "base/hash_tables.h" -#include "base/logging.h" -#include "ppapi/shared_impl/array_var.h" -#include "ppapi/shared_impl/dictionary_var.h" -#include "ppapi/shared_impl/var.h" -#include "ppapi/shared_impl/var_tracker.h" - -namespace ppapi { - -namespace { - -// When two vars x and y are found to be equal, an entry is inserted into -// |visited_map| with (x.value.as_id, y.value.as_id). This allows reference -// cycles to be avoided. It also allows us to associate nodes in |expected| with -// nodes in |actual| and check whether the graphs have equivalent topology. -bool Equals(const PP_Var& expected, - const PP_Var& actual, - base::hash_map<int64_t, int64_t>* visited_map) { - if (expected.type != actual.type) { - LOG(ERROR) << "expected type: " << expected.type << - " actual type: " << actual.type; - return false; - } - if (VarTracker::IsVarTypeRefcounted(expected.type)) { - base::hash_map<int64_t, int64_t>::iterator it = - visited_map->find(expected.value.as_id); - if (it != visited_map->end()) { - if (it->second != actual.value.as_id) { - LOG(ERROR) << "expected id: " << it->second << " actual id: " << - actual.value.as_id; - return false; - } else { - return true; - } - } else { - (*visited_map)[expected.value.as_id] = actual.value.as_id; - } - } - switch (expected.type) { - case PP_VARTYPE_UNDEFINED: - return true; - case PP_VARTYPE_NULL: - return true; - case PP_VARTYPE_BOOL: - if (expected.value.as_bool != actual.value.as_bool) { - LOG(ERROR) << "expected: " << expected.value.as_bool << " actual: " << - actual.value.as_bool; - return false; - } - return true; - case PP_VARTYPE_INT32: - if (expected.value.as_int != actual.value.as_int) { - LOG(ERROR) << "expected: " << expected.value.as_int << " actual: " << - actual.value.as_int; - return false; - } - return true; - case PP_VARTYPE_DOUBLE: - if (fabs(expected.value.as_double - actual.value.as_double) > 1.0e-4) { - LOG(ERROR) << "expected: " << expected.value.as_double << - " actual: " << actual.value.as_double; - return false; - } - return true; - case PP_VARTYPE_OBJECT: - if (expected.value.as_id != actual.value.as_id) { - LOG(ERROR) << "expected: " << expected.value.as_id << " actual: " << - actual.value.as_id; - return false; - } - return true; - case PP_VARTYPE_STRING: { - StringVar* expected_var = StringVar::FromPPVar(expected); - StringVar* actual_var = StringVar::FromPPVar(actual); - DCHECK(expected_var && actual_var); - if (expected_var->value() != actual_var->value()) { - LOG(ERROR) << "expected: " << expected_var->value() << " actual: " << - actual_var->value(); - return false; - } - return true; - } - case PP_VARTYPE_ARRAY_BUFFER: { - ArrayBufferVar* expected_var = ArrayBufferVar::FromPPVar(expected); - ArrayBufferVar* actual_var = ArrayBufferVar::FromPPVar(actual); - DCHECK(expected_var && actual_var); - if (expected_var->ByteLength() != actual_var->ByteLength()) { - LOG(ERROR) << "expected: " << expected_var->ByteLength() << - " actual: " << actual_var->ByteLength(); - return false; - } - if (memcmp(expected_var->Map(), actual_var->Map(), - expected_var->ByteLength()) != 0) { - LOG(ERROR) << "expected array buffer does not match actual."; - return false; - } - return true; - } - case PP_VARTYPE_ARRAY: { - ArrayVar* expected_var = ArrayVar::FromPPVar(expected); - ArrayVar* actual_var = ArrayVar::FromPPVar(actual); - DCHECK(expected_var && actual_var); - if (expected_var->elements().size() != actual_var->elements().size()) { - LOG(ERROR) << "expected: " << expected_var->elements().size() << - " actual: " << actual_var->elements().size(); - return false; - } - for (size_t i = 0; i < expected_var->elements().size(); ++i) { - if (!Equals(expected_var->elements()[i].get(), - actual_var->elements()[i].get(), - visited_map)) { - return false; - } - } - return true; - } - case PP_VARTYPE_DICTIONARY: { - DictionaryVar* expected_var = DictionaryVar::FromPPVar(expected); - DictionaryVar* actual_var = DictionaryVar::FromPPVar(actual); - DCHECK(expected_var && actual_var); - if (expected_var->key_value_map().size() != - actual_var->key_value_map().size()) { - LOG(ERROR) << "expected: " << expected_var->key_value_map().size() << - " actual: " << actual_var->key_value_map().size(); - return false; - } - DictionaryVar::KeyValueMap::const_iterator expected_iter = - expected_var->key_value_map().begin(); - DictionaryVar::KeyValueMap::const_iterator actual_iter = - actual_var->key_value_map().begin(); - for ( ; expected_iter != expected_var->key_value_map().end(); - ++expected_iter, ++actual_iter) { - if (expected_iter->first != actual_iter->first) { - LOG(ERROR) << "expected: " << expected_iter->first << - " actual: " << actual_iter->first; - return false; - } - if (!Equals(expected_iter->second.get(), - actual_iter->second.get(), - visited_map)) { - return false; - } - } - return true; - } - } - NOTREACHED(); - return false; -} - -} // namespace - -bool TestEqual(const PP_Var& expected, const PP_Var& actual) { - base::hash_map<int64_t, int64_t> visited_map; - return Equals(expected, actual, &visited_map); -} - -} // namespace ppapi diff --git a/ppapi/shared_impl/unittest_utils.h b/ppapi/shared_impl/unittest_utils.h deleted file mode 100644 index e07d8a8..0000000 --- a/ppapi/shared_impl/unittest_utils.h +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -#ifndef PPAPI_SHARED_IMPL_UNITTEST_UTILS_H_ -#define PPAPI_SHARED_IMPL_UNITTEST_UTILS_H_ - -#include "ppapi/c/pp_var.h" - -namespace ppapi { - -// Compares two vars for equality. This is a deep comparison (the entire graph -// is traversed recursively). The function guarantees that the topology of the -// two PP_Var graphs being compared is identical, including graphs with cycles. -bool TestEqual(const PP_Var& expected, const PP_Var& actual); - -} // namespace ppapi - -#endif // PPAPI_SHARED_IMPL_UNITTEST_UTILS_H_ |