blob: b3d136f753d0958a88728770a9e24948c9e68ff7 [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(
35 pw_sync_BinarySemaphore* semaphore,
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080036 pw_chrono_SystemClock_Duration for_at_least);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080037bool pw_sync_BinarySemaphore_CallTryAcquireUntil(
38 pw_sync_BinarySemaphore* semaphore,
39 pw_chrono_SystemClock_TimePoint until_at_least);
40ptrdiff_t pw_sync_BinarySemaphore_CallMax(void);
41
42} // extern "C"
43
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080044// We can't control the SystemClock's period configuration, so just in case
45// duration cannot be accurately expressed in integer ticks, round the
Ewout van Bekkum959b8832021-03-11 08:55:01 -080046// duration up.
47constexpr SystemClock::duration kRoundedArbitraryDuration =
48 SystemClock::for_at_least(42ms);
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080049constexpr pw_chrono_SystemClock_Duration kRoundedArbitraryDurationInC =
50 PW_SYSTEM_CLOCK_MS(42);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -080051
52TEST(BinarySemaphore, EmptyInitialState) {
53 BinarySemaphore semaphore;
54 EXPECT_FALSE(semaphore.try_acquire());
55}
56
57// TODO(pwbug/291): Add real concurrency tests once we have pw::thread.
58
59TEST(BinarySemaphore, Release) {
60 BinarySemaphore semaphore;
61 semaphore.release();
62 semaphore.release();
63 semaphore.acquire();
64 // Ensure it fails when empty.
65 EXPECT_FALSE(semaphore.try_acquire());
66}
67
68BinarySemaphore empty_initial_semaphore;
69TEST(BinarySemaphore, EmptyInitialStateStatic) {
70 EXPECT_FALSE(empty_initial_semaphore.try_acquire());
71}
72
73BinarySemaphore release_semaphore;
74TEST(BinarySemaphore, ReleaseStatic) {
75 release_semaphore.release();
76 release_semaphore.release();
77 release_semaphore.acquire();
78 // Ensure it fails when empty.
79 EXPECT_FALSE(release_semaphore.try_acquire());
80}
81
82TEST(BinarySemaphore, TryAcquireFor) {
83 BinarySemaphore semaphore;
84 semaphore.release();
85
86 SystemClock::time_point before = SystemClock::now();
87 EXPECT_TRUE(semaphore.try_acquire_for(kRoundedArbitraryDuration));
88 SystemClock::duration time_elapsed = SystemClock::now() - before;
89 EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
90
91 // Ensure it blocks and fails when empty.
92 before = SystemClock::now();
93 EXPECT_FALSE(semaphore.try_acquire_for(kRoundedArbitraryDuration));
94 time_elapsed = SystemClock::now() - before;
95 EXPECT_GE(time_elapsed, kRoundedArbitraryDuration);
96}
97
98TEST(BinarySemaphore, TryAcquireUntil) {
99 BinarySemaphore semaphore;
100 semaphore.release();
101
102 const SystemClock::time_point deadline =
103 SystemClock::now() + kRoundedArbitraryDuration;
104 EXPECT_TRUE(semaphore.try_acquire_until(deadline));
105 EXPECT_LT(SystemClock::now(), deadline);
106
107 // Ensure it blocks and fails when empty.
108 EXPECT_FALSE(semaphore.try_acquire_until(deadline));
109 EXPECT_GE(SystemClock::now(), deadline);
110}
111
112TEST(BinarySemaphore, EmptyInitialStateInC) {
113 BinarySemaphore semaphore;
114 EXPECT_FALSE(pw_sync_BinarySemaphore_CallTryAcquire(&semaphore));
115}
116
117TEST(BinarySemaphore, ReleaseInC) {
118 BinarySemaphore semaphore;
119 pw_sync_BinarySemaphore_CallRelease(&semaphore);
120 pw_sync_BinarySemaphore_CallRelease(&semaphore);
121 pw_sync_BinarySemaphore_CallAcquire(&semaphore);
122 // Ensure it fails when empty.
123 EXPECT_FALSE(pw_sync_BinarySemaphore_CallTryAcquire(&semaphore));
124}
125
126TEST(BinarySemaphore, TryAcquireForInC) {
127 BinarySemaphore semaphore;
128 pw_sync_BinarySemaphore_CallRelease(&semaphore);
129
130 pw_chrono_SystemClock_TimePoint before = pw_chrono_SystemClock_Now();
131 ASSERT_TRUE(pw_sync_BinarySemaphore_CallTryAcquireFor(
132 &semaphore, kRoundedArbitraryDurationInC));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800133 pw_chrono_SystemClock_Duration time_elapsed =
134 pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
135 EXPECT_LT(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800136
137 // Ensure it blocks and fails when empty.
138 before = pw_chrono_SystemClock_Now();
139 EXPECT_FALSE(pw_sync_BinarySemaphore_CallTryAcquireFor(
140 &semaphore, kRoundedArbitraryDurationInC));
141 time_elapsed =
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800142 pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
143 EXPECT_GE(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800144}
145
146TEST(BinarySemaphore, TryAcquireUntilInC) {
147 BinarySemaphore semaphore;
148 pw_sync_BinarySemaphore_CallRelease(&semaphore);
149
150 pw_chrono_SystemClock_TimePoint deadline;
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800151 deadline.duration_since_epoch = {
152 .ticks = pw_chrono_SystemClock_Now().duration_since_epoch.ticks +
153 kRoundedArbitraryDurationInC.ticks,
154 };
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800155 ASSERT_TRUE(
156 pw_sync_BinarySemaphore_CallTryAcquireUntil(&semaphore, deadline));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800157 EXPECT_LT(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
158 deadline.duration_since_epoch.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800159
160 // Ensure it blocks and fails when empty.
161 EXPECT_FALSE(
162 pw_sync_BinarySemaphore_CallTryAcquireUntil(&semaphore, deadline));
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800163 EXPECT_GE(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
164 deadline.duration_since_epoch.ticks);
Ewout van Bekkum9618d8a2020-11-09 12:46:52 -0800165}
166
167TEST(BinarySemaphore, MaxInC) {
168 EXPECT_EQ(BinarySemaphore::max(), pw_sync_BinarySemaphore_Max());
169}
170
171} // namespace
172} // namespace pw::sync