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