blob: bd2365acd12cb8bff5ea29a9484b2e0d44c5ed7c [file] [log] [blame]
Brian Silverman653491d2014-05-13 16:53:29 -07001#include "aos/common/mutex.h"
2
3#include <sched.h>
4#include <math.h>
5#include <pthread.h>
6
7#include "gtest/gtest.h"
8
9#include "aos/linux_code/ipc_lib/aos_sync.h"
10#include "aos/common/die.h"
11#include "aos/common/util/death_test_log_implementation.h"
12#include "aos/common/util/thread.h"
13#include "aos/common/time.h"
Brian Silvermandc1eb272014-08-19 14:25:59 -040014#include "aos/common/queue_testutils.h"
15#include "aos/linux_code/ipc_lib/core_lib.h"
Brian Silverman653491d2014-05-13 16:53:29 -070016
17namespace aos {
18namespace testing {
19
20class MutexTest : public ::testing::Test {
21 public:
22 Mutex test_mutex;
23
24 protected:
25 void SetUp() override {
Brian Silvermandc1eb272014-08-19 14:25:59 -040026 ::aos::common::testing::EnableTestLogging();
Brian Silverman653491d2014-05-13 16:53:29 -070027 SetDieTestMode(true);
28 }
29};
30
31typedef MutexTest MutexDeathTest;
Brian Silvermandc1eb272014-08-19 14:25:59 -040032typedef MutexTest MutexLockerTest;
33typedef MutexTest MutexLockerDeathTest;
34typedef MutexTest IPCMutexLockerTest;
35typedef MutexTest IPCMutexLockerDeathTest;
Brian Silverman653491d2014-05-13 16:53:29 -070036
37TEST_F(MutexTest, TryLock) {
Brian Silvermandc1eb272014-08-19 14:25:59 -040038 EXPECT_EQ(Mutex::State::kLocked, test_mutex.TryLock());
39 EXPECT_EQ(Mutex::State::kUnlocked, test_mutex.TryLock());
40
41 test_mutex.Unlock();
Brian Silverman653491d2014-05-13 16:53:29 -070042}
43
44TEST_F(MutexTest, Lock) {
Brian Silvermandc1eb272014-08-19 14:25:59 -040045 ASSERT_FALSE(test_mutex.Lock());
46 EXPECT_EQ(Mutex::State::kUnlocked, test_mutex.TryLock());
47
48 test_mutex.Unlock();
Brian Silverman653491d2014-05-13 16:53:29 -070049}
50
51TEST_F(MutexTest, Unlock) {
Brian Silvermandc1eb272014-08-19 14:25:59 -040052 ASSERT_FALSE(test_mutex.Lock());
53 EXPECT_EQ(Mutex::State::kUnlocked, test_mutex.TryLock());
Brian Silverman653491d2014-05-13 16:53:29 -070054 test_mutex.Unlock();
Brian Silvermandc1eb272014-08-19 14:25:59 -040055 EXPECT_EQ(Mutex::State::kLocked, test_mutex.TryLock());
56
57 test_mutex.Unlock();
Brian Silverman653491d2014-05-13 16:53:29 -070058}
59
60// Sees what happens with multiple unlocks.
61TEST_F(MutexDeathTest, RepeatUnlock) {
Brian Silverman5c201e22014-06-12 22:40:28 -070062 logging::Init();
Brian Silvermandc1eb272014-08-19 14:25:59 -040063 ASSERT_FALSE(test_mutex.Lock());
Brian Silverman653491d2014-05-13 16:53:29 -070064 test_mutex.Unlock();
65 EXPECT_DEATH(
66 {
67 logging::AddImplementation(new util::DeathTestLogImplementation());
68 test_mutex.Unlock();
69 },
70 ".*multiple unlock.*");
71}
72
73// Sees what happens if you unlock without ever locking (or unlocking) it.
74TEST_F(MutexDeathTest, NeverLock) {
Brian Silverman5c201e22014-06-12 22:40:28 -070075 logging::Init();
Brian Silverman653491d2014-05-13 16:53:29 -070076 EXPECT_DEATH(
77 {
78 logging::AddImplementation(new util::DeathTestLogImplementation());
79 test_mutex.Unlock();
80 },
81 ".*multiple unlock.*");
82}
83
Brian Silvermandc1eb272014-08-19 14:25:59 -040084// Sees what happens with multiple locks.
85TEST_F(MutexDeathTest, RepeatLock) {
86 EXPECT_DEATH(
87 {
88 logging::AddImplementation(new util::DeathTestLogImplementation());
89 ASSERT_FALSE(test_mutex.Lock());
90 ASSERT_FALSE(test_mutex.Lock());
91 },
92 ".*multiple lock.*");
Brian Silverman653491d2014-05-13 16:53:29 -070093}
94
Brian Silvermandc1eb272014-08-19 14:25:59 -040095TEST_F(MutexDeathTest, DestroyLocked) {
96 EXPECT_DEATH(
97 {
98 logging::AddImplementation(new util::DeathTestLogImplementation());
99 Mutex new_mutex;
100 ASSERT_FALSE(new_mutex.Lock());
101 },
102 ".*destroying locked mutex.*");
Brian Silverman653491d2014-05-13 16:53:29 -0700103}
104
105namespace {
106
107class AdderThread : public ::aos::util::Thread {
108 public:
109 AdderThread(int *counter, Mutex *mutex, ::aos::time::Time sleep_before_time,
110 ::aos::time::Time sleep_after_time)
111 : counter_(counter),
112 mutex_(mutex),
113 sleep_before_time_(sleep_before_time),
114 sleep_after_time_(sleep_after_time) {}
115 virtual void Run() override {
116 ::aos::time::SleepFor(sleep_before_time_);
117 MutexLocker locker(mutex_);
118 ++(*counter_);
119 ::aos::time::SleepFor(sleep_after_time_);
120 }
121
122 private:
123 int *const counter_;
124 Mutex *const mutex_;
125 const ::aos::time::Time sleep_before_time_, sleep_after_time_;
126};
127
128} // namespace
129
130// Verifies that ThreadSanitizer understands that a contended mutex establishes
131// a happens-before relationship.
132TEST_F(MutexTest, ThreadSanitizerContended) {
133 int counter = 0;
134 AdderThread threads[2]{
Brian Silvermandc1eb272014-08-19 14:25:59 -0400135 {&counter, &test_mutex, ::aos::time::Time::InSeconds(0.2),
Brian Silverman653491d2014-05-13 16:53:29 -0700136 ::aos::time::Time::InSeconds(0)},
137 {&counter, &test_mutex, ::aos::time::Time::InSeconds(0),
138 ::aos::time::Time::InSeconds(0)}, };
139 for (auto &c : threads) {
140 c.Start();
141 }
142 for (auto &c : threads) {
143 c.WaitUntilDone();
144 }
145 EXPECT_EQ(2, counter);
146}
147
148// Verifies that ThreadSanitizer understands that an uncontended mutex
149// establishes a happens-before relationship.
150TEST_F(MutexTest, ThreadSanitizerUncontended) {
151 int counter = 0;
152 AdderThread threads[2]{
Brian Silvermandc1eb272014-08-19 14:25:59 -0400153 {&counter, &test_mutex, ::aos::time::Time::InSeconds(0.2),
Brian Silverman653491d2014-05-13 16:53:29 -0700154 ::aos::time::Time::InSeconds(0)},
155 {&counter, &test_mutex, ::aos::time::Time::InSeconds(0),
156 ::aos::time::Time::InSeconds(0)}, };
157 for (auto &c : threads) {
158 c.Start();
159 }
160 for (auto &c : threads) {
161 c.WaitUntilDone();
162 }
163 EXPECT_EQ(2, counter);
164}
165
Brian Silvermandc1eb272014-08-19 14:25:59 -0400166TEST_F(MutexLockerTest, Basic) {
167 {
168 aos::MutexLocker locker(&test_mutex);
169 EXPECT_EQ(Mutex::State::kUnlocked, test_mutex.TryLock());
170 }
171 EXPECT_EQ(Mutex::State::kLocked, test_mutex.TryLock());
172
173 test_mutex.Unlock();
174}
175
176TEST_F(IPCMutexLockerTest, Basic) {
177 {
178 aos::IPCMutexLocker locker(&test_mutex);
179 EXPECT_EQ(Mutex::State::kUnlocked, test_mutex.TryLock());
180 EXPECT_FALSE(locker.owner_died());
181 }
182 EXPECT_EQ(Mutex::State::kLocked, test_mutex.TryLock());
183
184 test_mutex.Unlock();
185}
186
187TEST_F(IPCMutexLockerDeathTest, NoCheckOwnerDied) {
188 EXPECT_DEATH({ aos::IPCMutexLocker locker(&test_mutex); },
189 "nobody checked if the previous owner of mutex [^ ]+ died.*");
190}
191
Brian Silverman653491d2014-05-13 16:53:29 -0700192} // namespace testing
193} // namespace aos