• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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