1 // Copyright 2014 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 "fake_ppapi/fake_resource_manager.h"
6 #include "gtest/gtest.h"
7 #include "sdk_util/auto_lock.h"
8
FakeResourceManager()9 FakeResourceManager::FakeResourceManager() : next_handle_(1) {}
10
~FakeResourceManager()11 FakeResourceManager::~FakeResourceManager() {
12 // The ref counts for all resources should be zero.
13 for (ResourceMap::iterator iter = resource_map_.begin();
14 iter != resource_map_.end();
15 ++iter) {
16 const FakeResourceTracker* resource_tracker = iter->second;
17 EXPECT_EQ(0, resource_tracker->ref_count()) << "Leaked resource "
18 << resource_tracker->classname()
19 << "(" << iter->first
20 << "), created at "
21 << resource_tracker->file()
22 << ":"
23 << resource_tracker->line();
24 delete resource_tracker;
25 }
26 }
27
Create(FakeResource * resource,const char * classname,const char * file,int line)28 PP_Resource FakeResourceManager::Create(FakeResource* resource,
29 const char* classname,
30 const char* file,
31 int line) {
32 AUTO_LOCK(lock_);
33 PP_Resource handle = next_handle_++;
34 FakeResourceTracker* resource_tracker =
35 new FakeResourceTracker(resource, classname, file, line);
36 std::pair<ResourceMap::iterator, bool> result =
37 resource_map_.insert(ResourceMap::value_type(handle, resource_tracker));
38 EXPECT_TRUE(result.second);
39 result.first->second->AddRef();
40 return handle;
41 }
42
AddRef(PP_Resource handle)43 void FakeResourceManager::AddRef(PP_Resource handle) {
44 AUTO_LOCK(lock_);
45 ResourceMap::iterator iter = resource_map_.find(handle);
46 ASSERT_NE(resource_map_.end(), iter) << "AddRefing unknown resource "
47 << handle;
48
49 FakeResourceTracker* resource_tracker = iter->second;
50 EXPECT_LT(0, resource_tracker->ref_count()) << "AddRefing freed resource "
51 << resource_tracker->classname()
52 << "(" << handle
53 << "), created at "
54 << resource_tracker->file() << ":"
55 << resource_tracker->line();
56 resource_tracker->AddRef();
57 }
58
Release(PP_Resource handle)59 void FakeResourceManager::Release(PP_Resource handle) {
60 if (handle == 0)
61 return;
62
63 sdk_util::AutoLock lock(lock_);
64 ResourceMap::iterator iter = resource_map_.find(handle);
65 ASSERT_NE(resource_map_.end(), iter) << "Releasing unknown resource "
66 << handle;
67
68 FakeResourceTracker* resource_tracker = iter->second;
69 EXPECT_LT(0, resource_tracker->ref_count()) << "Releasing freed resource "
70 << resource_tracker->classname()
71 << "(" << handle
72 << "), created at "
73 << resource_tracker->file() << ":"
74 << resource_tracker->line();
75 resource_tracker->Release();
76 // It's OK to access the tracker when its refcount is zero; it doesn't
77 // actually destroy the object until the manager is destroyed.
78 if (resource_tracker->ref_count() == 0) {
79 // Remove the resource from this tracker.
80 FakeResource* resource = resource_tracker->Pass();
81 // Release the lock before we call Destroy; resources can call
82 // FakeResourceManager::Release(), which will deadlock if we are already
83 // holding the lock.
84 lock.Unlock();
85
86 resource->Destroy();
87 delete resource;
88 }
89 }
90
Get(PP_Resource handle,bool not_found_ok)91 FakeResourceTracker* FakeResourceManager::Get(PP_Resource handle,
92 bool not_found_ok) {
93 AUTO_LOCK(lock_);
94 ResourceMap::iterator iter = resource_map_.find(handle);
95 if (iter == resource_map_.end()) {
96 if (!not_found_ok) {
97 // Can't use FAIL() because it tries to return void.
98 EXPECT_TRUE(false) << "Trying to get resource " << handle
99 << " that doesn't exist!";
100 }
101
102 return NULL;
103 }
104
105 FakeResourceTracker* resource_tracker = iter->second;
106 EXPECT_LT(0, resource_tracker->ref_count()) << "Accessing freed resource "
107 << resource_tracker->classname()
108 << "(" << handle
109 << "), created at "
110 << resource_tracker->file() << ":"
111 << resource_tracker->line();
112
113 return iter->second;
114 }
115
FakeResourceTracker(FakeResource * resource,const char * classname,const char * file,int line)116 FakeResourceTracker::FakeResourceTracker(FakeResource* resource,
117 const char* classname,
118 const char* file,
119 int line)
120 : resource_(resource),
121 classname_(classname),
122 file_(file),
123 line_(line),
124 ref_count_(0) {}
125
~FakeResourceTracker()126 FakeResourceTracker::~FakeResourceTracker() { delete resource_; }
127
CheckType(const char * other_classname) const128 bool FakeResourceTracker::CheckType(const char* other_classname) const {
129 if (strcmp(other_classname, classname_) != 0) {
130 // Repeat the expectation, just to print out a nice error message before we
131 // crash. :)
132 EXPECT_STREQ(classname_, other_classname);
133 return false;
134 }
135
136 return true;
137 }
138