1 // Copyright (C) 2014 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "emugl/common/mutex.h" 16 17 #include "emugl/common/testing/test_thread.h" 18 19 #include <gtest/gtest.h> 20 21 namespace emugl { 22 23 // Check that construction and destruction doesn't crash. 24 TEST(Mutex, ConstructionDestruction) { 25 Mutex lock; 26 } 27 28 // Check that a simple lock + unlock works. 29 TEST(Mutex, LockUnlock) { 30 Mutex lock; 31 lock.lock(); 32 lock.unlock(); 33 } 34 35 // Check that AutoLock compiles and doesn't crash. 36 TEST(Mutex, AutoLock) { 37 Mutex mutex; 38 Mutex::AutoLock lock(mutex); 39 } 40 41 // Wrapper class for threads. Does not use emugl::Thread intentionally. 42 // Common data type used by the following tests below. 43 struct ThreadParams { 44 ThreadParams() : mutex(), counter(0) {} 45 46 Mutex mutex; 47 int counter; 48 }; 49 50 // This thread function uses Mutex::lock/unlock to synchronize a counter 51 // increment operation. 52 static void* threadFunction(void* param) { 53 ThreadParams* p = static_cast<ThreadParams*>(param); 54 55 p->mutex.lock(); 56 p->counter++; 57 p->mutex.unlock(); 58 return NULL; 59 } 60 61 TEST(Mutex, Synchronization) { 62 const size_t kNumThreads = 2000; 63 TestThread* threads[kNumThreads]; 64 ThreadParams p; 65 66 // Create and launch all threads. 67 for (size_t n = 0; n < kNumThreads; ++n) { 68 threads[n] = new TestThread(threadFunction, &p); 69 } 70 71 // Wait until their completion. 72 for (size_t n = 0; n < kNumThreads; ++n) { 73 threads[n]->join(); 74 delete threads[n]; 75 } 76 77 EXPECT_EQ(static_cast<int>(kNumThreads), p.counter); 78 } 79 80 // This thread function uses a Mutex::AutoLock to protect the counter. 81 static void* threadAutoLockFunction(void* param) { 82 ThreadParams* p = static_cast<ThreadParams*>(param); 83 84 Mutex::AutoLock lock(p->mutex); 85 p->counter++; 86 return NULL; 87 } 88 89 TEST(Mutex, AutoLockSynchronization) { 90 const size_t kNumThreads = 2000; 91 TestThread* threads[kNumThreads]; 92 ThreadParams p; 93 94 // Create and launch all threads. 95 for (size_t n = 0; n < kNumThreads; ++n) { 96 threads[n] = new TestThread(threadAutoLockFunction, &p); 97 } 98 99 // Wait until their completion. 100 for (size_t n = 0; n < kNumThreads; ++n) { 101 threads[n]->join(); 102 delete threads[n]; 103 } 104 105 EXPECT_EQ(static_cast<int>(kNumThreads), p.counter); 106 } 107 108 } // namespace emugl 109