summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ppapi/ppapi.gyp20
-rw-r--r--ppapi/proxy/plugin_var_tracker.h1
-rw-r--r--ppapi/proxy/plugin_var_tracker_unittest.cc176
-rw-r--r--ppapi/proxy/run_all_unittests.cc9
4 files changed, 206 insertions, 0 deletions
diff --git a/ppapi/ppapi.gyp b/ppapi/ppapi.gyp
index ae5b4ed..c2c3237 100644
--- a/ppapi/ppapi.gyp
+++ b/ppapi/ppapi.gyp
@@ -647,5 +647,25 @@
}]
],
},
+ {
+ 'target_name': 'ppapi_unittests',
+ 'type': 'executable',
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'msvs_guid': 'C2BD9365-5BD7-44A7-854E-A49E606BE8E4',
+ 'dependencies': [
+ 'ppapi_proxy',
+ '../base/base.gyp:test_support_base',
+ '../ipc/ipc.gyp:test_support_ipc',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'proxy/run_all_unittests.cc',
+
+ 'proxy/plugin_var_tracker_unittest.cc',
+ ],
+ },
],
}
diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h
index 4d6c49c..02e83d5 100644
--- a/ppapi/proxy/plugin_var_tracker.h
+++ b/ppapi/proxy/plugin_var_tracker.h
@@ -83,6 +83,7 @@ class PluginVarTracker {
private:
friend struct DefaultSingletonTraits<PluginVarTracker>;
+ friend class PluginVarTrackerTest;
// Represents a var as received from the host.
struct HostVar {
diff --git a/ppapi/proxy/plugin_var_tracker_unittest.cc b/ppapi/proxy/plugin_var_tracker_unittest.cc
new file mode 100644
index 0000000..52f7168
--- /dev/null
+++ b/ppapi/proxy/plugin_var_tracker_unittest.cc
@@ -0,0 +1,176 @@
+// 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 "ipc/ipc_test_sink.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Var MakeObject(PluginVarTracker::VarID object_id) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = object_id;
+ return ret;
+}
+
+// Creates a PP_Var from the given string ID.
+PP_Var MakeString(PluginVarTracker::VarID string_id) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = string_id;
+ return ret;
+}
+
+} // namespace
+
+class PluginVarTrackerTest : public testing::Test {
+ public:
+ PluginVarTrackerTest() {}
+
+ protected:
+ // Asserts that there is a unique "release object" IPC message in the test
+ // sink. This will return the var ID from the message or -1 if none found.
+ PluginVarTracker::VarID GetObjectIDForUniqueReleaseObject() {
+ const IPC::Message* release_msg = sink_.GetUniqueMessageMatching(
+ PpapiHostMsg_PPBVar_ReleaseObject::ID);
+ if (!release_msg)
+ return -1;
+
+ Tuple1<int64> id;
+ PpapiHostMsg_PPBVar_ReleaseObject::Read(release_msg, &id);
+ return id.a;
+ }
+
+ PluginVarTracker tracker_;
+
+ IPC::TestSink sink_;
+};
+
+TEST_F(PluginVarTrackerTest, Strings) {
+ std::string str("Hello");
+ PluginVarTracker::VarID str_id1 = tracker_.MakeString(str);
+ EXPECT_NE(0, str_id1);
+
+ PluginVarTracker::VarID str_id2 = tracker_.MakeString(
+ str.c_str(), static_cast<uint32_t>(str.size()));
+ EXPECT_NE(0, str_id2);
+
+ // Make sure the strings come out the other end.
+ std::string result = tracker_.GetString(MakeString(str_id1));
+ EXPECT_EQ(str, result);
+ result = tracker_.GetString(MakeString(str_id2));
+ EXPECT_EQ(str, result);
+}
+
+TEST_F(PluginVarTrackerTest, GetHostObject) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Round-trip through the tracker to make sure the host object comes out the
+ // other end.
+ PP_Var plugin_object = tracker_.ReceiveObjectPassRef(host_object, &sink_);
+ PP_Var host_object2 = tracker_.GetHostObject(plugin_object);
+ EXPECT_EQ(PP_VARTYPE_OBJECT, host_object2.type);
+ EXPECT_EQ(host_object.value.as_id, host_object2.value.as_id);
+
+ tracker_.Release(plugin_object);
+}
+
+TEST_F(PluginVarTrackerTest, ReceiveObjectPassRef) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Receive the object, we should have one ref and no messages.
+ PP_Var plugin_object = tracker_.ReceiveObjectPassRef(host_object, &sink_);
+ EXPECT_EQ(0u, sink_.message_count());
+ EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0,
+ tracker_.GetTrackedWithNoReferenceCountForObject(plugin_object));
+
+ // Receive the same object again, we should get the same plugin ID out.
+ PP_Var plugin_object2 = tracker_.ReceiveObjectPassRef(host_object, &sink_);
+ EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id);
+ EXPECT_EQ(2, tracker_.GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0,
+ tracker_.GetTrackedWithNoReferenceCountForObject(plugin_object));
+
+ // It should have sent one message to decerment the refcount in the host.
+ // This is because it only maintains one host refcount for all references
+ // in the plugin, but the host just sent the second one.
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+ sink_.ClearMessages();
+
+ // Release the object, one ref at a time. The second release should free
+ // the tracking data and send a release message to the browser.
+ tracker_.Release(plugin_object);
+ EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_object));
+ tracker_.Release(plugin_object);
+ EXPECT_EQ(-1, tracker_.GetRefCountForObject(plugin_object));
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+}
+
+// Tests freeing objects that have both refcounts and "tracked with no ref".
+TEST_F(PluginVarTrackerTest, FreeTrackedAndReferencedObject) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Phase one: First receive via a "pass ref", then a tracked with no ref.
+ PP_Var plugin_var = tracker_.ReceiveObjectPassRef(host_object, &sink_);
+ PP_Var plugin_var2 = tracker_.TrackObjectWithNoReference(host_object, &sink_);
+ EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id);
+ EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_var));
+ EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var));
+
+ // Free via the refcount, this should release the object to the browser but
+ // maintain the tracked object.
+ tracker_.Release(plugin_var);
+ EXPECT_EQ(0, tracker_.GetRefCountForObject(plugin_var));
+ EXPECT_EQ(1u, sink_.message_count());
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+
+ // Now free via the tracked object, this should free it.
+ tracker_.StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(-1, tracker_.GetRefCountForObject(plugin_var));
+
+ // Phase two: Receive via a tracked, then get an addref.
+ sink_.ClearMessages();
+ plugin_var = tracker_.TrackObjectWithNoReference(host_object, &sink_);
+ plugin_var2 = tracker_.ReceiveObjectPassRef(host_object, &sink_);
+ EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id);
+ EXPECT_EQ(1, tracker_.GetRefCountForObject(plugin_var));
+ EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var));
+
+ // Free via the tracked object, this should have no effect.
+ tracker_.StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(0, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var));
+ EXPECT_EQ(0u, sink_.message_count());
+
+ // Now free via the refcount, this should delete it.
+ tracker_.Release(plugin_var);
+ EXPECT_EQ(-1, tracker_.GetRefCountForObject(plugin_var));
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+}
+
+TEST_F(PluginVarTrackerTest, RecursiveTrackWithNoRef) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Receive a tracked object twice.
+ PP_Var plugin_var = tracker_.TrackObjectWithNoReference(host_object, &sink_);
+ EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var));
+ PP_Var plugin_var2 = tracker_.TrackObjectWithNoReference(host_object, &sink_);
+ EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id);
+ EXPECT_EQ(0, tracker_.GetRefCountForObject(plugin_var));
+ EXPECT_EQ(2, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var));
+
+ // Now release those tracked items, the reference should be freed.
+ tracker_.StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var));
+ tracker_.StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(-1, tracker_.GetTrackedWithNoReferenceCountForObject(plugin_var));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/run_all_unittests.cc b/ppapi/proxy/run_all_unittests.cc
new file mode 100644
index 0000000..7fd6ef2
--- /dev/null
+++ b/ppapi/proxy/run_all_unittests.cc
@@ -0,0 +1,9 @@
+// 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 "base/test/test_suite.h"
+
+int main(int argc, char** argv) {
+ return base::TestSuite(argc, argv).Run();
+}