blob: 6ec62d82a8868931ab8ab580fdb7a6d0760b0e26 [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"
14
15namespace aos {
16namespace testing {
17
18class MutexTest : public ::testing::Test {
19 public:
20 Mutex test_mutex;
21
22 protected:
23 void SetUp() override {
24 SetDieTestMode(true);
25 }
26};
27
28typedef MutexTest MutexDeathTest;
29
30TEST_F(MutexTest, TryLock) {
31 EXPECT_TRUE(test_mutex.TryLock());
32 EXPECT_FALSE(test_mutex.TryLock());
33}
34
35TEST_F(MutexTest, Lock) {
36 test_mutex.Lock();
37 EXPECT_FALSE(test_mutex.TryLock());
38}
39
40TEST_F(MutexTest, Unlock) {
41 test_mutex.Lock();
42 EXPECT_FALSE(test_mutex.TryLock());
43 test_mutex.Unlock();
44 EXPECT_TRUE(test_mutex.TryLock());
45}
46
47// Sees what happens with multiple unlocks.
48TEST_F(MutexDeathTest, RepeatUnlock) {
Brian Silverman5c201e22014-06-12 22:40:28 -070049 logging::Init();
Brian Silverman653491d2014-05-13 16:53:29 -070050 test_mutex.Lock();
51 test_mutex.Unlock();
52 EXPECT_DEATH(
53 {
54 logging::AddImplementation(new util::DeathTestLogImplementation());
55 test_mutex.Unlock();
56 },
57 ".*multiple unlock.*");
58}
59
60// Sees what happens if you unlock without ever locking (or unlocking) it.
61TEST_F(MutexDeathTest, NeverLock) {
Brian Silverman5c201e22014-06-12 22:40:28 -070062 logging::Init();
Brian Silverman653491d2014-05-13 16:53:29 -070063 EXPECT_DEATH(
64 {
65 logging::AddImplementation(new util::DeathTestLogImplementation());
66 test_mutex.Unlock();
67 },
68 ".*multiple unlock.*");
69}
70
71TEST_F(MutexTest, MutexLocker) {
72 {
73 aos::MutexLocker locker(&test_mutex);
74 EXPECT_FALSE(test_mutex.TryLock());
75 }
76 EXPECT_TRUE(test_mutex.TryLock());
77}
78
79TEST_F(MutexTest, MutexUnlocker) {
80 test_mutex.Lock();
81 {
82 aos::MutexUnlocker unlocker(&test_mutex);
83 // If this fails, then something weird is going on and the next line might
84 // hang, so fail immediately.
85 ASSERT_TRUE(test_mutex.TryLock());
86 test_mutex.Unlock();
87 }
88 EXPECT_FALSE(test_mutex.TryLock());
89}
90
91namespace {
92
93class AdderThread : public ::aos::util::Thread {
94 public:
95 AdderThread(int *counter, Mutex *mutex, ::aos::time::Time sleep_before_time,
96 ::aos::time::Time sleep_after_time)
97 : counter_(counter),
98 mutex_(mutex),
99 sleep_before_time_(sleep_before_time),
100 sleep_after_time_(sleep_after_time) {}
101 virtual void Run() override {
102 ::aos::time::SleepFor(sleep_before_time_);
103 MutexLocker locker(mutex_);
104 ++(*counter_);
105 ::aos::time::SleepFor(sleep_after_time_);
106 }
107
108 private:
109 int *const counter_;
110 Mutex *const mutex_;
111 const ::aos::time::Time sleep_before_time_, sleep_after_time_;
112};
113
114} // namespace
115
116// Verifies that ThreadSanitizer understands that a contended mutex establishes
117// a happens-before relationship.
118TEST_F(MutexTest, ThreadSanitizerContended) {
119 int counter = 0;
120 AdderThread threads[2]{
121 {&counter, &test_mutex, ::aos::time::Time::InSeconds(1),
122 ::aos::time::Time::InSeconds(0)},
123 {&counter, &test_mutex, ::aos::time::Time::InSeconds(0),
124 ::aos::time::Time::InSeconds(0)}, };
125 for (auto &c : threads) {
126 c.Start();
127 }
128 for (auto &c : threads) {
129 c.WaitUntilDone();
130 }
131 EXPECT_EQ(2, counter);
132}
133
134// Verifies that ThreadSanitizer understands that an uncontended mutex
135// establishes a happens-before relationship.
136TEST_F(MutexTest, ThreadSanitizerUncontended) {
137 int counter = 0;
138 AdderThread threads[2]{
139 {&counter, &test_mutex, ::aos::time::Time::InSeconds(1),
140 ::aos::time::Time::InSeconds(0)},
141 {&counter, &test_mutex, ::aos::time::Time::InSeconds(0),
142 ::aos::time::Time::InSeconds(0)}, };
143 for (auto &c : threads) {
144 c.Start();
145 }
146 for (auto &c : threads) {
147 c.WaitUntilDone();
148 }
149 EXPECT_EQ(2, counter);
150}
151
152} // namespace testing
153} // namespace aos