// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" #include "base/compiler_specific.h" #include "base/message_loop/message_loop.h" #include "ppapi/shared_impl/proxy_lock.h" #include "ppapi/shared_impl/var.h" #include "ppapi/shared_impl/var_tracker.h" #include "ppapi/shared_impl/test_globals.h" namespace ppapi { namespace { int mock_var_alive_count = 0; class MockStringVar : public StringVar { public: MockStringVar(const std::string& str) : StringVar(str) { mock_var_alive_count++; } ~MockStringVar() override { mock_var_alive_count--; } bool HasValidVarID() { return GetExistingVarID() != 0; } }; class MockObjectVar : public Var { public: MockObjectVar() : Var() { mock_var_alive_count++; } ~MockObjectVar() override { mock_var_alive_count--; } PP_VarType GetType() const override { return PP_VARTYPE_OBJECT; } bool HasValidVarID() { return GetExistingVarID() != 0; } }; } // namespace class VarTrackerTest : public testing::Test { public: VarTrackerTest() {} // Test implementation. void SetUp() override { ASSERT_EQ(0, mock_var_alive_count); } void TearDown() override {} VarTracker& var_tracker() { return *globals_.GetVarTracker(); } private: base::MessageLoop message_loop_; // Required to receive callbacks. TestGlobals globals_; }; // Test that ResetVarID is called when the last PP_Var ref was deleted but the // object lives on. TEST_F(VarTrackerTest, LastResourceRef) { ProxyAutoLock lock; scoped_refptr var(new MockStringVar(std::string("xyz"))); PP_Var pp_var = var->GetPPVar(); EXPECT_TRUE(var->HasValidVarID()); EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID())); // Releasing it should keep the object (because we have a ref) but reset the // var_id_. EXPECT_TRUE(var_tracker().ReleaseVar(pp_var)); EXPECT_FALSE(var->HasValidVarID()); EXPECT_EQ(1, mock_var_alive_count); var = NULL; EXPECT_EQ(0, mock_var_alive_count); } TEST_F(VarTrackerTest, GetPluginRefAgain) { ProxyAutoLock lock; scoped_refptr var(new MockStringVar(std::string("xyz"))); PP_Var pp_var = var->GetPPVar(); EXPECT_TRUE(var_tracker().ReleaseVar(pp_var)); EXPECT_FALSE(var->HasValidVarID()); EXPECT_EQ(1, mock_var_alive_count); // Obtaining PP_Var ref again, and add ref from VarTracker. pp_var = var->GetPPVar(); EXPECT_TRUE(var->HasValidVarID()); EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID())); scoped_refptr another_var = static_cast(var_tracker().GetVar(pp_var)); EXPECT_EQ(1, mock_var_alive_count); // Releasing it again. EXPECT_TRUE(var_tracker().ReleaseVar(pp_var)); EXPECT_FALSE(var->HasValidVarID()); EXPECT_EQ(1, mock_var_alive_count); var = NULL; EXPECT_FALSE(var_tracker().GetVar(pp_var)); EXPECT_EQ(1, mock_var_alive_count); another_var = NULL; EXPECT_FALSE(var_tracker().GetVar(pp_var)); EXPECT_EQ(0, mock_var_alive_count); } // Tests when the plugin is holding a ref to a PP_Var when the instance is // owned only by VarTracker. TEST_F(VarTrackerTest, PluginRefWithoutVarRef) { ProxyAutoLock lock; // Make a PP_Var with one ref held by the plugin, and release the reference. scoped_refptr var(new MockStringVar(std::string("zzz"))); PP_Var pp_var = var->GetPPVar(); EXPECT_EQ(1, mock_var_alive_count); var = NULL; EXPECT_EQ(1, mock_var_alive_count); // The var is owned only by VarTracker. PP_Var must be still valid. EXPECT_TRUE(var_tracker().GetVar(pp_var)); var_tracker().ReleaseVar(pp_var); EXPECT_EQ(0, mock_var_alive_count); EXPECT_FALSE(var_tracker().GetVar(pp_var)); } // Tests on Var having type of PP_VARTYPE_OBJECT. TEST_F(VarTrackerTest, ObjectRef) { ProxyAutoLock lock; scoped_refptr var(new MockObjectVar()); PP_Var pp_var = var->GetPPVar(); EXPECT_TRUE(var_tracker().ReleaseVar(pp_var)); EXPECT_FALSE(var->HasValidVarID()); EXPECT_EQ(1, mock_var_alive_count); // Obtaining PP_Var ref again, and add ref from VarTracker. pp_var = var->GetPPVar(); EXPECT_TRUE(var->HasValidVarID()); EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID())); scoped_refptr another_var = static_cast(var_tracker().GetVar(pp_var)); EXPECT_EQ(1, mock_var_alive_count); // Releasing all references, then only VarTracker own the instance. var = NULL; EXPECT_TRUE(var_tracker().GetVar(pp_var)); EXPECT_EQ(1, mock_var_alive_count); another_var = NULL; EXPECT_TRUE(var_tracker().GetVar(pp_var)); EXPECT_EQ(1, mock_var_alive_count); // Releasing plugin reference. EXPECT_TRUE(var_tracker().ReleaseVar(pp_var)); EXPECT_EQ(0, mock_var_alive_count); } } // namespace ppapi