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/unittest_utils.h"
9 #include "base/containers/hash_tables.h"
10 #include "base/logging.h"
11 #include "ppapi/shared_impl/array_var.h"
12 #include "ppapi/shared_impl/dictionary_var.h"
13 #include "ppapi/shared_impl/var.h"
14 #include "ppapi/shared_impl/var_tracker.h"
20 // When two vars x and y are found to be equal, an entry is inserted into
21 // |visited_map| with (x.value.as_id, y.value.as_id). This allows reference
22 // cycles to be avoided. It also allows us to associate nodes in |expected| with
23 // nodes in |actual| and check whether the graphs have equivalent topology.
24 bool Equals(const PP_Var
& expected
,
26 base::hash_map
<int64_t, int64_t>* visited_map
) {
27 if (expected
.type
!= actual
.type
) {
28 LOG(ERROR
) << "expected type: " << expected
.type
<<
29 " actual type: " << actual
.type
;
32 if (VarTracker::IsVarTypeRefcounted(expected
.type
)) {
33 base::hash_map
<int64_t, int64_t>::iterator it
=
34 visited_map
->find(expected
.value
.as_id
);
35 if (it
!= visited_map
->end()) {
36 if (it
->second
!= actual
.value
.as_id
) {
37 LOG(ERROR
) << "expected id: " << it
->second
<< " actual id: " <<
44 (*visited_map
)[expected
.value
.as_id
] = actual
.value
.as_id
;
47 switch (expected
.type
) {
48 case PP_VARTYPE_UNDEFINED
:
53 if (expected
.value
.as_bool
!= actual
.value
.as_bool
) {
54 LOG(ERROR
) << "expected: " << expected
.value
.as_bool
<< " actual: " <<
59 case PP_VARTYPE_INT32
:
60 if (expected
.value
.as_int
!= actual
.value
.as_int
) {
61 LOG(ERROR
) << "expected: " << expected
.value
.as_int
<< " actual: " <<
66 case PP_VARTYPE_DOUBLE
:
67 if (fabs(expected
.value
.as_double
- actual
.value
.as_double
) > 1.0e-4) {
68 LOG(ERROR
) << "expected: " << expected
.value
.as_double
<<
69 " actual: " << actual
.value
.as_double
;
73 case PP_VARTYPE_OBJECT
:
74 if (expected
.value
.as_id
!= actual
.value
.as_id
) {
75 LOG(ERROR
) << "expected: " << expected
.value
.as_id
<< " actual: " <<
80 case PP_VARTYPE_STRING
: {
81 StringVar
* expected_var
= StringVar::FromPPVar(expected
);
82 StringVar
* actual_var
= StringVar::FromPPVar(actual
);
83 DCHECK(expected_var
&& actual_var
);
84 if (expected_var
->value() != actual_var
->value()) {
85 LOG(ERROR
) << "expected: " << expected_var
->value() << " actual: " <<
91 case PP_VARTYPE_ARRAY_BUFFER
: {
92 ArrayBufferVar
* expected_var
= ArrayBufferVar::FromPPVar(expected
);
93 ArrayBufferVar
* actual_var
= ArrayBufferVar::FromPPVar(actual
);
94 DCHECK(expected_var
&& actual_var
);
95 if (expected_var
->ByteLength() != actual_var
->ByteLength()) {
96 LOG(ERROR
) << "expected: " << expected_var
->ByteLength() <<
97 " actual: " << actual_var
->ByteLength();
100 if (memcmp(expected_var
->Map(), actual_var
->Map(),
101 expected_var
->ByteLength()) != 0) {
102 LOG(ERROR
) << "expected array buffer does not match actual.";
107 case PP_VARTYPE_ARRAY
: {
108 ArrayVar
* expected_var
= ArrayVar::FromPPVar(expected
);
109 ArrayVar
* actual_var
= ArrayVar::FromPPVar(actual
);
110 DCHECK(expected_var
&& actual_var
);
111 if (expected_var
->elements().size() != actual_var
->elements().size()) {
112 LOG(ERROR
) << "expected: " << expected_var
->elements().size() <<
113 " actual: " << actual_var
->elements().size();
116 for (size_t i
= 0; i
< expected_var
->elements().size(); ++i
) {
117 if (!Equals(expected_var
->elements()[i
].get(),
118 actual_var
->elements()[i
].get(),
125 case PP_VARTYPE_DICTIONARY
: {
126 DictionaryVar
* expected_var
= DictionaryVar::FromPPVar(expected
);
127 DictionaryVar
* actual_var
= DictionaryVar::FromPPVar(actual
);
128 DCHECK(expected_var
&& actual_var
);
129 if (expected_var
->key_value_map().size() !=
130 actual_var
->key_value_map().size()) {
131 LOG(ERROR
) << "expected: " << expected_var
->key_value_map().size() <<
132 " actual: " << actual_var
->key_value_map().size();
135 DictionaryVar::KeyValueMap::const_iterator expected_iter
=
136 expected_var
->key_value_map().begin();
137 DictionaryVar::KeyValueMap::const_iterator actual_iter
=
138 actual_var
->key_value_map().begin();
139 for ( ; expected_iter
!= expected_var
->key_value_map().end();
140 ++expected_iter
, ++actual_iter
) {
141 if (expected_iter
->first
!= actual_iter
->first
) {
142 LOG(ERROR
) << "expected: " << expected_iter
->first
<<
143 " actual: " << actual_iter
->first
;
146 if (!Equals(expected_iter
->second
.get(),
147 actual_iter
->second
.get(),
161 bool TestEqual(const PP_Var
& expected
, const PP_Var
& actual
) {
162 base::hash_map
<int64_t, int64_t> visited_map
;
163 return Equals(expected
, actual
, &visited_map
);