var_tracker_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
6
7#include "base/compiler_specific.h"
8#include "ppapi/shared_impl/proxy_lock.h"
9#include "ppapi/shared_impl/var.h"
10#include "ppapi/shared_impl/var_tracker.h"
11#include "ppapi/shared_impl/test_globals.h"
12
13namespace ppapi {
14
15namespace {
16
17int mock_var_alive_count = 0;
18
19class MockStringVar : public StringVar {
20 public:
21  MockStringVar(const std::string& str) : StringVar(str) {
22    mock_var_alive_count++;
23  }
24  virtual ~MockStringVar() {
25    mock_var_alive_count--;
26  }
27  bool HasValidVarID() {
28    return GetExistingVarID() != 0;
29  }
30};
31
32class MockObjectVar : public Var {
33 public:
34  MockObjectVar() : Var() {
35    mock_var_alive_count++;
36  }
37  virtual ~MockObjectVar() {
38    mock_var_alive_count--;
39  }
40  virtual PP_VarType GetType() const OVERRIDE {
41    return PP_VARTYPE_OBJECT;
42  }
43  bool HasValidVarID() {
44    return GetExistingVarID() != 0;
45  }
46};
47
48}  // namespace
49
50class VarTrackerTest : public testing::Test {
51 public:
52  VarTrackerTest() {}
53
54  // Test implementation.
55  virtual void SetUp() OVERRIDE {
56    ASSERT_EQ(0, mock_var_alive_count);
57    ProxyLock::EnableLockingOnThreadForTest();
58  }
59  virtual void TearDown() OVERRIDE {
60  }
61
62  VarTracker& var_tracker() { return *globals_.GetVarTracker(); }
63
64 private:
65  TestGlobals globals_;
66};
67
68// Test that ResetVarID is called when the last PP_Var ref was deleted but the
69// object lives on.
70TEST_F(VarTrackerTest, LastResourceRef) {
71  ProxyAutoLock lock;
72  scoped_refptr<MockStringVar> var(new MockStringVar(std::string("xyz")));
73  PP_Var pp_var = var->GetPPVar();
74  EXPECT_TRUE(var->HasValidVarID());
75  EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID()));
76
77  // Releasing it should keep the object (because we have a ref) but reset the
78  // var_id_.
79  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
80  EXPECT_FALSE(var->HasValidVarID());
81  EXPECT_EQ(1, mock_var_alive_count);
82
83  var = NULL;
84  EXPECT_EQ(0, mock_var_alive_count);
85}
86
87TEST_F(VarTrackerTest, GetPluginRefAgain) {
88  ProxyAutoLock lock;
89  scoped_refptr<MockStringVar> var(new MockStringVar(std::string("xyz")));
90  PP_Var pp_var = var->GetPPVar();
91  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
92  EXPECT_FALSE(var->HasValidVarID());
93  EXPECT_EQ(1, mock_var_alive_count);
94
95  // Obtaining PP_Var ref again, and add ref from VarTracker.
96  pp_var = var->GetPPVar();
97  EXPECT_TRUE(var->HasValidVarID());
98  EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID()));
99  scoped_refptr<MockStringVar> another_var =
100      static_cast<MockStringVar*>(var_tracker().GetVar(pp_var));
101  EXPECT_EQ(1, mock_var_alive_count);
102
103  // Releasing it again.
104  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
105  EXPECT_FALSE(var->HasValidVarID());
106  EXPECT_EQ(1, mock_var_alive_count);
107
108  var = NULL;
109  EXPECT_FALSE(var_tracker().GetVar(pp_var));
110  EXPECT_EQ(1, mock_var_alive_count);
111  another_var = NULL;
112  EXPECT_FALSE(var_tracker().GetVar(pp_var));
113  EXPECT_EQ(0, mock_var_alive_count);
114}
115
116// Tests when the plugin is holding a ref to a PP_Var when the instance is
117// owned only by VarTracker.
118TEST_F(VarTrackerTest, PluginRefWithoutVarRef) {
119  ProxyAutoLock lock;
120  // Make a PP_Var with one ref held by the plugin, and release the reference.
121  scoped_refptr<MockStringVar> var(new MockStringVar(std::string("zzz")));
122  PP_Var pp_var = var->GetPPVar();
123  EXPECT_EQ(1, mock_var_alive_count);
124  var = NULL;
125  EXPECT_EQ(1, mock_var_alive_count);
126
127  // The var is owned only by VarTracker. PP_Var must be still valid.
128  EXPECT_TRUE(var_tracker().GetVar(pp_var));
129
130  var_tracker().ReleaseVar(pp_var);
131  EXPECT_EQ(0, mock_var_alive_count);
132  EXPECT_FALSE(var_tracker().GetVar(pp_var));
133}
134
135// Tests on Var having type of PP_VARTYPE_OBJECT.
136TEST_F(VarTrackerTest, ObjectRef) {
137  ProxyAutoLock lock;
138  scoped_refptr<MockObjectVar> var(new MockObjectVar());
139  PP_Var pp_var = var->GetPPVar();
140  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
141  EXPECT_FALSE(var->HasValidVarID());
142  EXPECT_EQ(1, mock_var_alive_count);
143
144  // Obtaining PP_Var ref again, and add ref from VarTracker.
145  pp_var = var->GetPPVar();
146  EXPECT_TRUE(var->HasValidVarID());
147  EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID()));
148  scoped_refptr<MockObjectVar> another_var =
149      static_cast<MockObjectVar*>(var_tracker().GetVar(pp_var));
150  EXPECT_EQ(1, mock_var_alive_count);
151
152  // Releasing all references, then only VarTracker own the instance.
153  var = NULL;
154  EXPECT_TRUE(var_tracker().GetVar(pp_var));
155  EXPECT_EQ(1, mock_var_alive_count);
156  another_var = NULL;
157  EXPECT_TRUE(var_tracker().GetVar(pp_var));
158  EXPECT_EQ(1, mock_var_alive_count);
159
160  // Releasing plugin reference.
161  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
162  EXPECT_EQ(0, mock_var_alive_count);
163}
164
165}  // namespace ppapi
166