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