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