1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
// 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/resource.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/tracker_base.h"
namespace ppapi {
namespace {
int mock_resource_alive_count = 0;
int last_plugin_ref_was_deleted_count = 0;
int instance_was_deleted_count = 0;
class MyMockResource : public Resource {
public:
MyMockResource(PP_Instance instance) : Resource(instance) {
mock_resource_alive_count++;
}
virtual ~MyMockResource() {
mock_resource_alive_count--;
}
virtual void LastPluginRefWasDeleted() OVERRIDE {
Resource::LastPluginRefWasDeleted();
last_plugin_ref_was_deleted_count++;
}
virtual void InstanceWasDeleted() OVERRIDE {
Resource::InstanceWasDeleted();
instance_was_deleted_count++;
}
};
// Global singleton used by the TrackerBase.
TrackerBase* my_tracker_base = NULL;
TrackerBase* GetMyTrackerBase() {
return my_tracker_base;
}
} // namespace
class ResourceTrackerTest : public testing::Test, public TrackerBase {
public:
ResourceTrackerTest() {}
// Test implementation.
virtual void SetUp() OVERRIDE {
my_tracker_base = this;
TrackerBase::Init(&GetMyTrackerBase);
ASSERT_EQ(0, mock_resource_alive_count);
last_plugin_ref_was_deleted_count = 0;
instance_was_deleted_count = 0;
}
virtual void TearDown() OVERRIDE {
my_tracker_base = NULL;
TrackerBase::Init(NULL);
}
// TrackerBase implementation.
virtual FunctionGroupBase* GetFunctionAPI(
PP_Instance inst,
ppapi::proxy::InterfaceID id) OVERRIDE {
return NULL;
}
virtual VarTracker* GetVarTracker() OVERRIDE {
return NULL;
}
virtual ResourceTracker* GetResourceTracker() OVERRIDE {
return &resource_tracker_;
}
virtual PP_Module GetModuleForInstance(PP_Instance /* instance */) OVERRIDE {
return 0;
}
ResourceTracker& resource_tracker() { return resource_tracker_; }
private:
ResourceTracker resource_tracker_;
};
// Test that LastPluginRefWasDeleted is called when the last plugin ref was
// deleted but the object lives on.
TEST_F(ResourceTrackerTest, LastPluginRef) {
PP_Instance instance = 0x1234567;
resource_tracker().DidCreateInstance(instance);
scoped_refptr<MyMockResource> resource(new MyMockResource(instance));
PP_Resource pp_resource = resource->GetReference();
EXPECT_TRUE(resource_tracker().GetResource(pp_resource));
// Releasing it should keep the object (because we have a ref) but fire the
// "last plugin ref" message.
resource_tracker().ReleaseResource(pp_resource);
EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
EXPECT_EQ(1, mock_resource_alive_count);
resource_tracker().DidDeleteInstance(instance);
resource = NULL;
EXPECT_FALSE(resource_tracker().GetResource(pp_resource));
}
// Tests when the plugin is holding a ref to a resource when the instance is
// deleted.
TEST_F(ResourceTrackerTest, InstanceDeletedWithPluginRef) {
// Make a resource with one ref held by the plugin, and delete the instance.
PP_Instance instance = 0x2345678;
resource_tracker().DidCreateInstance(instance);
MyMockResource* resource = new MyMockResource(instance);
resource->GetReference();
EXPECT_EQ(1, mock_resource_alive_count);
resource_tracker().DidDeleteInstance(instance);
// The resource should have been deleted, and before it was, it should have
// received a "last plugin ref was deleted" notification.
EXPECT_EQ(0, mock_resource_alive_count);
EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
EXPECT_EQ(0, instance_was_deleted_count);
}
// Test when the plugin and the internal implementation (via scoped_refptr) is
// holding a ref to a resource when the instance is deleted.
TEST_F(ResourceTrackerTest, InstanceDeletedWithBothRefed) {
// Create a new instance.
PP_Instance instance = 0x3456789;
// Make a resource with one ref held by the plugin and one ref held by us
// (outlives the plugin), and delete the instance.
resource_tracker().DidCreateInstance(instance);
scoped_refptr<MyMockResource> resource = new MyMockResource(instance);
resource->GetReference();
EXPECT_EQ(1, mock_resource_alive_count);
resource_tracker().DidDeleteInstance(instance);
// The resource should NOT have been deleted, and it should have received both
// a "last plugin ref was deleted" and a "instance was deleted" notification.
EXPECT_EQ(1, mock_resource_alive_count);
EXPECT_EQ(1, last_plugin_ref_was_deleted_count);
EXPECT_EQ(1, instance_was_deleted_count);
EXPECT_EQ(0, resource->pp_instance());
resource = NULL;
EXPECT_EQ(0, mock_resource_alive_count);
}
} // namespace ppapi
|