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