• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
CheckLockState()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:
CheckLockStateInDestructor()36   CheckLockStateInDestructor() {}
Method()37   void Method() {
38     ++called_num;
39   }
40  private:
41   friend class base::RefCounted<CheckLockStateInDestructor>;
~CheckLockStateInDestructor()42   ~CheckLockStateInDestructor() {
43     CheckLockState();
44   }
45   DISALLOW_COPY_AND_ASSIGN(CheckLockStateInDestructor);
46 };
47 
TestCallback_0()48 void TestCallback_0() {
49   CheckLockState();
50   ++called_num;
51 }
52 
TestCallback_1(int p1)53 void TestCallback_1(int p1) {
54   CheckLockState();
55   ++called_num;
56 }
57 
TestCallback_2(int p1,const std::string & p2)58 void TestCallback_2(int p1, const std::string& p2) {
59   CheckLockState();
60   ++called_num;
61 }
62 
63 struct Param {};
TestCallback_3(int p1,const std::string & p2,Param p3)64 void TestCallback_3(int p1, const std::string& p2, Param p3) {
65   CheckLockState();
66   ++called_num;
67 }
68 
69 }  // namespace
70 
TEST(PpapiProxyLockTest,Locking)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 
TEST(PpapiProxyLockTest,Unlocking)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