fake_var_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_var_manager.h"
6
7#include "gtest/gtest.h"
8
9FakeVarManager::FakeVarManager() : debug(false), next_id_(1) {}
10
11FakeVarManager::~FakeVarManager() {
12  // The ref counts for all vars should be zero.
13  for (VarMap::const_iterator iter = var_map_.begin(); iter != var_map_.end();
14       ++iter) {
15    const FakeVarData& var_data = iter->second;
16    EXPECT_EQ(0, var_data.ref_count) << "Non-zero refcount on "
17                                     << Describe(var_data);
18  }
19}
20
21FakeVarData* FakeVarManager::CreateVarData() {
22  Id id = next_id_++;
23  FakeVarData data;
24  data.id = id;
25  data.ref_count = 1;
26  var_map_[id] = data;
27  return &var_map_[id];
28}
29
30void FakeVarManager::AddRef(PP_Var var) {
31  // From ppb_var.h:
32  //   AddRef() adds a reference to the given var. If this is not a refcounted
33  //   object, this function will do nothing so you can always call it no matter
34  //   what the type.
35
36  FakeVarData* var_data = GetVarData(var);
37  if (!var_data)
38    return;
39
40  EXPECT_GT(var_data->ref_count, 0)
41       << "AddRefing freed " << Describe(*var_data);
42  var_data->ref_count++;
43  if (debug)
44    printf("AddRef of %s [new refcount=%d]\n",
45           Describe(*var_data).c_str(),
46           var_data->ref_count);
47}
48
49std::string FakeVarManager::Describe(const FakeVarData& var_data) {
50  std::stringstream rtn;
51  switch (var_data.type) {
52    case PP_VARTYPE_STRING:
53      rtn << "String with id " << var_data.id <<
54             " with value \"" << var_data.string_value << "\"";
55      break;
56    case PP_VARTYPE_ARRAY:
57      rtn << "Array of size " << var_data.array_value.size()
58          << " with id " << var_data.id;
59      break;
60    case PP_VARTYPE_ARRAY_BUFFER:
61      rtn << "ArrayBuffer of size " << var_data.buffer_value.length
62          << " with id " << var_data.id;
63      break;
64    default:
65      rtn << "resource of type " << var_data.type
66          << " with id " << var_data.id;
67      break;
68  }
69  return rtn.str();
70}
71
72void FakeVarManager::DestroyVarData(FakeVarData* var_data) {
73  // Release each PP_Var in the array
74
75  switch (var_data->type) {
76    case PP_VARTYPE_ARRAY: {
77      std::vector<PP_Var>& vector = var_data->array_value;
78      for (std::vector<PP_Var>::iterator it = vector.begin();
79          it != vector.end(); ++it) {
80        Release(*it);
81      }
82      vector.clear();
83      break;
84    }
85    case PP_VARTYPE_ARRAY_BUFFER:
86      free(var_data->buffer_value.ptr);
87      var_data->buffer_value.ptr = NULL;
88      var_data->buffer_value.length = 0;
89    default:
90      break;
91  }
92}
93
94FakeVarData* FakeVarManager::GetVarData(PP_Var var) {
95  VarMap::iterator iter = var_map_.find(var.value.as_id);
96  if (iter == var_map_.end())
97    return NULL;
98  return &iter->second;
99}
100
101void FakeVarManager::Release(PP_Var var) {
102  // From ppb_var.h:
103  //   Release() removes a reference to given var, deleting it if the internal
104  //   reference count becomes 0. If the given var is not a refcounted object,
105  //   this function will do nothing so you can always call it no matter what
106  //   the type.
107  FakeVarData* var_data = GetVarData(var);
108  if (!var_data) {
109    if (debug)
110      printf("Releasing simple var\n");
111    return;
112  }
113
114  EXPECT_GT(var_data->ref_count, 0)
115      << "Releasing freed " << Describe(*var_data);
116
117  var_data->ref_count--;
118  if (debug)
119    printf("Released %s [new refcount=%d]\n",
120           Describe(*var_data).c_str(),
121           var_data->ref_count);
122
123  if (var_data->ref_count == 0)
124    DestroyVarData(var_data);
125}
126