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