15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var_tracker.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/test_globals.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int mock_var_alive_count = 0;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockStringVar : public StringVar {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockStringVar(const std::string& str) : StringVar(str) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_var_alive_count++;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockStringVar() {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_var_alive_count--;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasValidVarID() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetExistingVarID() != 0;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockObjectVar : public Var {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockObjectVar() : Var() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_var_alive_count++;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockObjectVar() {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_var_alive_count--;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PP_VarType GetType() const OVERRIDE {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_VARTYPE_OBJECT;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasValidVarID() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetExistingVarID() != 0;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VarTrackerTest : public testing::Test {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VarTrackerTest() {}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test implementation.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(0, mock_var_alive_count);
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ProxyLock::EnableLockingOnThreadForTest();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VarTracker& var_tracker() { return *globals_.GetVarTracker(); }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGlobals globals_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that ResetVarID is called when the last PP_Var ref was deleted but the
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object lives on.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VarTrackerTest, LastResourceRef) {
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProxyAutoLock lock;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockStringVar> var(new MockStringVar(std::string("xyz")));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var pp_var = var->GetPPVar();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var->HasValidVarID());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID()));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releasing it should keep the object (because we have a ref) but reset the
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // var_id_.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(var->HasValidVarID());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var = NULL;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, mock_var_alive_count);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VarTrackerTest, GetPluginRefAgain) {
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProxyAutoLock lock;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockStringVar> var(new MockStringVar(std::string("xyz")));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var pp_var = var->GetPPVar();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(var->HasValidVarID());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtaining PP_Var ref again, and add ref from VarTracker.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp_var = var->GetPPVar();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var->HasValidVarID());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID()));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockStringVar> another_var =
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<MockStringVar*>(var_tracker().GetVar(pp_var));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releasing it again.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(var->HasValidVarID());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var = NULL;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(var_tracker().GetVar(pp_var));
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  another_var = NULL;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(var_tracker().GetVar(pp_var));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, mock_var_alive_count);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests when the plugin is holding a ref to a PP_Var when the instance is
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// owned only by VarTracker.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VarTrackerTest, PluginRefWithoutVarRef) {
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProxyAutoLock lock;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a PP_Var with one ref held by the plugin, and release the reference.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockStringVar> var(new MockStringVar(std::string("zzz")));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var pp_var = var->GetPPVar();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var = NULL;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The var is owned only by VarTracker. PP_Var must be still valid.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().GetVar(pp_var));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_tracker().ReleaseVar(pp_var);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, mock_var_alive_count);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(var_tracker().GetVar(pp_var));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests on Var having type of PP_VARTYPE_OBJECT.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VarTrackerTest, ObjectRef) {
137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProxyAutoLock lock;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockObjectVar> var(new MockObjectVar());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Var pp_var = var->GetPPVar();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(var->HasValidVarID());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtaining PP_Var ref again, and add ref from VarTracker.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp_var = var->GetPPVar();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var->HasValidVarID());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().GetVar(var->GetExistingVarID()));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockObjectVar> another_var =
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<MockObjectVar*>(var_tracker().GetVar(pp_var));
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releasing all references, then only VarTracker own the instance.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var = NULL;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().GetVar(pp_var));
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  another_var = NULL;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().GetVar(pp_var));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_var_alive_count);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releasing plugin reference.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(var_tracker().ReleaseVar(pp_var));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, mock_var_alive_count);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
166