1// Copyright (c) 2013 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 <string> 6 7#include "base/bind.h" 8#include "base/callback.h" 9#include "base/compiler_specific.h" 10#include "base/logging.h" 11#include "base/memory/ref_counted.h" 12#include "ppapi/shared_impl/proxy_lock.h" 13#include "ppapi/shared_impl/test_globals.h" 14#include "testing/gtest/include/gtest/gtest.h" 15 16namespace ppapi { 17 18namespace { 19 20bool expect_to_be_locked = false; 21void CheckLockState() { 22 if (expect_to_be_locked) { 23 ProxyLock::AssertAcquired(); 24 } else { 25 // If we expect to be unlocked, try to lock. We rely on the checking inside 26 // base::Lock that prevents recursive locking. 27 ProxyAutoLock lock; 28 } 29} 30 31int called_num = 0; 32 33class CheckLockStateInDestructor 34 : public base::RefCounted<CheckLockStateInDestructor> { 35 public: 36 CheckLockStateInDestructor() {} 37 void Method() { ++called_num; } 38 39 private: 40 friend class base::RefCounted<CheckLockStateInDestructor>; 41 ~CheckLockStateInDestructor() { CheckLockState(); } 42 DISALLOW_COPY_AND_ASSIGN(CheckLockStateInDestructor); 43}; 44 45void TestCallback_0() { 46 CheckLockState(); 47 ++called_num; 48} 49 50void TestCallback_1(int p1) { 51 CheckLockState(); 52 ++called_num; 53} 54 55void TestCallback_2(int p1, const std::string& p2) { 56 CheckLockState(); 57 ++called_num; 58} 59 60struct Param {}; 61void TestCallback_3(int p1, const std::string& p2, Param p3) { 62 CheckLockState(); 63 ++called_num; 64} 65 66} // namespace 67 68TEST(PpapiProxyLockTest, Locking) { 69 TestGlobals globals; 70 expect_to_be_locked = true; 71 72 base::Callback<void()> cb0; 73 { 74 ProxyAutoLock lock; 75 cb0 = RunWhileLocked(base::Bind(TestCallback_0)); 76 } 77 cb0.Run(); 78 ASSERT_EQ(1, called_num); 79 called_num = 0; 80 81 { 82 ProxyAutoLock lock; 83 cb0 = RunWhileLocked(base::Bind(TestCallback_1, 123)); 84 } 85 cb0.Run(); 86 ASSERT_EQ(1, called_num); 87 called_num = 0; 88 89 { 90 ProxyAutoLock lock; 91 scoped_refptr<CheckLockStateInDestructor> object = 92 new CheckLockStateInDestructor(); 93 cb0 = 94 RunWhileLocked(base::Bind(&CheckLockStateInDestructor::Method, object)); 95 // Note after this scope, the Callback owns the only reference. 96 } 97 cb0.Run(); 98 ASSERT_EQ(1, called_num); 99 called_num = 0; 100 101 base::Callback<void(int)> cb1; 102 { 103 ProxyAutoLock lock; 104 cb1 = RunWhileLocked(base::Bind(TestCallback_1)); 105 } 106 cb1.Run(123); 107 ASSERT_EQ(1, called_num); 108 called_num = 0; 109 110 base::Callback<void(int, const std::string&)> cb2; 111 { 112 ProxyAutoLock lock; 113 cb2 = RunWhileLocked(base::Bind(TestCallback_2)); 114 } 115 cb2.Run(123, std::string("yo")); 116 ASSERT_EQ(1, called_num); 117 called_num = 0; 118 119 base::Callback<void(int, const std::string&, Param)> cb3; 120 { 121 ProxyAutoLock lock; 122 cb3 = RunWhileLocked(base::Bind(TestCallback_3)); 123 } 124 cb3.Run(123, std::string("yo"), Param()); 125 ASSERT_EQ(1, called_num); 126 called_num = 0; 127 128 base::Callback<void(const std::string&)> cb1_string; 129 { 130 ProxyAutoLock lock; 131 cb1_string = RunWhileLocked(base::Bind(TestCallback_2, 123)); 132 } 133 cb1_string.Run(std::string("yo")); 134 ASSERT_EQ(1, called_num); 135 called_num = 0; 136 137 { 138 ProxyAutoLock lock; 139 cb0 = RunWhileLocked(base::Bind(TestCallback_2, 123, std::string("yo"))); 140 } 141 cb0.Run(); 142 ASSERT_EQ(1, called_num); 143 called_num = 0; 144} 145 146TEST(PpapiProxyLockTest, Unlocking) { 147 TestGlobals globals; 148 expect_to_be_locked = false; 149 // These calls should all try to _unlock_, so we must be locked before 150 // entering them. 151 ProxyAutoLock auto_lock; 152 153 { 154 CallWhileUnlocked(TestCallback_0); 155 ASSERT_EQ(1, called_num); 156 called_num = 0; 157 } 158 { 159 CallWhileUnlocked(TestCallback_1, 123); 160 ASSERT_EQ(1, called_num); 161 called_num = 0; 162 } 163 { 164 // TODO(dmichael): Make const-ref arguments work properly with type 165 // deduction. 166 CallWhileUnlocked<void, int, const std::string&>( 167 TestCallback_2, 123, std::string("yo")); 168 ASSERT_EQ(1, called_num); 169 called_num = 0; 170 } 171 { 172 base::Callback<void()> callback(base::Bind(TestCallback_0)); 173 CallWhileUnlocked(callback); 174 ASSERT_EQ(1, called_num); 175 called_num = 0; 176 } 177} 178 179} // namespace ppapi 180