// 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 "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++;
  }
  virtual ~MockStringVar() { mock_var_alive_count--; }
  bool HasValidVarID() { return GetExistingVarID() != 0; }
};

class MockObjectVar : public Var {
 public:
  MockObjectVar() : Var() { mock_var_alive_count++; }
  virtual ~MockObjectVar() { mock_var_alive_count--; }
  virtual PP_VarType GetType() const OVERRIDE { return PP_VARTYPE_OBJECT; }
  bool HasValidVarID() { return GetExistingVarID() != 0; }
};

}  // namespace

class VarTrackerTest : public testing::Test {
 public:
  VarTrackerTest() {}

  // Test implementation.
  virtual void SetUp() OVERRIDE {
    ASSERT_EQ(0, mock_var_alive_count);
    ProxyLock::EnableLockingOnThreadForTest();
  }
  virtual void TearDown() OVERRIDE {}

  VarTracker& var_tracker() { return *globals_.GetVarTracker(); }

 private:
  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<MockStringVar> 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<MockStringVar> 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<MockStringVar> another_var =
      static_cast<MockStringVar*>(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<MockStringVar> 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<MockObjectVar> 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<MockObjectVar> another_var =
      static_cast<MockObjectVar*>(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
