Home | History | Annotate | Download | only in fake_ppapi
      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 
      9 FakeResourceManager::FakeResourceManager() : next_handle_(1) {}
     10 
     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 
     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 
     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 
     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 
     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 
    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 
    126 FakeResourceTracker::~FakeResourceTracker() { delete resource_; }
    127 
    128 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