| 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..783a5bfa94abb0257df3ec31e47c673e44ced3aa
|
| --- /dev/null
|
| +++ b/ppapi/shared_impl/proxy_lock_unittest.cc
|
| @@ -0,0 +1,184 @@
|
| +// 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;
|
| + base::Lock lock;
|
| + globals.set_proxy_lock(&lock);
|
| + 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;
|
| + base::Lock lock;
|
| + globals.set_proxy_lock(&lock);
|
| + 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
|
|
|