fake_resource_manager.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 9FakeResourceManager::FakeResourceManager() : next_handle_(1) {} 10 11FakeResourceManager::~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 28PP_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 43void 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 59void FakeResourceManager::Release(PP_Resource handle) { 60 sdk_util::AutoLock lock(lock_); 61 ResourceMap::iterator iter = resource_map_.find(handle); 62 ASSERT_NE(resource_map_.end(), iter) << "Releasing unknown resource " 63 << handle; 64 65 FakeResourceTracker* resource_tracker = iter->second; 66 EXPECT_LT(0, resource_tracker->ref_count()) << "Releasing freed resource " 67 << resource_tracker->classname() 68 << "(" << handle 69 << "), created at " 70 << resource_tracker->file() << ":" 71 << resource_tracker->line(); 72 resource_tracker->Release(); 73 // It's OK to access the tracker when its refcount is zero; it doesn't 74 // actually destroy the object until the manager is destroyed. 75 if (resource_tracker->ref_count() == 0) { 76 // Remove the resource from this tracker. 77 FakeResource* resource = resource_tracker->Pass(); 78 // Release the lock before we call Destroy; resources can call 79 // FakeResourceManager::Release(), which will deadlock if we are already 80 // holding the lock. 81 lock.Unlock(); 82 83 resource->Destroy(); 84 } 85} 86 87FakeResourceTracker* FakeResourceManager::Get(PP_Resource handle) { 88 AUTO_LOCK(lock_); 89 ResourceMap::iterator iter = resource_map_.find(handle); 90 if (iter == resource_map_.end()) { 91 // Can't use FAIL() because it tries to return void. 92 EXPECT_TRUE(false) << "Trying to get resource " << handle 93 << " that doesn't exist!"; 94 return NULL; 95 } 96 97 FakeResourceTracker* resource_tracker = iter->second; 98 EXPECT_LT(0, resource_tracker->ref_count()) << "Accessing freed resource " 99 << resource_tracker->classname() 100 << "(" << handle 101 << "), created at " 102 << resource_tracker->file() << ":" 103 << resource_tracker->line(); 104 105 return iter->second; 106} 107 108FakeResourceTracker::FakeResourceTracker(FakeResource* resource, 109 const char* classname, 110 const char* file, 111 int line) 112 : resource_(resource), 113 classname_(classname), 114 file_(file), 115 line_(line), 116 ref_count_(0) {} 117 118FakeResourceTracker::~FakeResourceTracker() { delete resource_; } 119 120bool FakeResourceTracker::CheckType(const char* other_classname) const { 121 if (strcmp(other_classname, classname_) != 0) { 122 // Repeat the expectation, just to print out a nice error message before we 123 // crash. :) 124 EXPECT_STREQ(classname_, other_classname); 125 return false; 126 } 127 128 return true; 129} 130