blob: 11ca6c580748dd2bab1cd5b635a7b362483049dc [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/binary_semaphore.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 binary_semaphore_facade_test_c.c which call the API
30// from C.
31void pw_sync_BinarySemaphore_CallRelease(pw_sync_BinarySemaphore* semaphore);
32void pw_sync_BinarySemaphore_CallAcquire(pw_sync_BinarySemaphore* semaphore);
33bool pw_sync_BinarySemaphore_CallTryAcquire(pw_sync_BinarySemaphore* semaphore);
34bool pw_sync_BinarySemaphore_CallTryAcquireFor(
Ewout van Bekkum5ff8cc52021-09-07 15:46:36 -070035 pw_sync_BinarySemaphore* semaphore, pw_chrono_SystemClock_Duration timeout);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080036bool pw_sync_BinarySemaphore_CallTryAcquireUntil(
37 pw_sync_BinarySemaphore* semaphore,
Ewout van Bekkum5ff8cc52021-09-07 15:46:36 -070038 pw_chrono_SystemClock_TimePoint deadline);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080039ptrdiff_t pw_sync_BinarySemaphore_CallMax(void);
40
41} // extern "C"
42
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080043// We can't control the SystemClock's period configuration, so just in case
44// duration cannot be accurately expressed in integer ticks, round the
Ewout van Bekkum959b8832021-03-11 08:55:01 -080045// duration up.
46constexpr SystemClock::duration kRoundedArbitraryDuration =
47 SystemClock::for_at_least(42ms);
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080048constexpr pw_chrono_SystemClock_Duration kRoundedArbitraryDurationInC =
49 PW_SYSTEM_CLOCK_MS(42);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080050
51TEST(BinarySemaphore, EmptyInitialState) {
52 BinarySemaphore semaphore;
53 EXPECT_FALSE(semaphore.try_acquire());
54}
55
56// TODO(pwbug/291): Add real concurrency tests once we have pw::thread.
57
58TEST(BinarySemaphore, Release) {
59 BinarySemaphore semaphore;
60 semaphore.release();
61 semaphore.release();
62 semaphore.acquire();
63 // Ensure it fails when empty.
64 EXPECT_FALSE(semaphore.try_acquire());
65}
66
67BinarySemaphore empty_initial_semaphore;
68TEST(BinarySemaphore, EmptyInitialStateStatic) {
69 EXPECT_FALSE(empty_initial_semaphore.try_acquire());
70}
71
72BinarySemaphore release_semaphore;
73TEST(BinarySemaphore, ReleaseStatic) {
74 release_semaphore.release();
75 release_semaphore.release();
76 release_semaphore.acquire();
77 // Ensure it fails when empty.
78 EXPECT_FALSE(release_semaphore.try_acquire());
79}
80
81TEST(BinarySemaphore, TryAcquireFor) {
82 BinarySemaphore semaphore;
83 semaphore.release();
84
85 SystemClock::time_point before = SystemClock::now();
86 EXPECT_TRUE(semaphore.try_acquire_for(kRoundedArbitraryDuration));
87 SystemClock::duration time_elapsed = SystemClock::now() - before;
88 EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
89
90 // Ensure it blocks and fails when empty.
91 before = SystemClock::now();
92 EXPECT_FALSE(semaphore.try_acquire_for(kRoundedArbitraryDuration));
93 time_elapsed = SystemClock::now() - before;
94 EXPECT_GE(time_elapsed, kRoundedArbitraryDuration);
95}
96
97TEST(BinarySemaphore, TryAcquireUntil) {
98 BinarySemaphore semaphore;
99 semaphore.release();
100
101 const SystemClock::time_point deadline =
102 SystemClock::now() + kRoundedArbitraryDuration;
103 EXPECT_TRUE(semaphore.try_acquire_until(deadline));
104 EXPECT_LT(SystemClock::now(), deadline);
105
106 // Ensure it blocks and fails when empty.
107 EXPECT_FALSE(semaphore.try_acquire_until(deadline));
108 EXPECT_GE(SystemClock::now(), deadline);
109}
110
111TEST(BinarySemaphore, EmptyInitialStateInC) {
112 BinarySemaphore semaphore;
113 EXPECT_FALSE(pw_sync_BinarySemaphore_CallTryAcquire(&semaphore));
114}
115
116TEST(BinarySemaphore, ReleaseInC) {
117 BinarySemaphore semaphore;
118 pw_sync_BinarySemaphore_CallRelease(&semaphore);
119 pw_sync_BinarySemaphore_CallRelease(&semaphore);
120 pw_sync_BinarySemaphore_CallAcquire(&semaphore);
121 // Ensure it fails when empty.
122 EXPECT_FALSE(pw_sync_BinarySemaphore_CallTryAcquire(&semaphore));
123}
124
125TEST(BinarySemaphore, TryAcquireForInC) {
126 BinarySemaphore semaphore;
127 pw_sync_BinarySemaphore_CallRelease(&semaphore);
128
129 pw_chrono_SystemClock_TimePoint before = pw_chrono_SystemClock_Now();
130 ASSERT_TRUE(pw_sync_BinarySemaphore_CallTryAcquireFor(
131 &semaphore, kRoundedArbitraryDurationInC));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800132 pw_chrono_SystemClock_Duration time_elapsed =
133 pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
134 EXPECT_LT(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800135
136 // Ensure it blocks and fails when empty.
137 before = pw_chrono_SystemClock_Now();
138 EXPECT_FALSE(pw_sync_BinarySemaphore_CallTryAcquireFor(
139 &semaphore, kRoundedArbitraryDurationInC));
140 time_elapsed =
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800141 pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
142 EXPECT_GE(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800143}
144
145TEST(BinarySemaphore, TryAcquireUntilInC) {
146 BinarySemaphore semaphore;
147 pw_sync_BinarySemaphore_CallRelease(&semaphore);
148
149 pw_chrono_SystemClock_TimePoint deadline;
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800150 deadline.duration_since_epoch = {
151 .ticks = pw_chrono_SystemClock_Now().duration_since_epoch.ticks +
152 kRoundedArbitraryDurationInC.ticks,
153 };
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800154 ASSERT_TRUE(
155 pw_sync_BinarySemaphore_CallTryAcquireUntil(&semaphore, deadline));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800156 EXPECT_LT(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
157 deadline.duration_since_epoch.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800158
159 // Ensure it blocks and fails when empty.
160 EXPECT_FALSE(
161 pw_sync_BinarySemaphore_CallTryAcquireUntil(&semaphore, deadline));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800162 EXPECT_GE(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
163 deadline.duration_since_epoch.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800164}
165
166TEST(BinarySemaphore, MaxInC) {
167 EXPECT_EQ(BinarySemaphore::max(), pw_sync_BinarySemaphore_Max());
168}
169
170} // namespace
171} // namespace pw::sync