diff options
author | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-23 20:01:21 +0000 |
---|---|---|
committer | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-23 20:01:21 +0000 |
commit | 725c05196e3a8bcfc9b0114ff920252c67d54dd3 (patch) | |
tree | e078f6c8df5fb197cfb1c31d07384efafce4066c /ppapi/proxy/ppp_instance_private_proxy_unittest.cc | |
parent | 0ce348504238ae1aeb7e2555ea21301b0a428214 (diff) | |
download | chromium_src-725c05196e3a8bcfc9b0114ff920252c67d54dd3.zip chromium_src-725c05196e3a8bcfc9b0114ff920252c67d54dd3.tar.gz chromium_src-725c05196e3a8bcfc9b0114ff920252c67d54dd3.tar.bz2 |
Add a test for PPP_Instance_Private_Proxy, to verify reference counting.
BUG=90240
TEST=this test
Review URL: http://codereview.chromium.org/7974013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102556 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy/ppp_instance_private_proxy_unittest.cc')
-rw-r--r-- | ppapi/proxy/ppp_instance_private_proxy_unittest.cc | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/ppapi/proxy/ppp_instance_private_proxy_unittest.cc b/ppapi/proxy/ppp_instance_private_proxy_unittest.cc new file mode 100644 index 0000000..a192154 --- /dev/null +++ b/ppapi/proxy/ppp_instance_private_proxy_unittest.cc @@ -0,0 +1,191 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/c/dev/ppp_class_deprecated.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/c/ppb_var.h" +#include "ppapi/c/ppp_instance.h" +#include "ppapi/c/private/ppp_instance_private.h" +#include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_proxy_test.h" + +namespace ppapi { +namespace proxy { + +namespace { +const PP_Instance kInstance = 0xdeadbeef; + +PP_Var MakeObjectVar(int64_t object_id) { + PP_Var ret; + ret.type = PP_VARTYPE_OBJECT; + ret.value.as_id = object_id; + return ret; +} + +PluginDispatcher* plugin_dispatcher = NULL; +// Return the plugin-side proxy for PPB_Var_Deprecated. +const PPB_Var_Deprecated* plugin_var_deprecated_if() { + // The test code must set the plugin dispatcher. + CHECK(plugin_dispatcher); + // Grab the plugin-side proxy for PPB_Var_Deprecated (for CreateObject). + return static_cast<const PPB_Var_Deprecated*>( + plugin_dispatcher->GetBrowserInterface( + PPB_VAR_DEPRECATED_INTERFACE)); +} + +// Mock PPP_Instance_Private. +PP_Var instance_obj; +PP_Var GetInstanceObject(PP_Instance /*instance*/) { + // The 1 ref we got from CreateObject will be passed to the host. We want to + // have a ref of our own. + plugin_var_deprecated_if()->AddRef(instance_obj); + return instance_obj; +} + +PPP_Instance_Private ppp_instance_private_mock = { + &GetInstanceObject +}; + +// We need to mock PPP_Instance, so that we can create and destroy the pretend +// instance that PPP_Instance_Private uses. +PP_Bool DidCreate(PP_Instance /*instance*/, uint32_t /*argc*/, + const char* /*argn*/[], const char* /*argv*/[]) { + // Create an object var. This should exercise the typical path for creating + // instance objects. + instance_obj = + plugin_var_deprecated_if()->CreateObject(kInstance, NULL, NULL); + return PP_TRUE; +} + +void DidDestroy(PP_Instance /*instance*/) { + // Decrement the reference count for our instance object. It should be + // deleted. + plugin_var_deprecated_if()->Release(instance_obj); +} + +PPP_Instance_1_0 ppp_instance_mock = { &DidCreate, &DidDestroy }; + +} // namespace + +// Mock PPB_Var_Deprecated, so that we can emulate creating an Object Var. +std::map<int64_t, int> id_refcount_map; +void AddRefVar(PP_Var var) { + CHECK(var.type >= PP_VARTYPE_STRING); // Must be a ref-counted type. + CHECK(id_refcount_map.find(var.value.as_id) != id_refcount_map.end()); + ++id_refcount_map[var.value.as_id]; +} + +void ReleaseVar(PP_Var var) { + CHECK(var.type >= PP_VARTYPE_STRING); // Must be a ref-counted type. + std::map<int64_t, int>::iterator iter = id_refcount_map.find(var.value.as_id); + CHECK(iter != id_refcount_map.end()); + CHECK(iter->second > 0); + if (--(iter->second) == 0) + id_refcount_map.erase(iter); +} + +PP_Var CreateObject(PP_Instance instance, + const PPP_Class_Deprecated* /*ppp_class*/, + void* /*ppp_class_data*/) { + static int64_t last_id = 0; + ++last_id; + // Set the refcount to 0. It should really be 1, but that ref gets passed to + // the plugin immediately (and we don't emulate all of that behavior here). + id_refcount_map[last_id] = 0; + return MakeObjectVar(last_id); +} + +const PPB_Var_Deprecated ppb_var_deprecated_mock = { + &AddRefVar, + &ReleaseVar, + NULL, // VarFromUtf8 + NULL, // VarToUtf8 + NULL, // HasProperty + NULL, // HasMethod + NULL, // GetProperty + NULL, // EnumerateProperties + NULL, // SetProperty + NULL, // RemoveProperty + NULL, // Call + NULL, // Construct + NULL, // IsInstanceOf + &CreateObject +}; + +const PPB_Var ppb_var_mock = { &AddRefVar, &ReleaseVar }; + +class PPP_Instance_Private_ProxyTest : public TwoWayTest { + public: + PPP_Instance_Private_ProxyTest() + : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { + plugin().RegisterTestInterface(PPP_INSTANCE_PRIVATE_INTERFACE, + &ppp_instance_private_mock); + plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0, + &ppp_instance_mock); + host().RegisterTestInterface(PPB_VAR_DEPRECATED_INTERFACE, + &ppb_var_deprecated_mock); + host().RegisterTestInterface(PPB_VAR_INTERFACE, + &ppb_var_mock); + } +}; + +TEST_F(PPP_Instance_Private_ProxyTest, PPPInstancePrivate) { + // This test controls its own instance; we can't use the one that + // PluginProxyTestHarness provides. + ASSERT_NE(kInstance, pp_instance()); + HostDispatcher::SetForInstance(kInstance, host().host_dispatcher()); + + // This file-local global is used by the PPP_Instance mock above in order to + // access PPB_Var_Deprecated. + plugin_dispatcher = plugin().plugin_dispatcher(); + + // Grab the host-side proxy for PPP_Instance and PPP_Instance_Private. + const PPP_Instance_Private* ppp_instance_private = + static_cast<const PPP_Instance_Private*>( + host().host_dispatcher()->GetProxiedInterface( + PPP_INSTANCE_PRIVATE_INTERFACE)); + const PPP_Instance_1_0* ppp_instance = static_cast<const PPP_Instance_1_0*>( + host().host_dispatcher()->GetProxiedInterface( + PPP_INSTANCE_INTERFACE_1_0)); + + // Initialize an Instance, so that the plugin-side machinery will work + // properly. + EXPECT_EQ(PP_TRUE, ppp_instance->DidCreate(kInstance, 0, NULL, NULL)); + + // Now instance_obj is valid and should have a ref-count of 1. + PluginVarTracker& plugin_var_tracker = + PluginResourceTracker::GetInstance()->var_tracker(); + // Check the plugin-side reference count. + EXPECT_EQ(1, plugin_var_tracker.GetRefCountForObject(instance_obj)); + // Check the host-side var and reference count. + ASSERT_EQ(1u, id_refcount_map.size()); + EXPECT_EQ(plugin_var_tracker.GetHostObject(instance_obj).value.as_id, + id_refcount_map.begin()->first); + EXPECT_EQ(0, id_refcount_map.begin()->second); + + // Call from the browser side to get the instance object. + PP_Var host_obj = ppp_instance_private->GetInstanceObject(kInstance); + EXPECT_EQ(instance_obj.type, host_obj.type); + EXPECT_EQ(host_obj.value.as_id, + plugin_var_tracker.GetHostObject(instance_obj).value.as_id); + EXPECT_EQ(1, plugin_var_tracker.GetRefCountForObject(instance_obj)); + ASSERT_EQ(1u, id_refcount_map.size()); + // The browser should be passed a reference. + EXPECT_EQ(1, id_refcount_map.begin()->second); + + // The plugin is going away; generally, so will all references to its instance + // object. + ReleaseVar(host_obj); + // Destroy the instance. DidDestroy above decrements the reference count for + // instance_obj, so it should also be destroyed. + ppp_instance->DidDestroy(kInstance); + EXPECT_EQ(-1, plugin_var_tracker.GetRefCountForObject(instance_obj)); + // Check the host-side reference count. + EXPECT_EQ(0u, id_refcount_map.size()); +} + +} // namespace proxy +} // namespace ppapi + |