15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/test_globals.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int mock_resource_alive_count = 0;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int last_plugin_ref_was_deleted_count = 0;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int instance_was_deleted_count = 0;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MyMockResource : public Resource {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MyMockResource(PP_Instance instance) : Resource(OBJECT_IS_IMPL, instance) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_resource_alive_count++;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~MyMockResource() { mock_resource_alive_count--; }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void LastPluginRefWasDeleted() OVERRIDE {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_plugin_ref_was_deleted_count++;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void InstanceWasDeleted() OVERRIDE { instance_was_deleted_count++; }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResourceTrackerTest : public testing::Test {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceTrackerTest() {}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test implementation.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(0, mock_resource_alive_count);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_plugin_ref_was_deleted_count = 0;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance_was_deleted_count = 0;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void TearDown() OVERRIDE {}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceTracker& resource_tracker() { return *globals_.GetResourceTracker(); }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestGlobals globals_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that LastPluginRefWasDeleted is called when the last plugin ref was
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleted but the object lives on.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ResourceTrackerTest, LastPluginRef) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Instance instance = 0x1234567;
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProxyAutoLock lock;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_tracker().DidCreateInstance(instance);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MyMockResource> resource(new MyMockResource(instance));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource pp_resource = resource->GetReference();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(resource_tracker().GetResource(pp_resource));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releasing it should keep the object (because we have a ref) but fire the
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "last plugin ref" message.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_tracker().ReleaseResource(pp_resource);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_resource_alive_count);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_tracker().DidDeleteInstance(instance);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource = NULL;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(resource_tracker().GetResource(pp_resource));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests when the plugin is holding a ref to a resource when the instance is
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleted.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ResourceTrackerTest, InstanceDeletedWithPluginRef) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a resource with one ref held by the plugin, and delete the instance.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Instance instance = 0x2345678;
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProxyAutoLock lock;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_tracker().DidCreateInstance(instance);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MyMockResource* resource = new MyMockResource(instance);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource->GetReference();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_resource_alive_count);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_tracker().DidDeleteInstance(instance);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The resource should have been deleted, and before it was, it should have
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // received a "last plugin ref was deleted" notification.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, mock_resource_alive_count);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, instance_was_deleted_count);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test when the plugin and the internal implementation (via scoped_refptr) is
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// holding a ref to a resource when the instance is deleted.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ResourceTrackerTest, InstanceDeletedWithBothRefed) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a new instance.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Instance instance = 0x3456789;
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProxyAutoLock lock;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a resource with one ref held by the plugin and one ref held by us
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (outlives the plugin), and delete the instance.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_tracker().DidCreateInstance(instance);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MyMockResource> resource = new MyMockResource(instance);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource->GetReference();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_resource_alive_count);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_tracker().DidDeleteInstance(instance);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The resource should NOT have been deleted, and it should have received both
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a "last plugin ref was deleted" and a "instance was deleted" notification.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, mock_resource_alive_count);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, instance_was_deleted_count);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, resource->pp_instance());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource = NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, mock_resource_alive_count);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
122