Home | History | Annotate | Download | only in shared_impl
      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