• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ppapi/proxy/raw_var_data.h"
6 
7 #include "base/logging.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/values.h"
11 #include "ppapi/c/pp_bool.h"
12 #include "ppapi/c/pp_var.h"
13 #include "ppapi/shared_impl/array_var.h"
14 #include "ppapi/shared_impl/dictionary_var.h"
15 #include "ppapi/shared_impl/ppapi_globals.h"
16 #include "ppapi/shared_impl/proxy_lock.h"
17 #include "ppapi/shared_impl/resource_var.h"
18 #include "ppapi/shared_impl/scoped_pp_var.h"
19 #include "ppapi/shared_impl/test_globals.h"
20 #include "ppapi/shared_impl/unittest_utils.h"
21 #include "ppapi/shared_impl/var.h"
22 #include "ppapi/shared_impl/var_tracker.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 
25 namespace ppapi {
26 namespace proxy {
27 
28 namespace {
29 
DefaultHandleWriter(IPC::Message * m,const SerializedHandle & handle)30 void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
31   IPC::ParamTraits<SerializedHandle>::Write(m, handle);
32 }
33 
34 class RawVarDataTest : public testing::Test {
35  public:
RawVarDataTest()36   RawVarDataTest() {}
~RawVarDataTest()37   ~RawVarDataTest() {}
38 
39   // testing::Test implementation.
SetUp()40   virtual void SetUp() {
41     ProxyLock::EnableLockingOnThreadForTest();
42     ProxyLock::Acquire();
43   }
TearDown()44   virtual void TearDown() {
45     ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
46     ProxyLock::Release();
47   }
48 
49  private:
50   TestGlobals globals_;
51 };
52 
WriteAndRead(const PP_Var & var,PP_Var * result)53 bool WriteAndRead(const PP_Var& var, PP_Var* result) {
54   PP_Instance dummy_instance = 1234;
55   scoped_ptr<RawVarDataGraph> expected_data(RawVarDataGraph::Create(
56       var, dummy_instance));
57   if (!expected_data)
58     return false;
59   IPC::Message m;
60   expected_data->Write(&m, base::Bind(&DefaultHandleWriter));
61   PickleIterator iter(m);
62   scoped_ptr<RawVarDataGraph> actual_data(RawVarDataGraph::Read(&m, &iter));
63   *result = actual_data->CreatePPVar(dummy_instance);
64   return true;
65 }
66 
67 // Assumes a ref for var.
WriteReadAndCompare(const PP_Var & var)68 bool WriteReadAndCompare(const PP_Var& var) {
69   ScopedPPVar expected(ScopedPPVar::PassRef(), var);
70   PP_Var result;
71   bool success = WriteAndRead(expected.get(), &result);
72   if (!success)
73     return false;
74   ScopedPPVar actual(ScopedPPVar::PassRef(), result);
75   return TestEqual(expected.get(), actual.get(), true);
76 }
77 
78 }  // namespace
79 
TEST_F(RawVarDataTest,SimpleTest)80 TEST_F(RawVarDataTest, SimpleTest) {
81   EXPECT_TRUE(WriteReadAndCompare(PP_MakeUndefined()));
82   EXPECT_TRUE(WriteReadAndCompare(PP_MakeNull()));
83   EXPECT_TRUE(WriteReadAndCompare(PP_MakeInt32(100)));
84   EXPECT_TRUE(WriteReadAndCompare(PP_MakeBool(PP_TRUE)));
85   EXPECT_TRUE(WriteReadAndCompare(PP_MakeDouble(53.75)));
86   PP_Var object;
87   object.type = PP_VARTYPE_OBJECT;
88   object.value.as_id = 10;
89   EXPECT_TRUE(WriteReadAndCompare(object));
90 }
91 
TEST_F(RawVarDataTest,StringTest)92 TEST_F(RawVarDataTest, StringTest) {
93   EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("")));
94   EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("hello world!")));
95 }
96 
TEST_F(RawVarDataTest,ArrayBufferTest)97 TEST_F(RawVarDataTest, ArrayBufferTest) {
98   std::string data = "hello world!";
99   PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
100       data.size(), data.data());
101   EXPECT_TRUE(WriteReadAndCompare(var));
102   var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
103       0, static_cast<void*>(NULL));
104   EXPECT_TRUE(WriteReadAndCompare(var));
105   // TODO(raymes): add tests for shmem type array buffers.
106 }
107 
TEST_F(RawVarDataTest,DictionaryArrayTest)108 TEST_F(RawVarDataTest, DictionaryArrayTest) {
109   // Empty array.
110   scoped_refptr<ArrayVar> array(new ArrayVar);
111   ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar());
112   EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
113 
114   size_t index = 0;
115 
116   // Array with primitives.
117   array->Set(index++, PP_MakeUndefined());
118   array->Set(index++, PP_MakeNull());
119   array->Set(index++, PP_MakeInt32(100));
120   array->Set(index++, PP_MakeBool(PP_FALSE));
121   array->Set(index++, PP_MakeDouble(0.123));
122   EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
123 
124   // Array with 2 references to the same string.
125   ScopedPPVar release_string(
126       ScopedPPVar::PassRef(), StringVar::StringToPPVar("abc"));
127   array->Set(index++, release_string.get());
128   array->Set(index++, release_string.get());
129   EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
130 
131   // Array with nested array that references the same string.
132   scoped_refptr<ArrayVar> array2(new ArrayVar);
133   ScopedPPVar release_array2(ScopedPPVar::PassRef(), array2->GetPPVar());
134   array2->Set(0, release_string.get());
135   array->Set(index++, release_array2.get());
136   EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
137 
138   // Empty dictionary.
139   scoped_refptr<DictionaryVar> dictionary(new DictionaryVar);
140   ScopedPPVar release_dictionary(ScopedPPVar::PassRef(),
141                                  dictionary->GetPPVar());
142   EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
143 
144   // Dictionary with primitives.
145   dictionary->SetWithStringKey("1", PP_MakeUndefined());
146   dictionary->SetWithStringKey("2", PP_MakeNull());
147   dictionary->SetWithStringKey("3", PP_MakeInt32(-100));
148   dictionary->SetWithStringKey("4", PP_MakeBool(PP_TRUE));
149   dictionary->SetWithStringKey("5", PP_MakeDouble(-103.52));
150   EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
151 
152   // Dictionary with 2 references to the same string.
153   dictionary->SetWithStringKey("6", release_string.get());
154   dictionary->SetWithStringKey("7", release_string.get());
155   EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
156 
157   // Dictionary with nested dictionary that references the same string.
158   scoped_refptr<DictionaryVar> dictionary2(new DictionaryVar);
159   ScopedPPVar release_dictionary2(ScopedPPVar::PassRef(),
160                                   dictionary2->GetPPVar());
161   dictionary2->SetWithStringKey("abc", release_string.get());
162   dictionary->SetWithStringKey("8", release_dictionary2.get());
163   EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
164 
165   // Array with dictionary.
166   array->Set(index++, release_dictionary.get());
167   EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
168 
169   // Array with dictionary with array.
170   array2->Set(0, PP_MakeInt32(100));
171   dictionary->SetWithStringKey("9", release_array2.get());
172   EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
173 
174   // Array <-> dictionary cycle.
175   dictionary->SetWithStringKey("10", release_array.get());
176   PP_Var result;
177   ASSERT_FALSE(WriteAndRead(release_dictionary.get(), &result));
178   // Break the cycle.
179   // TODO(raymes): We need some better machinery for releasing vars with
180   // cycles. Remove the code below once we have that.
181   dictionary->DeleteWithStringKey("10");
182 
183   // Array with self references.
184   array->Set(index, release_array.get());
185   ASSERT_FALSE(WriteAndRead(release_array.get(), &result));
186   // Break the self reference.
187   array->Set(index, PP_MakeUndefined());
188 }
189 
TEST_F(RawVarDataTest,ResourceTest)190 TEST_F(RawVarDataTest, ResourceTest) {
191   // TODO(mgiuca): This test passes trivially, since GetVarTracker() returns a
192   // TestVarTracker which returns a null PP_Var.
193   ScopedPPVar resource(
194       ScopedPPVar::PassRef(),
195       PpapiGlobals::Get()->GetVarTracker()->MakeResourcePPVar(34));
196   EXPECT_TRUE(WriteReadAndCompare(resource.get()));
197 
198   // TODO(mgiuca): Test a host resource with an IPC::Message. It is currently a
199   // checkfail to deserialize such a resource.
200 }
201 
202 }  // namespace proxy
203 }  // namespace ppapi
204