blob: ad4696ee3897b71e43f573719adeb97872b3eb00 [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);
32bool pw_sync_TimedMutex_CallTryLockFor(
33 pw_sync_TimedMutex* mutex, pw_chrono_SystemClock_Duration for_at_least);
34bool pw_sync_TimedMutex_CallTryLockUntil(
35 pw_sync_TimedMutex* mutex, pw_chrono_SystemClock_TimePoint until_at_least);
36void 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();
53 // TODO(pwbug/291): Ensure it fails to lock when already held.
54 // EXPECT_FALSE(mutex.try_lock());
55 mutex.unlock();
56}
57
58TimedMutex static_mutex;
59TEST(TimedMutex, LockUnlockStatic) {
60 static_mutex.lock();
61 // TODO(pwbug/291): Ensure it fails to lock when already held.
62 // EXPECT_FALSE(static_mutex.try_lock());
63 static_mutex.unlock();
64}
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) {
71 // TODO(pwbug/291): Ensure it fails to lock when already held.
72 // EXPECT_FALSE(mutex.try_lock());
73 mutex.unlock();
74 }
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070075}
76
77TEST(TimedMutex, TryLockUnlockFor) {
78 pw::sync::TimedMutex mutex;
79
80 SystemClock::time_point before = SystemClock::now();
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -070081 const bool locked = mutex.try_lock_for(kRoundedArbitraryDuration);
82 EXPECT_TRUE(locked);
83 if (locked) {
84 SystemClock::duration time_elapsed = SystemClock::now() - before;
85 EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070086
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -070087 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
88 // before = SystemClock::now();
89 // EXPECT_FALSE(mutex.try_lock_for(kRoundedArbitraryDuration));
90 // time_elapsed = SystemClock::now() - before;
91 /// EXPECT_GE(time_elapsed, kRoundedArbitraryDuration);
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -070092
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -070093 mutex.unlock();
94 }
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 Bekkum6f5b8fb2021-04-06 16:15:22 -0700106
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -0700107 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
108 // EXPECT_FALSE(
109 // mutex.try_lock_until(SystemClock::now() +
110 // kRoundedArbitraryDuration));
111 // EXPECT_GE(SystemClock::now(), deadline);
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700112
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -0700113 mutex.unlock();
114 }
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700115}
116
117TEST(TimedMutex, LockUnlockInC) {
118 pw::sync::TimedMutex mutex;
119 pw_sync_TimedMutex_CallLock(&mutex);
120 pw_sync_TimedMutex_CallUnlock(&mutex);
121}
122
123TEST(TimedMutex, TryLockUnlockInC) {
124 pw::sync::TimedMutex mutex;
125 ASSERT_TRUE(pw_sync_TimedMutex_CallTryLock(&mutex));
126 // TODO(pwbug/291): Ensure it fails to lock when already held.
127 // EXPECT_FALSE(pw_sync_TimedMutex_CallTryLock(&mutex));
128 pw_sync_TimedMutex_CallUnlock(&mutex);
129}
130
131TEST(TimedMutex, TryLockUnlockForInC) {
132 pw::sync::TimedMutex mutex;
133
134 pw_chrono_SystemClock_TimePoint before = pw_chrono_SystemClock_Now();
135 ASSERT_TRUE(
136 pw_sync_TimedMutex_CallTryLockFor(&mutex, kRoundedArbitraryDurationInC));
137 pw_chrono_SystemClock_Duration time_elapsed =
138 pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
139 EXPECT_LT(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
140
141 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
142 // before = pw_chrono_SystemClock_Now();
143 // EXPECT_FALSE(
144 // pw_sync_TimedMutex_CallTryLockFor(&mutex,
145 // kRoundedArbitraryDurationInC));
146 // time_elapsed =
147 // pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
148 // EXPECT_GE(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
149
150 pw_sync_TimedMutex_CallUnlock(&mutex);
151}
152
153TEST(TimedMutex, TryLockUnlockUntilInC) {
154 pw::sync::TimedMutex mutex;
155 pw_chrono_SystemClock_TimePoint deadline;
156 deadline.duration_since_epoch.ticks =
157 pw_chrono_SystemClock_Now().duration_since_epoch.ticks +
158 kRoundedArbitraryDurationInC.ticks;
159 ASSERT_TRUE(pw_sync_TimedMutex_CallTryLockUntil(&mutex, deadline));
160 EXPECT_LT(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
161 deadline.duration_since_epoch.ticks);
162
163 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
164 // EXPECT_FALSE(pw_sync_TimedMutex_CallTryLockUntil(&mutex, deadline));
165 // EXPECT_GE(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
166 // deadline.duration_since_epoch.ticks);
167
Ewout van Bekkumcc9ef832021-04-08 08:51:16 -0700168 pw_sync_TimedMutex_CallUnlock(&mutex);
Ewout van Bekkum6f5b8fb2021-04-06 16:15:22 -0700169}
170
171} // namespace
172} // namespace pw::sync