Home | History | Annotate | Download | only in shared_impl
      1 // Copyright (c) 2012 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/resource.h"
     10 #include "ppapi/shared_impl/resource_tracker.h"
     11 #include "ppapi/shared_impl/test_globals.h"
     12 
     13 namespace ppapi {
     14 
     15 namespace {
     16 
     17 int mock_resource_alive_count = 0;
     18 int last_plugin_ref_was_deleted_count = 0;
     19 int instance_was_deleted_count = 0;
     20 
     21 class MyMockResource : public Resource {
     22  public:
     23   MyMockResource(PP_Instance instance) : Resource(OBJECT_IS_IMPL, instance) {
     24     mock_resource_alive_count++;
     25   }
     26   virtual ~MyMockResource() { mock_resource_alive_count--; }
     27 
     28   virtual void LastPluginRefWasDeleted() OVERRIDE {
     29     last_plugin_ref_was_deleted_count++;
     30   }
     31   virtual void InstanceWasDeleted() OVERRIDE { instance_was_deleted_count++; }
     32 };
     33 
     34 }  // namespace
     35 
     36 class ResourceTrackerTest : public testing::Test {
     37  public:
     38   ResourceTrackerTest() {}
     39 
     40   // Test implementation.
     41   virtual void SetUp() OVERRIDE {
     42     ASSERT_EQ(0, mock_resource_alive_count);
     43     last_plugin_ref_was_deleted_count = 0;
     44     instance_was_deleted_count = 0;
     45   }
     46   virtual void TearDown() OVERRIDE {}
     47 
     48   ResourceTracker& resource_tracker() { return *globals_.GetResourceTracker(); }
     49 
     50  private:
     51   TestGlobals globals_;
     52 };
     53 
     54 // Test that LastPluginRefWasDeleted is called when the last plugin ref was
     55 // deleted but the object lives on.
     56 TEST_F(ResourceTrackerTest, LastPluginRef) {
     57   PP_Instance instance = 0x1234567;
     58   ProxyAutoLock lock;
     59   resource_tracker().DidCreateInstance(instance);
     60 
     61   scoped_refptr<MyMockResource> resource(new MyMockResource(instance));
     62   PP_Resource pp_resource = resource->GetReference();
     63   EXPECT_TRUE(resource_tracker().GetResource(pp_resource));
     64 
     65   // Releasing it should keep the object (because we have a ref) but fire the
     66   // "last plugin ref" message.
     67   resource_tracker().ReleaseResource(pp_resource);
     68   EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
     69   EXPECT_EQ(1, mock_resource_alive_count);
     70 
     71   resource_tracker().DidDeleteInstance(instance);
     72   resource = NULL;
     73   EXPECT_FALSE(resource_tracker().GetResource(pp_resource));
     74 }
     75 
     76 // Tests when the plugin is holding a ref to a resource when the instance is
     77 // deleted.
     78 TEST_F(ResourceTrackerTest, InstanceDeletedWithPluginRef) {
     79   // Make a resource with one ref held by the plugin, and delete the instance.
     80   PP_Instance instance = 0x2345678;
     81   ProxyAutoLock lock;
     82   resource_tracker().DidCreateInstance(instance);
     83   MyMockResource* resource = new MyMockResource(instance);
     84   resource->GetReference();
     85   EXPECT_EQ(1, mock_resource_alive_count);
     86   resource_tracker().DidDeleteInstance(instance);
     87 
     88   // The resource should have been deleted, and before it was, it should have
     89   // received a "last plugin ref was deleted" notification.
     90   EXPECT_EQ(0, mock_resource_alive_count);
     91   EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
     92   EXPECT_EQ(0, instance_was_deleted_count);
     93 }
     94 
     95 // Test when the plugin and the internal implementation (via scoped_refptr) is
     96 // holding a ref to a resource when the instance is deleted.
     97 TEST_F(ResourceTrackerTest, InstanceDeletedWithBothRefed) {
     98   // Create a new instance.
     99   PP_Instance instance = 0x3456789;
    100   ProxyAutoLock lock;
    101 
    102   // Make a resource with one ref held by the plugin and one ref held by us
    103   // (outlives the plugin), and delete the instance.
    104   resource_tracker().DidCreateInstance(instance);
    105   scoped_refptr<MyMockResource> resource = new MyMockResource(instance);
    106   resource->GetReference();
    107   EXPECT_EQ(1, mock_resource_alive_count);
    108   resource_tracker().DidDeleteInstance(instance);
    109 
    110   // The resource should NOT have been deleted, and it should have received both
    111   // a "last plugin ref was deleted" and a "instance was deleted" notification.
    112   EXPECT_EQ(1, mock_resource_alive_count);
    113   EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
    114   EXPECT_EQ(1, instance_was_deleted_count);
    115   EXPECT_EQ(0, resource->pp_instance());
    116 
    117   resource = NULL;
    118   EXPECT_EQ(0, mock_resource_alive_count);
    119 }
    120 
    121 }  // namespace ppapi
    122