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