blob: 75ba2b625395416b4919130c1ba3fe600de9c445 [file] [log] [blame]
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -07001// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://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, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include <chrono>
16
17#include "gtest/gtest.h"
18#include "pw_chrono/system_clock.h"
19#include "pw_sync/timed_mutex.h"
20
21using pw::chrono::SystemClock;
22using namespace std::chrono_literals;
23
24namespace pw::sync {
25namespace {
26
27extern "C" {
28
29// Functions defined in mutex_facade_test_c.c which call the API from C.
30void pw_sync_TimedMutex_CallLock(pw_sync_TimedMutex* mutex);
31bool pw_sync_TimedMutex_CallTryLock(pw_sync_TimedMutex* mutex);
Ewout van Bekkum5ff8cc52021-09-07 15:46:36 -070032bool pw_sync_TimedMutex_CallTryLockFor(pw_sync_TimedMutex* mutex,
33 pw_chrono_SystemClock_Duration timeout);
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070034bool pw_sync_TimedMutex_CallTryLockUntil(
Ewout van Bekkum5ff8cc52021-09-07 15:46:36 -070035 pw_sync_TimedMutex* mutex, pw_chrono_SystemClock_TimePoint deadline);
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070036void pw_sync_TimedMutex_CallUnlock(pw_sync_TimedMutex* mutex);
37
38} // extern "C"
39
40// We can't control the SystemClock's period configuration, so just in case
41// duration cannot be accurately expressed in integer ticks, round the
42// duration up.
43constexpr SystemClock::duration kRoundedArbitraryDuration =
44 SystemClock::for_at_least(42ms);
45constexpr pw_chrono_SystemClock_Duration kRoundedArbitraryDurationInC =
46 PW_SYSTEM_CLOCK_MS(42);
47
48// TODO(pwbug/291): Add real concurrency tests once we have pw::thread.
49
50TEST(TimedMutex, LockUnlock) {
51 pw::sync::TimedMutex mutex;
52 mutex.lock();
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070053 mutex.unlock();
Ewout van Bekkum262ae732021-11-11 15:00:07 -080054 // TODO(pwbug/291): Ensure it fails to lock when already held by someone else.
55 // EXPECT_FALSE(mutex.try_lock());
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070056}
57
58TimedMutex static_mutex;
59TEST(TimedMutex, LockUnlockStatic) {
60 static_mutex.lock();
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070061 static_mutex.unlock();
Ewout van Bekkum262ae732021-11-11 15:00:07 -080062 // TODO(pwbug/291): Ensure it fails to lock when already held by someone else.
63 // EXPECT_FALSE(static_mutex.try_lock());
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070064}
65
66TEST(TimedMutex, TryLockUnlock) {
67 pw::sync::TimedMutex mutex;
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -070068 const bool locked = mutex.try_lock();
69 EXPECT_TRUE(locked);
70 if (locked) {
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -070071 // EXPECT_FALSE(mutex.try_lock());
72 mutex.unlock();
73 }
Ewout van Bekkum262ae732021-11-11 15:00:07 -080074 // TODO(pwbug/291): Ensure it fails to lock when already held by someone
75 // else.
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070076}
77
78TEST(TimedMutex, TryLockUnlockFor) {
79 pw::sync::TimedMutex mutex;
80
81 SystemClock::time_point before = SystemClock::now();
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -070082 const bool locked = mutex.try_lock_for(kRoundedArbitraryDuration);
83 EXPECT_TRUE(locked);
84 if (locked) {
85 SystemClock::duration time_elapsed = SystemClock::now() - before;
86 EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -070087 mutex.unlock();
88 }
Ewout van Bekkum262ae732021-11-11 15:00:07 -080089 // TODO(pwbug/291): Ensure it blocks and fails to lock when already held by
90 // someone else.
91 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
92 // held by someone else and a zero length duration is used.
93 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
94 // held by someone else and a negative duration is used.
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070095}
96
97TEST(TimedMutex, TryLockUnlockUntil) {
98 pw::sync::TimedMutex mutex;
99
100 const SystemClock::time_point deadline =
101 SystemClock::now() + kRoundedArbitraryDuration;
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -0700102 const bool locked = mutex.try_lock_until(deadline);
103 EXPECT_TRUE(locked);
104 if (locked) {
105 EXPECT_LT(SystemClock::now(), deadline);
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -0700106 mutex.unlock();
107 }
Ewout van Bekkum262ae732021-11-11 15:00:07 -0800108 // TODO(pwbug/291): Ensure it blocks and fails to lock when already held by
109 // someone else.
110 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
111 // held by someone else and now is used.
112 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
113 // held by someone else and a timestamp in the past is used.
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700114}
115
Ewout van Bekkumbaf2fdc2021-09-09 14:11:51 -0700116TEST(VirtualTimedMutex, LockUnlock) {
117 pw::sync::VirtualTimedMutex mutex;
118 mutex.lock();
Ewout van Bekkum262ae732021-11-11 15:00:07 -0800119 // TODO(pwbug/291): Ensure it fails to lock when already held by someone else.
Ewout van Bekkumbaf2fdc2021-09-09 14:11:51 -0700120 // EXPECT_FALSE(mutex.try_lock());
121 mutex.unlock();
122}
123
124VirtualTimedMutex static_virtual_mutex;
125TEST(VirtualTimedMutex, LockUnlockStatic) {
126 static_virtual_mutex.lock();
Ewout van Bekkum262ae732021-11-11 15:00:07 -0800127 // TODO(pwbug/291): Ensure it fails to lock when already held by someone else.
Ewout van Bekkumbaf2fdc2021-09-09 14:11:51 -0700128 // EXPECT_FALSE(static_virtual_mutex.try_lock());
129 static_virtual_mutex.unlock();
130}
131
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700132TEST(TimedMutex, LockUnlockInC) {
133 pw::sync::TimedMutex mutex;
134 pw_sync_TimedMutex_CallLock(&mutex);
135 pw_sync_TimedMutex_CallUnlock(&mutex);
136}
137
138TEST(TimedMutex, TryLockUnlockInC) {
139 pw::sync::TimedMutex mutex;
140 ASSERT_TRUE(pw_sync_TimedMutex_CallTryLock(&mutex));
Ewout van Bekkum262ae732021-11-11 15:00:07 -0800141 // TODO(pwbug/291): Ensure it fails to lock when already held by someone else.
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700142 // EXPECT_FALSE(pw_sync_TimedMutex_CallTryLock(&mutex));
143 pw_sync_TimedMutex_CallUnlock(&mutex);
144}
145
146TEST(TimedMutex, TryLockUnlockForInC) {
147 pw::sync::TimedMutex mutex;
148
149 pw_chrono_SystemClock_TimePoint before = pw_chrono_SystemClock_Now();
150 ASSERT_TRUE(
151 pw_sync_TimedMutex_CallTryLockFor(&mutex, kRoundedArbitraryDurationInC));
152 pw_chrono_SystemClock_Duration time_elapsed =
153 pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
154 EXPECT_LT(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700155 pw_sync_TimedMutex_CallUnlock(&mutex);
Ewout van Bekkum262ae732021-11-11 15:00:07 -0800156 // TODO(pwbug/291): Ensure it blocks and fails to lock when already held by
157 // someone else.
158 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
159 // held by someone else and a zero length duration is used.
160 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
161 // held by someone else and a negative duration is used.
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700162}
163
164TEST(TimedMutex, TryLockUnlockUntilInC) {
165 pw::sync::TimedMutex mutex;
166 pw_chrono_SystemClock_TimePoint deadline;
167 deadline.duration_since_epoch.ticks =
168 pw_chrono_SystemClock_Now().duration_since_epoch.ticks +
169 kRoundedArbitraryDurationInC.ticks;
170 ASSERT_TRUE(pw_sync_TimedMutex_CallTryLockUntil(&mutex, deadline));
171 EXPECT_LT(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
172 deadline.duration_since_epoch.ticks);
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -0700173 pw_sync_TimedMutex_CallUnlock(&mutex);
Ewout van Bekkum262ae732021-11-11 15:00:07 -0800174 // TODO(pwbug/291): Ensure it blocks and fails to lock when already held by
175 // someone else.
176 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
177 // held by someone else and now is used.
178 // TODO(pwbug/291): Ensure it does not block and fails to lock when already
179 // held by someone else and a timestamp in the past is used.
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700180}
181
182} // namespace
183} // namespace pw::sync