xref: /aosp_15_r20/external/libchrome/base/synchronization/lock_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <stdlib.h>
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/debug/activity_tracker.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
13*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker namespace base {
16*635a8641SAndroid Build Coastguard Worker 
17*635a8641SAndroid Build Coastguard Worker // Basic test to make sure that Acquire()/Release()/Try() don't crash ----------
18*635a8641SAndroid Build Coastguard Worker 
19*635a8641SAndroid Build Coastguard Worker class BasicLockTestThread : public PlatformThread::Delegate {
20*635a8641SAndroid Build Coastguard Worker  public:
BasicLockTestThread(Lock * lock)21*635a8641SAndroid Build Coastguard Worker   explicit BasicLockTestThread(Lock* lock) : lock_(lock), acquired_(0) {}
22*635a8641SAndroid Build Coastguard Worker 
ThreadMain()23*635a8641SAndroid Build Coastguard Worker   void ThreadMain() override {
24*635a8641SAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
25*635a8641SAndroid Build Coastguard Worker       lock_->Acquire();
26*635a8641SAndroid Build Coastguard Worker       acquired_++;
27*635a8641SAndroid Build Coastguard Worker       lock_->Release();
28*635a8641SAndroid Build Coastguard Worker     }
29*635a8641SAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
30*635a8641SAndroid Build Coastguard Worker       lock_->Acquire();
31*635a8641SAndroid Build Coastguard Worker       acquired_++;
32*635a8641SAndroid Build Coastguard Worker       PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
33*635a8641SAndroid Build Coastguard Worker       lock_->Release();
34*635a8641SAndroid Build Coastguard Worker     }
35*635a8641SAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
36*635a8641SAndroid Build Coastguard Worker       if (lock_->Try()) {
37*635a8641SAndroid Build Coastguard Worker         acquired_++;
38*635a8641SAndroid Build Coastguard Worker         PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
39*635a8641SAndroid Build Coastguard Worker         lock_->Release();
40*635a8641SAndroid Build Coastguard Worker       }
41*635a8641SAndroid Build Coastguard Worker     }
42*635a8641SAndroid Build Coastguard Worker   }
43*635a8641SAndroid Build Coastguard Worker 
acquired() const44*635a8641SAndroid Build Coastguard Worker   int acquired() const { return acquired_; }
45*635a8641SAndroid Build Coastguard Worker 
46*635a8641SAndroid Build Coastguard Worker  private:
47*635a8641SAndroid Build Coastguard Worker   Lock* lock_;
48*635a8641SAndroid Build Coastguard Worker   int acquired_;
49*635a8641SAndroid Build Coastguard Worker 
50*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
51*635a8641SAndroid Build Coastguard Worker };
52*635a8641SAndroid Build Coastguard Worker 
TEST(LockTest,Basic)53*635a8641SAndroid Build Coastguard Worker TEST(LockTest, Basic) {
54*635a8641SAndroid Build Coastguard Worker   Lock lock;
55*635a8641SAndroid Build Coastguard Worker   BasicLockTestThread thread(&lock);
56*635a8641SAndroid Build Coastguard Worker   PlatformThreadHandle handle;
57*635a8641SAndroid Build Coastguard Worker 
58*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
59*635a8641SAndroid Build Coastguard Worker 
60*635a8641SAndroid Build Coastguard Worker   int acquired = 0;
61*635a8641SAndroid Build Coastguard Worker   for (int i = 0; i < 5; i++) {
62*635a8641SAndroid Build Coastguard Worker     lock.Acquire();
63*635a8641SAndroid Build Coastguard Worker     acquired++;
64*635a8641SAndroid Build Coastguard Worker     lock.Release();
65*635a8641SAndroid Build Coastguard Worker   }
66*635a8641SAndroid Build Coastguard Worker   for (int i = 0; i < 10; i++) {
67*635a8641SAndroid Build Coastguard Worker     lock.Acquire();
68*635a8641SAndroid Build Coastguard Worker     acquired++;
69*635a8641SAndroid Build Coastguard Worker     PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
70*635a8641SAndroid Build Coastguard Worker     lock.Release();
71*635a8641SAndroid Build Coastguard Worker   }
72*635a8641SAndroid Build Coastguard Worker   for (int i = 0; i < 10; i++) {
73*635a8641SAndroid Build Coastguard Worker     if (lock.Try()) {
74*635a8641SAndroid Build Coastguard Worker       acquired++;
75*635a8641SAndroid Build Coastguard Worker       PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
76*635a8641SAndroid Build Coastguard Worker       lock.Release();
77*635a8641SAndroid Build Coastguard Worker     }
78*635a8641SAndroid Build Coastguard Worker   }
79*635a8641SAndroid Build Coastguard Worker   for (int i = 0; i < 5; i++) {
80*635a8641SAndroid Build Coastguard Worker     lock.Acquire();
81*635a8641SAndroid Build Coastguard Worker     acquired++;
82*635a8641SAndroid Build Coastguard Worker     PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
83*635a8641SAndroid Build Coastguard Worker     lock.Release();
84*635a8641SAndroid Build Coastguard Worker   }
85*635a8641SAndroid Build Coastguard Worker 
86*635a8641SAndroid Build Coastguard Worker   PlatformThread::Join(handle);
87*635a8641SAndroid Build Coastguard Worker 
88*635a8641SAndroid Build Coastguard Worker   EXPECT_GE(acquired, 20);
89*635a8641SAndroid Build Coastguard Worker   EXPECT_GE(thread.acquired(), 20);
90*635a8641SAndroid Build Coastguard Worker }
91*635a8641SAndroid Build Coastguard Worker 
92*635a8641SAndroid Build Coastguard Worker // Test that Try() works as expected -------------------------------------------
93*635a8641SAndroid Build Coastguard Worker 
94*635a8641SAndroid Build Coastguard Worker class TryLockTestThread : public PlatformThread::Delegate {
95*635a8641SAndroid Build Coastguard Worker  public:
TryLockTestThread(Lock * lock)96*635a8641SAndroid Build Coastguard Worker   explicit TryLockTestThread(Lock* lock) : lock_(lock), got_lock_(false) {}
97*635a8641SAndroid Build Coastguard Worker 
ThreadMain()98*635a8641SAndroid Build Coastguard Worker   void ThreadMain() override {
99*635a8641SAndroid Build Coastguard Worker     got_lock_ = lock_->Try();
100*635a8641SAndroid Build Coastguard Worker     if (got_lock_)
101*635a8641SAndroid Build Coastguard Worker       lock_->Release();
102*635a8641SAndroid Build Coastguard Worker   }
103*635a8641SAndroid Build Coastguard Worker 
got_lock() const104*635a8641SAndroid Build Coastguard Worker   bool got_lock() const { return got_lock_; }
105*635a8641SAndroid Build Coastguard Worker 
106*635a8641SAndroid Build Coastguard Worker  private:
107*635a8641SAndroid Build Coastguard Worker   Lock* lock_;
108*635a8641SAndroid Build Coastguard Worker   bool got_lock_;
109*635a8641SAndroid Build Coastguard Worker 
110*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(TryLockTestThread);
111*635a8641SAndroid Build Coastguard Worker };
112*635a8641SAndroid Build Coastguard Worker 
TEST(LockTest,TryLock)113*635a8641SAndroid Build Coastguard Worker TEST(LockTest, TryLock) {
114*635a8641SAndroid Build Coastguard Worker   Lock lock;
115*635a8641SAndroid Build Coastguard Worker 
116*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(lock.Try());
117*635a8641SAndroid Build Coastguard Worker   // We now have the lock....
118*635a8641SAndroid Build Coastguard Worker 
119*635a8641SAndroid Build Coastguard Worker   // This thread will not be able to get the lock.
120*635a8641SAndroid Build Coastguard Worker   {
121*635a8641SAndroid Build Coastguard Worker     TryLockTestThread thread(&lock);
122*635a8641SAndroid Build Coastguard Worker     PlatformThreadHandle handle;
123*635a8641SAndroid Build Coastguard Worker 
124*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
125*635a8641SAndroid Build Coastguard Worker 
126*635a8641SAndroid Build Coastguard Worker     PlatformThread::Join(handle);
127*635a8641SAndroid Build Coastguard Worker 
128*635a8641SAndroid Build Coastguard Worker     ASSERT_FALSE(thread.got_lock());
129*635a8641SAndroid Build Coastguard Worker   }
130*635a8641SAndroid Build Coastguard Worker 
131*635a8641SAndroid Build Coastguard Worker   lock.Release();
132*635a8641SAndroid Build Coastguard Worker 
133*635a8641SAndroid Build Coastguard Worker   // This thread will....
134*635a8641SAndroid Build Coastguard Worker   {
135*635a8641SAndroid Build Coastguard Worker     TryLockTestThread thread(&lock);
136*635a8641SAndroid Build Coastguard Worker     PlatformThreadHandle handle;
137*635a8641SAndroid Build Coastguard Worker 
138*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
139*635a8641SAndroid Build Coastguard Worker 
140*635a8641SAndroid Build Coastguard Worker     PlatformThread::Join(handle);
141*635a8641SAndroid Build Coastguard Worker 
142*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(thread.got_lock());
143*635a8641SAndroid Build Coastguard Worker     // But it released it....
144*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(lock.Try());
145*635a8641SAndroid Build Coastguard Worker   }
146*635a8641SAndroid Build Coastguard Worker 
147*635a8641SAndroid Build Coastguard Worker   lock.Release();
148*635a8641SAndroid Build Coastguard Worker }
149*635a8641SAndroid Build Coastguard Worker 
TEST(LockTest,TryTrackedLock)150*635a8641SAndroid Build Coastguard Worker TEST(LockTest, TryTrackedLock) {
151*635a8641SAndroid Build Coastguard Worker   // Enable the activity tracker.
152*635a8641SAndroid Build Coastguard Worker   debug::GlobalActivityTracker::CreateWithLocalMemory(64 << 10, 0, "", 3, 0);
153*635a8641SAndroid Build Coastguard Worker 
154*635a8641SAndroid Build Coastguard Worker   Lock lock;
155*635a8641SAndroid Build Coastguard Worker 
156*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(lock.Try());
157*635a8641SAndroid Build Coastguard Worker   // We now have the lock....
158*635a8641SAndroid Build Coastguard Worker 
159*635a8641SAndroid Build Coastguard Worker   // This thread will not be able to get the lock.
160*635a8641SAndroid Build Coastguard Worker   {
161*635a8641SAndroid Build Coastguard Worker     TryLockTestThread thread(&lock);
162*635a8641SAndroid Build Coastguard Worker     PlatformThreadHandle handle;
163*635a8641SAndroid Build Coastguard Worker 
164*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
165*635a8641SAndroid Build Coastguard Worker 
166*635a8641SAndroid Build Coastguard Worker     PlatformThread::Join(handle);
167*635a8641SAndroid Build Coastguard Worker 
168*635a8641SAndroid Build Coastguard Worker     ASSERT_FALSE(thread.got_lock());
169*635a8641SAndroid Build Coastguard Worker   }
170*635a8641SAndroid Build Coastguard Worker 
171*635a8641SAndroid Build Coastguard Worker   lock.Release();
172*635a8641SAndroid Build Coastguard Worker 
173*635a8641SAndroid Build Coastguard Worker   // This thread will....
174*635a8641SAndroid Build Coastguard Worker   {
175*635a8641SAndroid Build Coastguard Worker     TryLockTestThread thread(&lock);
176*635a8641SAndroid Build Coastguard Worker     PlatformThreadHandle handle;
177*635a8641SAndroid Build Coastguard Worker 
178*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
179*635a8641SAndroid Build Coastguard Worker 
180*635a8641SAndroid Build Coastguard Worker     PlatformThread::Join(handle);
181*635a8641SAndroid Build Coastguard Worker 
182*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(thread.got_lock());
183*635a8641SAndroid Build Coastguard Worker     // But it released it....
184*635a8641SAndroid Build Coastguard Worker     ASSERT_TRUE(lock.Try());
185*635a8641SAndroid Build Coastguard Worker   }
186*635a8641SAndroid Build Coastguard Worker 
187*635a8641SAndroid Build Coastguard Worker   lock.Release();
188*635a8641SAndroid Build Coastguard Worker   debug::GlobalActivityTracker::ReleaseForTesting();
189*635a8641SAndroid Build Coastguard Worker }
190*635a8641SAndroid Build Coastguard Worker 
191*635a8641SAndroid Build Coastguard Worker // Tests that locks actually exclude -------------------------------------------
192*635a8641SAndroid Build Coastguard Worker 
193*635a8641SAndroid Build Coastguard Worker class MutexLockTestThread : public PlatformThread::Delegate {
194*635a8641SAndroid Build Coastguard Worker  public:
MutexLockTestThread(Lock * lock,int * value)195*635a8641SAndroid Build Coastguard Worker   MutexLockTestThread(Lock* lock, int* value) : lock_(lock), value_(value) {}
196*635a8641SAndroid Build Coastguard Worker 
197*635a8641SAndroid Build Coastguard Worker   // Static helper which can also be called from the main thread.
DoStuff(Lock * lock,int * value)198*635a8641SAndroid Build Coastguard Worker   static void DoStuff(Lock* lock, int* value) {
199*635a8641SAndroid Build Coastguard Worker     for (int i = 0; i < 40; i++) {
200*635a8641SAndroid Build Coastguard Worker       lock->Acquire();
201*635a8641SAndroid Build Coastguard Worker       int v = *value;
202*635a8641SAndroid Build Coastguard Worker       PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
203*635a8641SAndroid Build Coastguard Worker       *value = v + 1;
204*635a8641SAndroid Build Coastguard Worker       lock->Release();
205*635a8641SAndroid Build Coastguard Worker     }
206*635a8641SAndroid Build Coastguard Worker   }
207*635a8641SAndroid Build Coastguard Worker 
ThreadMain()208*635a8641SAndroid Build Coastguard Worker   void ThreadMain() override { DoStuff(lock_, value_); }
209*635a8641SAndroid Build Coastguard Worker 
210*635a8641SAndroid Build Coastguard Worker  private:
211*635a8641SAndroid Build Coastguard Worker   Lock* lock_;
212*635a8641SAndroid Build Coastguard Worker   int* value_;
213*635a8641SAndroid Build Coastguard Worker 
214*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread);
215*635a8641SAndroid Build Coastguard Worker };
216*635a8641SAndroid Build Coastguard Worker 
TEST(LockTest,MutexTwoThreads)217*635a8641SAndroid Build Coastguard Worker TEST(LockTest, MutexTwoThreads) {
218*635a8641SAndroid Build Coastguard Worker   Lock lock;
219*635a8641SAndroid Build Coastguard Worker   int value = 0;
220*635a8641SAndroid Build Coastguard Worker 
221*635a8641SAndroid Build Coastguard Worker   MutexLockTestThread thread(&lock, &value);
222*635a8641SAndroid Build Coastguard Worker   PlatformThreadHandle handle;
223*635a8641SAndroid Build Coastguard Worker 
224*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
225*635a8641SAndroid Build Coastguard Worker 
226*635a8641SAndroid Build Coastguard Worker   MutexLockTestThread::DoStuff(&lock, &value);
227*635a8641SAndroid Build Coastguard Worker 
228*635a8641SAndroid Build Coastguard Worker   PlatformThread::Join(handle);
229*635a8641SAndroid Build Coastguard Worker 
230*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(2 * 40, value);
231*635a8641SAndroid Build Coastguard Worker }
232*635a8641SAndroid Build Coastguard Worker 
TEST(LockTest,MutexFourThreads)233*635a8641SAndroid Build Coastguard Worker TEST(LockTest, MutexFourThreads) {
234*635a8641SAndroid Build Coastguard Worker   Lock lock;
235*635a8641SAndroid Build Coastguard Worker   int value = 0;
236*635a8641SAndroid Build Coastguard Worker 
237*635a8641SAndroid Build Coastguard Worker   MutexLockTestThread thread1(&lock, &value);
238*635a8641SAndroid Build Coastguard Worker   MutexLockTestThread thread2(&lock, &value);
239*635a8641SAndroid Build Coastguard Worker   MutexLockTestThread thread3(&lock, &value);
240*635a8641SAndroid Build Coastguard Worker   PlatformThreadHandle handle1;
241*635a8641SAndroid Build Coastguard Worker   PlatformThreadHandle handle2;
242*635a8641SAndroid Build Coastguard Worker   PlatformThreadHandle handle3;
243*635a8641SAndroid Build Coastguard Worker 
244*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1));
245*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2));
246*635a8641SAndroid Build Coastguard Worker   ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3));
247*635a8641SAndroid Build Coastguard Worker 
248*635a8641SAndroid Build Coastguard Worker   MutexLockTestThread::DoStuff(&lock, &value);
249*635a8641SAndroid Build Coastguard Worker 
250*635a8641SAndroid Build Coastguard Worker   PlatformThread::Join(handle1);
251*635a8641SAndroid Build Coastguard Worker   PlatformThread::Join(handle2);
252*635a8641SAndroid Build Coastguard Worker   PlatformThread::Join(handle3);
253*635a8641SAndroid Build Coastguard Worker 
254*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(4 * 40, value);
255*635a8641SAndroid Build Coastguard Worker }
256*635a8641SAndroid Build Coastguard Worker 
257*635a8641SAndroid Build Coastguard Worker }  // namespace base
258