15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "fake_ppapi/fake_resource_manager.h"
63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "gtest/gtest.h"
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "sdk_util/auto_lock.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)FakeResourceManager::FakeResourceManager() : next_handle_(1) {}
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)FakeResourceManager::~FakeResourceManager() {
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The ref counts for all resources should be zero.
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (ResourceMap::iterator iter = resource_map_.begin();
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       iter != resource_map_.end();
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       ++iter) {
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const FakeResourceTracker* resource_tracker = iter->second;
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    EXPECT_EQ(0, resource_tracker->ref_count()) << "Leaked resource "
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                << resource_tracker->classname()
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                << "(" << iter->first
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                << "), created at "
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                << resource_tracker->file()
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                << ":"
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                << resource_tracker->line();
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delete resource_tracker;
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)PP_Resource FakeResourceManager::Create(FakeResource* resource,
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        const char* classname,
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        const char* file,
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        int line) {
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AUTO_LOCK(lock_);
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PP_Resource handle = next_handle_++;
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FakeResourceTracker* resource_tracker =
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new FakeResourceTracker(resource, classname, file, line);
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::pair<ResourceMap::iterator, bool> result =
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      resource_map_.insert(ResourceMap::value_type(handle, resource_tracker));
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(result.second);
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  result.first->second->AddRef();
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return handle;
413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void FakeResourceManager::AddRef(PP_Resource handle) {
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AUTO_LOCK(lock_);
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ResourceMap::iterator iter = resource_map_.find(handle);
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_NE(resource_map_.end(), iter) << "AddRefing unknown resource "
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       << handle;
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FakeResourceTracker* resource_tracker = iter->second;
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_LT(0, resource_tracker->ref_count()) << "AddRefing freed resource "
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->classname()
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << "(" << handle
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << "), created at "
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->file() << ":"
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->line();
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  resource_tracker->AddRef();
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void FakeResourceManager::Release(PP_Resource handle) {
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (handle == 0)
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  sdk_util::AutoLock lock(lock_);
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ResourceMap::iterator iter = resource_map_.find(handle);
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_NE(resource_map_.end(), iter) << "Releasing unknown resource "
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       << handle;
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FakeResourceTracker* resource_tracker = iter->second;
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_LT(0, resource_tracker->ref_count()) << "Releasing freed resource "
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->classname()
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << "(" << handle
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << "), created at "
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->file() << ":"
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->line();
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  resource_tracker->Release();
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // It's OK to access the tracker when its refcount is zero; it doesn't
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // actually destroy the object until the manager is destroyed.
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (resource_tracker->ref_count() == 0) {
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Remove the resource from this tracker.
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    FakeResource* resource = resource_tracker->Pass();
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Release the lock before we call Destroy; resources can call
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // FakeResourceManager::Release(), which will deadlock if we are already
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // holding the lock.
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    lock.Unlock();
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    resource->Destroy();
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    delete resource;
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)FakeResourceTracker* FakeResourceManager::Get(PP_Resource handle,
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              bool not_found_ok) {
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AUTO_LOCK(lock_);
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ResourceMap::iterator iter = resource_map_.find(handle);
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (iter == resource_map_.end()) {
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!not_found_ok) {
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Can't use FAIL() because it tries to return void.
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      EXPECT_TRUE(false) << "Trying to get resource " << handle
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         << " that doesn't exist!";
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return NULL;
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FakeResourceTracker* resource_tracker = iter->second;
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_LT(0, resource_tracker->ref_count()) << "Accessing freed resource "
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->classname()
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << "(" << handle
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << "), created at "
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->file() << ":"
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              << resource_tracker->line();
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return iter->second;
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)FakeResourceTracker::FakeResourceTracker(FakeResource* resource,
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                         const char* classname,
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                         const char* file,
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                         int line)
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : resource_(resource),
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      classname_(classname),
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      file_(file),
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      line_(line),
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ref_count_(0) {}
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)FakeResourceTracker::~FakeResourceTracker() { delete resource_; }
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool FakeResourceTracker::CheckType(const char* other_classname) const {
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (strcmp(other_classname, classname_) != 0) {
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Repeat the expectation, just to print out a nice error message before we
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // crash. :)
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    EXPECT_STREQ(classname_, other_classname);
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
138