blob: 30cef1ff8358d175074db2b7ed400991bf1416e7 [file] [log] [blame]
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -08001// 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/mutex.h"
20
21using pw::chrono::SystemClock;
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080022using namespace std::chrono_literals;
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080023
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_Mutex_CallLock(pw_sync_Mutex* mutex);
31bool pw_sync_Mutex_CallTryLock(pw_sync_Mutex* mutex);
32bool pw_sync_Mutex_CallTryLockFor(pw_sync_Mutex* mutex,
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080033 pw_chrono_SystemClock_Duration for_at_least);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080034bool pw_sync_Mutex_CallTryLockUntil(
35 pw_sync_Mutex* mutex, pw_chrono_SystemClock_TimePoint until_at_least);
36void pw_sync_Mutex_CallUnlock(pw_sync_Mutex* mutex);
37
38} // extern "C"
39
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080040// We can't control the SystemClock's period configuration, so just in case
41// duration cannot be accurately expressed in integer ticks, round the
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080042// duration w/ ceil.
43constexpr auto kRoundedArbitraryDuration =
44 std::chrono::ceil<SystemClock::duration>(42ms);
45constexpr pw_chrono_SystemClock_Duration kRoundedArbitraryDurationInC =
46 PW_SYSTEM_CLOCK_MS(42);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080047
48// TODO(pwbug/291): Add real concurrency tests once we have pw::thread.
49
50TEST(Mutex, LockUnlock) {
51 pw::sync::Mutex mutex;
52 mutex.lock();
Ewout van Bekkum6615d852020-12-30 16:29:42 -080053 // TODO(pwbug/291): Ensure it fails to lock when already held.
54 // EXPECT_FALSE(mutex.try_lock());
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080055 mutex.unlock();
56}
57
58Mutex static_mutex;
59TEST(Mutex, LockUnlockStatic) {
60 static_mutex.lock();
Ewout van Bekkum6615d852020-12-30 16:29:42 -080061 // TODO(pwbug/291): Ensure it fails to lock when already held.
62 // EXPECT_FALSE(static_mutex.try_lock());
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080063 static_mutex.unlock();
64}
65
66TEST(Mutex, TryLockUnlock) {
67 pw::sync::Mutex mutex;
68 ASSERT_TRUE(mutex.try_lock());
Ewout van Bekkum6615d852020-12-30 16:29:42 -080069 // TODO(pwbug/291): Ensure it fails to lock when already held.
70 // EXPECT_FALSE(mutex.try_lock());
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080071 mutex.unlock();
72}
73
74TEST(Mutex, TryLockUnlockFor) {
75 pw::sync::Mutex mutex;
76
77 SystemClock::time_point before = SystemClock::now();
78 ASSERT_TRUE(mutex.try_lock_for(kRoundedArbitraryDuration));
79 SystemClock::duration time_elapsed = SystemClock::now() - before;
80 EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
81
Ewout van Bekkum6615d852020-12-30 16:29:42 -080082 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
83 // before = SystemClock::now();
84 // EXPECT_FALSE(mutex.try_lock_for(kRoundedArbitraryDuration));
85 // time_elapsed = SystemClock::now() - before;
86 /// EXPECT_GE(time_elapsed, kRoundedArbitraryDuration);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080087
88 mutex.unlock();
89}
90
91TEST(Mutex, TryLockUnlockUntil) {
92 pw::sync::Mutex mutex;
93
94 const SystemClock::time_point deadline =
95 SystemClock::now() + kRoundedArbitraryDuration;
96 ASSERT_TRUE(mutex.try_lock_until(deadline));
97 EXPECT_LT(SystemClock::now(), deadline);
98
Ewout van Bekkum6615d852020-12-30 16:29:42 -080099 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
100 // EXPECT_FALSE(
101 // mutex.try_lock_until(SystemClock::now() + kRoundedArbitraryDuration));
102 // EXPECT_GE(SystemClock::now(), deadline);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800103
104 mutex.unlock();
105}
106
107TEST(Mutex, LockUnlockInC) {
108 pw::sync::Mutex mutex;
109 pw_sync_Mutex_CallLock(&mutex);
110 pw_sync_Mutex_CallUnlock(&mutex);
111}
112
113TEST(Mutex, TryLockUnlockInC) {
114 pw::sync::Mutex mutex;
115 ASSERT_TRUE(pw_sync_Mutex_CallTryLock(&mutex));
Ewout van Bekkum6615d852020-12-30 16:29:42 -0800116 // TODO(pwbug/291): Ensure it fails to lock when already held.
117 // EXPECT_FALSE(pw_sync_Mutex_CallTryLock(&mutex));
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800118 pw_sync_Mutex_CallUnlock(&mutex);
119}
120
121TEST(Mutex, TryLockUnlockForInC) {
122 pw::sync::Mutex mutex;
123
124 pw_chrono_SystemClock_TimePoint before = pw_chrono_SystemClock_Now();
125 ASSERT_TRUE(
126 pw_sync_Mutex_CallTryLockFor(&mutex, kRoundedArbitraryDurationInC));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800127 pw_chrono_SystemClock_Duration time_elapsed =
128 pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
129 EXPECT_LT(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800130
Ewout van Bekkum6615d852020-12-30 16:29:42 -0800131 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
132 // before = pw_chrono_SystemClock_Now();
133 // EXPECT_FALSE(
134 // pw_sync_Mutex_CallTryLockFor(&mutex, kRoundedArbitraryDurationInC));
135 // time_elapsed =
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800136 // pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
137 // EXPECT_GE(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800138
139 pw_sync_Mutex_CallUnlock(&mutex);
140}
141
142TEST(Mutex, TryLockUnlockUntilInC) {
143 pw::sync::Mutex mutex;
144 pw_chrono_SystemClock_TimePoint deadline;
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800145 deadline.duration_since_epoch.ticks =
146 pw_chrono_SystemClock_Now().duration_since_epoch.ticks +
147 kRoundedArbitraryDurationInC.ticks;
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800148 ASSERT_TRUE(pw_sync_Mutex_CallTryLockUntil(&mutex, deadline));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800149 EXPECT_LT(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
150 deadline.duration_since_epoch.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800151
Ewout van Bekkum6615d852020-12-30 16:29:42 -0800152 // TODO(pwbug/291): Ensure it blocks fails to lock when already held.
153 // EXPECT_FALSE(pw_sync_Mutex_CallTryLockUntil(&mutex, deadline));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800154 // EXPECT_GE(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
155 // deadline.duration_since_epoch.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800156
157 mutex.unlock();
158}
159
160} // namespace
161} // namespace pw::sync