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 13 namespace ppapi { 14 15 namespace { 16 17 int mock_var_alive_count = 0; 18 19 class 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 28 class 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 38 class 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. 57 TEST_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 74 TEST_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. 105 TEST_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. 123 TEST_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