Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_sync / counting_semaphore_facade_test.cc
1 // 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/counting_semaphore.h"
20
21 using pw::chrono::SystemClock;
22 using namespace std::chrono_literals;
23
24 namespace pw::sync {
25 namespace {
26
27 extern "C" {
28
29 // Functions defined in counting_semaphore_facade_test_c.c which call the API
30 // from C.
31 void pw_sync_CountingSemaphore_CallRelease(
32     pw_sync_CountingSemaphore* semaphore);
33 void pw_sync_CountingSemaphore_CallReleaseNum(
34     pw_sync_CountingSemaphore* semaphore, ptrdiff_t update);
35 void pw_sync_CountingSemaphore_CallAcquire(
36     pw_sync_CountingSemaphore* semaphore);
37 bool pw_sync_CountingSemaphore_CallTryAcquire(
38     pw_sync_CountingSemaphore* semaphore);
39 bool pw_sync_CountingSemaphore_CallTryAcquireFor(
40     pw_sync_CountingSemaphore* semaphore,
41     pw_chrono_SystemClock_Duration for_at_least);
42 bool pw_sync_CountingSemaphore_CallTryAcquireUntil(
43     pw_sync_CountingSemaphore* semaphore,
44     pw_chrono_SystemClock_TimePoint until_at_least);
45 ptrdiff_t pw_sync_CountingSemaphore_CallMax(void);
46
47 }  // extern "C"
48
49 // We can't control the SystemClock's period configuration, so just in case
50 // duration cannot be accurately expressed in integer ticks, round the
51 // duration w/ ceil.
52 constexpr auto kRoundedArbitraryDuration =
53     std::chrono::ceil<SystemClock::duration>(42ms);
54 constexpr pw_chrono_SystemClock_Duration kRoundedArbitraryDurationInC =
55     PW_SYSTEM_CLOCK_MS(42);
56
57 TEST(CountingSemaphore, EmptyInitialState) {
58   CountingSemaphore semaphore;
59   EXPECT_FALSE(semaphore.try_acquire());
60 }
61
62 // TODO(pwbug/291): Add real concurrency tests once we have pw::thread.
63
64 TEST(CountingSemaphore, SingleRelease) {
65   CountingSemaphore semaphore;
66   semaphore.release();
67   semaphore.release();
68   semaphore.acquire();
69   semaphore.acquire();
70   // Ensure it fails when empty.
71   EXPECT_FALSE(semaphore.try_acquire());
72 }
73
74 CountingSemaphore empty_initial_semaphore;
75 TEST(CountingSemaphore, EmptyInitialStateStatic) {
76   EXPECT_FALSE(empty_initial_semaphore.try_acquire());
77 }
78
79 CountingSemaphore release_semaphore;
80 TEST(CountingSemaphore, ReleaseStatic) {
81   release_semaphore.release();
82   release_semaphore.release();
83   release_semaphore.acquire();
84   release_semaphore.acquire();
85   // Ensure it fails when empty.
86   EXPECT_FALSE(release_semaphore.try_acquire());
87 }
88
89 TEST(CountingSemaphore, MultiRelease) {
90   CountingSemaphore semaphore;
91   semaphore.release(2);
92   semaphore.release(1);
93   semaphore.acquire();
94   semaphore.acquire();
95   semaphore.acquire();
96   // Ensure it fails when empty.
97   EXPECT_FALSE(semaphore.try_acquire());
98 }
99
100 TEST(CountingSemaphore, TryAcquireFor) {
101   CountingSemaphore semaphore;
102   semaphore.release();
103
104   SystemClock::time_point before = SystemClock::now();
105   EXPECT_TRUE(semaphore.try_acquire_for(kRoundedArbitraryDuration));
106   SystemClock::duration time_elapsed = SystemClock::now() - before;
107   EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
108
109   // Ensure it blocks and fails when empty.
110   before = SystemClock::now();
111   EXPECT_FALSE(semaphore.try_acquire_for(kRoundedArbitraryDuration));
112   time_elapsed = SystemClock::now() - before;
113   EXPECT_GE(time_elapsed, kRoundedArbitraryDuration);
114 }
115
116 TEST(CountingSemaphore, TryAcquireUntil) {
117   CountingSemaphore semaphore;
118   semaphore.release();
119
120   const SystemClock::time_point deadline =
121       SystemClock::now() + kRoundedArbitraryDuration;
122   EXPECT_TRUE(semaphore.try_acquire_until(deadline));
123   EXPECT_LT(SystemClock::now(), deadline);
124
125   // Ensure it blocks and fails when empty.
126   EXPECT_FALSE(semaphore.try_acquire_until(deadline));
127   EXPECT_GE(SystemClock::now(), deadline);
128 }
129
130 TEST(CountingSemaphore, EmptyInitialStateInC) {
131   CountingSemaphore semaphore;
132   EXPECT_FALSE(pw_sync_CountingSemaphore_CallTryAcquire(&semaphore));
133 }
134
135 TEST(CountingSemaphore, SingeReleaseInC) {
136   CountingSemaphore semaphore;
137   pw_sync_CountingSemaphore_CallRelease(&semaphore);
138   pw_sync_CountingSemaphore_CallRelease(&semaphore);
139   pw_sync_CountingSemaphore_CallAcquire(&semaphore);
140   pw_sync_CountingSemaphore_CallAcquire(&semaphore);
141   // Ensure it fails when empty.
142   EXPECT_FALSE(pw_sync_CountingSemaphore_CallTryAcquire(&semaphore));
143 }
144
145 TEST(CountingSemaphore, MultiReleaseInC) {
146   CountingSemaphore semaphore;
147   pw_sync_CountingSemaphore_CallReleaseNum(&semaphore, 2);
148   pw_sync_CountingSemaphore_CallReleaseNum(&semaphore, 1);
149   pw_sync_CountingSemaphore_CallAcquire(&semaphore);
150   pw_sync_CountingSemaphore_CallAcquire(&semaphore);
151   pw_sync_CountingSemaphore_CallAcquire(&semaphore);
152   // Ensure it fails when empty.
153   EXPECT_FALSE(pw_sync_CountingSemaphore_CallTryAcquire(&semaphore));
154 }
155
156 TEST(CountingSemaphore, TryAcquireForInC) {
157   CountingSemaphore semaphore;
158   pw_sync_CountingSemaphore_CallRelease(&semaphore);
159
160   pw_chrono_SystemClock_TimePoint before = pw_chrono_SystemClock_Now();
161   ASSERT_TRUE(pw_sync_CountingSemaphore_CallTryAcquireFor(
162       &semaphore, kRoundedArbitraryDurationInC));
163   pw_chrono_SystemClock_Duration time_elapsed =
164       pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
165   EXPECT_LT(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
166
167   // Ensure it blocks and fails when empty.
168   before = pw_chrono_SystemClock_Now();
169   EXPECT_FALSE(pw_sync_CountingSemaphore_CallTryAcquireFor(
170       &semaphore, kRoundedArbitraryDurationInC));
171   time_elapsed =
172       pw_chrono_SystemClock_TimeElapsed(before, pw_chrono_SystemClock_Now());
173   EXPECT_GE(time_elapsed.ticks, kRoundedArbitraryDurationInC.ticks);
174 }
175
176 TEST(CountingSemaphore, TryAcquireUntilInC) {
177   CountingSemaphore semaphore;
178   pw_sync_CountingSemaphore_CallRelease(&semaphore);
179
180   pw_chrono_SystemClock_TimePoint deadline;
181   deadline.duration_since_epoch = {
182       .ticks = pw_chrono_SystemClock_Now().duration_since_epoch.ticks +
183                kRoundedArbitraryDurationInC.ticks,
184   };
185   ASSERT_TRUE(
186       pw_sync_CountingSemaphore_CallTryAcquireUntil(&semaphore, deadline));
187   EXPECT_LT(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
188             deadline.duration_since_epoch.ticks);
189
190   // Ensure it blocks and fails when empty.
191   EXPECT_FALSE(
192       pw_sync_CountingSemaphore_CallTryAcquireUntil(&semaphore, deadline));
193   EXPECT_GE(pw_chrono_SystemClock_Now().duration_since_epoch.ticks,
194             deadline.duration_since_epoch.ticks);
195 }
196
197 TEST(CountingSemaphore, MaxInC) {
198   EXPECT_EQ(CountingSemaphore::max(), pw_sync_CountingSemaphore_Max());
199 }
200
201 }  // namespace
202 }  // namespace pw::sync