1 // Copyright (c) 2012 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/proxy/raw_var_data.h"
7 #include "base/logging.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/values.h"
12 #include "ppapi/c/pp_bool.h"
13 #include "ppapi/c/pp_var.h"
14 #include "ppapi/shared_impl/array_var.h"
15 #include "ppapi/shared_impl/dictionary_var.h"
16 #include "ppapi/shared_impl/ppapi_globals.h"
17 #include "ppapi/shared_impl/proxy_lock.h"
18 #include "ppapi/shared_impl/resource_var.h"
19 #include "ppapi/shared_impl/scoped_pp_var.h"
20 #include "ppapi/shared_impl/test_globals.h"
21 #include "ppapi/shared_impl/test_utils.h"
22 #include "ppapi/shared_impl/var.h"
23 #include "ppapi/shared_impl/var_tracker.h"
24 #include "testing/gtest/include/gtest/gtest.h"
31 void DefaultHandleWriter(IPC::Message
* m
, const SerializedHandle
& handle
) {
32 IPC::ParamTraits
<SerializedHandle
>::Write(m
, handle
);
35 class RawVarDataTest
: public testing::Test
{
40 // testing::Test implementation.
41 virtual void SetUp() {
44 virtual void TearDown() {
45 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
50 base::MessageLoop message_loop_
; // Required to receive callbacks.
54 bool WriteAndRead(const PP_Var
& var
, PP_Var
* result
) {
55 PP_Instance dummy_instance
= 1234;
56 scoped_ptr
<RawVarDataGraph
> expected_data(RawVarDataGraph::Create(
57 var
, dummy_instance
));
61 expected_data
->Write(&m
, base::Bind(&DefaultHandleWriter
));
62 base::PickleIterator
iter(m
);
63 scoped_ptr
<RawVarDataGraph
> actual_data(RawVarDataGraph::Read(&m
, &iter
));
64 *result
= actual_data
->CreatePPVar(dummy_instance
);
68 // Assumes a ref for var.
69 bool WriteReadAndCompare(const PP_Var
& var
) {
70 ScopedPPVar
expected(ScopedPPVar::PassRef(), var
);
72 bool success
= WriteAndRead(expected
.get(), &result
);
75 ScopedPPVar
actual(ScopedPPVar::PassRef(), result
);
76 return TestEqual(expected
.get(), actual
.get(), true);
81 TEST_F(RawVarDataTest
, SimpleTest
) {
82 EXPECT_TRUE(WriteReadAndCompare(PP_MakeUndefined()));
83 EXPECT_TRUE(WriteReadAndCompare(PP_MakeNull()));
84 EXPECT_TRUE(WriteReadAndCompare(PP_MakeInt32(100)));
85 EXPECT_TRUE(WriteReadAndCompare(PP_MakeBool(PP_TRUE
)));
86 EXPECT_TRUE(WriteReadAndCompare(PP_MakeDouble(53.75)));
88 object
.type
= PP_VARTYPE_OBJECT
;
89 object
.value
.as_id
= 10;
90 EXPECT_TRUE(WriteReadAndCompare(object
));
93 TEST_F(RawVarDataTest
, StringTest
) {
94 EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("")));
95 EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("hello world!")));
98 TEST_F(RawVarDataTest
, ArrayBufferTest
) {
99 std::string data
= "hello world!";
100 PP_Var var
= PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
101 static_cast<uint32_t>(data
.size()), data
.data());
102 EXPECT_TRUE(WriteReadAndCompare(var
));
103 var
= PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
104 0, static_cast<void*>(NULL
));
105 EXPECT_TRUE(WriteReadAndCompare(var
));
106 // TODO(raymes): add tests for shmem type array buffers.
109 TEST_F(RawVarDataTest
, DictionaryArrayTest
) {
111 scoped_refptr
<ArrayVar
> array(new ArrayVar
);
112 ScopedPPVar
release_array(ScopedPPVar::PassRef(), array
->GetPPVar());
113 EXPECT_TRUE(WriteReadAndCompare(array
->GetPPVar()));
117 // Array with primitives.
118 array
->Set(static_cast<uint32_t>(index
++), PP_MakeUndefined());
119 array
->Set(static_cast<uint32_t>(index
++), PP_MakeNull());
120 array
->Set(static_cast<uint32_t>(index
++), PP_MakeInt32(100));
121 array
->Set(static_cast<uint32_t>(index
++), PP_MakeBool(PP_FALSE
));
122 array
->Set(static_cast<uint32_t>(index
++), PP_MakeDouble(0.123));
123 EXPECT_TRUE(WriteReadAndCompare(array
->GetPPVar()));
125 // Array with 2 references to the same string.
126 ScopedPPVar
release_string(
127 ScopedPPVar::PassRef(), StringVar::StringToPPVar("abc"));
128 array
->Set(static_cast<uint32_t>(index
++), release_string
.get());
129 array
->Set(static_cast<uint32_t>(index
++), release_string
.get());
130 EXPECT_TRUE(WriteReadAndCompare(array
->GetPPVar()));
132 // Array with nested array that references the same string.
133 scoped_refptr
<ArrayVar
> array2(new ArrayVar
);
134 ScopedPPVar
release_array2(ScopedPPVar::PassRef(), array2
->GetPPVar());
135 array2
->Set(0, release_string
.get());
136 array
->Set(static_cast<uint32_t>(index
++), release_array2
.get());
137 EXPECT_TRUE(WriteReadAndCompare(array
->GetPPVar()));
140 scoped_refptr
<DictionaryVar
> dictionary(new DictionaryVar
);
141 ScopedPPVar
release_dictionary(ScopedPPVar::PassRef(),
142 dictionary
->GetPPVar());
143 EXPECT_TRUE(WriteReadAndCompare(dictionary
->GetPPVar()));
145 // Dictionary with primitives.
146 dictionary
->SetWithStringKey("1", PP_MakeUndefined());
147 dictionary
->SetWithStringKey("2", PP_MakeNull());
148 dictionary
->SetWithStringKey("3", PP_MakeInt32(-100));
149 dictionary
->SetWithStringKey("4", PP_MakeBool(PP_TRUE
));
150 dictionary
->SetWithStringKey("5", PP_MakeDouble(-103.52));
151 EXPECT_TRUE(WriteReadAndCompare(dictionary
->GetPPVar()));
153 // Dictionary with 2 references to the same string.
154 dictionary
->SetWithStringKey("6", release_string
.get());
155 dictionary
->SetWithStringKey("7", release_string
.get());
156 EXPECT_TRUE(WriteReadAndCompare(dictionary
->GetPPVar()));
158 // Dictionary with nested dictionary that references the same string.
159 scoped_refptr
<DictionaryVar
> dictionary2(new DictionaryVar
);
160 ScopedPPVar
release_dictionary2(ScopedPPVar::PassRef(),
161 dictionary2
->GetPPVar());
162 dictionary2
->SetWithStringKey("abc", release_string
.get());
163 dictionary
->SetWithStringKey("8", release_dictionary2
.get());
164 EXPECT_TRUE(WriteReadAndCompare(dictionary
->GetPPVar()));
166 // Array with dictionary.
167 array
->Set(static_cast<uint32_t>(index
++), release_dictionary
.get());
168 EXPECT_TRUE(WriteReadAndCompare(array
->GetPPVar()));
170 // Array with dictionary with array.
171 array2
->Set(0, PP_MakeInt32(100));
172 dictionary
->SetWithStringKey("9", release_array2
.get());
173 EXPECT_TRUE(WriteReadAndCompare(array
->GetPPVar()));
175 // Array <-> dictionary cycle.
176 dictionary
->SetWithStringKey("10", release_array
.get());
178 ASSERT_FALSE(WriteAndRead(release_dictionary
.get(), &result
));
180 // TODO(raymes): We need some better machinery for releasing vars with
181 // cycles. Remove the code below once we have that.
182 dictionary
->DeleteWithStringKey("10");
184 // Array with self references.
185 array
->Set(static_cast<uint32_t>(index
), release_array
.get());
186 ASSERT_FALSE(WriteAndRead(release_array
.get(), &result
));
187 // Break the self reference.
188 array
->Set(static_cast<uint32_t>(index
), PP_MakeUndefined());
191 TEST_F(RawVarDataTest
, ResourceTest
) {
192 // TODO(mgiuca): This test passes trivially, since GetVarTracker() returns a
193 // TestVarTracker which returns a null PP_Var.
194 ScopedPPVar
resource(
195 ScopedPPVar::PassRef(),
196 PpapiGlobals::Get()->GetVarTracker()->MakeResourcePPVar(34));
197 EXPECT_TRUE(WriteReadAndCompare(resource
.get()));
199 // TODO(mgiuca): Test a host resource with an IPC::Message. It is currently a
200 // checkfail to deserialize such a resource.