fake_var_manager.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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      FakeArrayType& vector = var_data->array_value;
78      for (FakeArrayType::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      break;
90    }
91    case PP_VARTYPE_DICTIONARY: {
92      FakeDictType& dict = var_data->dict_value;
93      for (FakeDictType::iterator it = dict.begin();
94           it != dict.end(); it++) {
95        Release(it->second);
96      }
97      dict.clear();
98      break;
99    }
100    default:
101      break;
102  }
103}
104
105FakeVarData* FakeVarManager::GetVarData(PP_Var var) {
106  VarMap::iterator iter = var_map_.find(var.value.as_id);
107  if (iter == var_map_.end())
108    return NULL;
109  FakeVarData* var_data = &iter->second;
110  EXPECT_GT(var_data->ref_count, 0)
111      << "Accessing freed " << Describe(*var_data);
112  return var_data;
113}
114
115void FakeVarManager::Release(PP_Var var) {
116  // From ppb_var.h:
117  //   Release() removes a reference to given var, deleting it if the internal
118  //   reference count becomes 0. If the given var is not a refcounted object,
119  //   this function will do nothing so you can always call it no matter what
120  //   the type.
121  FakeVarData* var_data = GetVarData(var);
122  if (!var_data) {
123    if (debug)
124      printf("Releasing simple var\n");
125    return;
126  }
127
128  EXPECT_GT(var_data->ref_count, 0)
129      << "Releasing freed " << Describe(*var_data);
130
131  var_data->ref_count--;
132  if (debug)
133    printf("Released %s [new refcount=%d]\n",
134           Describe(*var_data).c_str(),
135           var_data->ref_count);
136
137  if (var_data->ref_count == 0)
138    DestroyVarData(var_data);
139}
140