Index: ppapi/shared_impl/proxy_lock_unittest.cc |
diff --git a/ppapi/shared_impl/proxy_lock_unittest.cc b/ppapi/shared_impl/proxy_lock_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f0751493ace848dd8db8fbe30a31e55fb87f51e4 |
--- /dev/null |
+++ b/ppapi/shared_impl/proxy_lock_unittest.cc |
@@ -0,0 +1,180 @@ |
+// Copyright (c) 2013 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 <string> |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/compiler_specific.h" |
+#include "base/logging.h" |
+#include "base/memory/ref_counted.h" |
+#include "ppapi/shared_impl/proxy_lock.h" |
+#include "ppapi/shared_impl/test_globals.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace ppapi { |
+ |
+namespace { |
+ |
+bool expect_to_be_locked = false; |
+void CheckLockState() { |
+ if (expect_to_be_locked) { |
+ ProxyLock::AssertAcquired(); |
+ } else { |
+ // If we expect to be unlocked, try to lock. We rely on the checking inside |
+ // base::Lock that prevents recursive locking. |
+ ProxyAutoLock lock; |
+ } |
+} |
+ |
+int called_num = 0; |
+ |
+class CheckLockStateInDestructor |
+ : public base::RefCounted<CheckLockStateInDestructor> { |
+ public: |
+ CheckLockStateInDestructor() {} |
+ void Method() { |
+ ++called_num; |
+ } |
+ private: |
+ friend class base::RefCounted<CheckLockStateInDestructor>; |
+ ~CheckLockStateInDestructor() { |
+ CheckLockState(); |
+ } |
+ DISALLOW_COPY_AND_ASSIGN(CheckLockStateInDestructor); |
+}; |
+ |
+void TestCallback_0() { |
+ CheckLockState(); |
+ ++called_num; |
+} |
+ |
+void TestCallback_1(int p1) { |
+ CheckLockState(); |
+ ++called_num; |
+} |
+ |
+void TestCallback_2(int p1, const std::string& p2) { |
+ CheckLockState(); |
+ ++called_num; |
+} |
+ |
+struct Param {}; |
+void TestCallback_3(int p1, const std::string& p2, Param p3) { |
+ CheckLockState(); |
+ ++called_num; |
+} |
+ |
+} // namespace |
+ |
+TEST(PpapiProxyLockTest, Locking) { |
+ TestGlobals globals; |
+ expect_to_be_locked = true; |
+ |
+ base::Callback<void()> cb0; |
+ { |
+ ProxyAutoLock lock; |
+ cb0 = RunWhileLocked(base::Bind(TestCallback_0)); |
+ } |
+ cb0.Run(); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ |
+ { |
+ ProxyAutoLock lock; |
+ cb0 = RunWhileLocked(base::Bind(TestCallback_1, 123)); |
+ } |
+ cb0.Run(); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ |
+ { |
+ ProxyAutoLock lock; |
+ scoped_refptr<CheckLockStateInDestructor> object = |
+ new CheckLockStateInDestructor(); |
+ cb0 = RunWhileLocked( |
+ base::Bind(&CheckLockStateInDestructor::Method, |
+ object)); |
+ // Note after this scope, the Callback owns the only reference. |
+ } |
+ cb0.Run(); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ |
+ base::Callback<void(int)> cb1; |
+ { |
+ ProxyAutoLock lock; |
+ cb1 = RunWhileLocked(base::Bind(TestCallback_1)); |
+ } |
+ cb1.Run(123); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ |
+ base::Callback<void(int, const std::string&)> cb2; |
+ { |
+ ProxyAutoLock lock; |
+ cb2 = RunWhileLocked(base::Bind(TestCallback_2)); |
+ } |
+ cb2.Run(123, std::string("yo")); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ |
+ base::Callback<void(int, const std::string&, Param)> cb3; |
+ { |
+ ProxyAutoLock lock; |
+ cb3 = RunWhileLocked(base::Bind(TestCallback_3)); |
+ } |
+ cb3.Run(123, std::string("yo"), Param()); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ |
+ base::Callback<void(const std::string&)> cb1_string; |
+ { |
+ ProxyAutoLock lock; |
+ cb1_string = RunWhileLocked(base::Bind(TestCallback_2, 123)); |
+ } |
+ cb1_string.Run(std::string("yo")); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ |
+ { |
+ ProxyAutoLock lock; |
+ cb0 = RunWhileLocked(base::Bind(TestCallback_2, 123, std::string("yo"))); |
+ } |
+ cb0.Run(); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+} |
+ |
+TEST(PpapiProxyLockTest, Unlocking) { |
+ TestGlobals globals; |
+ expect_to_be_locked = false; |
+ // These calls should all try to _unlock_, so we must be locked before |
+ // entering them. |
+ ProxyAutoLock auto_lock; |
+ |
+ { |
+ CallWhileUnlocked(TestCallback_0); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ } { |
+ CallWhileUnlocked(TestCallback_1, 123); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ } { |
+ // TODO(dmichael): Make const-ref arguments work properly with type |
+ // deduction. |
+ CallWhileUnlocked<void, int, const std::string&>( |
+ TestCallback_2, 123, std::string("yo")); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ } { |
+ base::Callback<void()> callback(base::Bind(TestCallback_0)); |
+ CallWhileUnlocked(callback); |
+ ASSERT_EQ(1, called_num); |
+ called_num = 0; |
+ } |
+} |
+ |
+} // namespace ppapi |