xref: /aosp_15_r20/external/pigweed/pw_sync/timed_thread_notification_facade_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 "pw_chrono/system_clock.h"
18 #include "pw_sync/timed_thread_notification.h"
19 #include "pw_unit_test/framework.h"
20 
21 using pw::chrono::SystemClock;
22 using namespace std::chrono_literals;
23 
24 namespace pw::sync {
25 namespace {
26 
27 // We can't control the SystemClock's period configuration, so just in case
28 // duration cannot be accurately expressed in integer ticks, round the
29 // duration up.
30 constexpr SystemClock::duration kRoundedArbitraryDuration =
31     SystemClock::for_at_least(42ms);
32 
TEST(TimedThreadNotification,EmptyInitialState)33 TEST(TimedThreadNotification, EmptyInitialState) {
34   TimedThreadNotification notification;
35   EXPECT_FALSE(notification.try_acquire());
36 }
37 
38 // TODO: b/235284163 - Add real concurrency tests.
39 
TEST(TimedThreadNotification,Release)40 TEST(TimedThreadNotification, Release) {
41   TimedThreadNotification notification;
42   notification.release();
43   notification.release();
44   notification.acquire();
45   // Ensure it fails when not notified.
46   EXPECT_FALSE(notification.try_acquire());
47 }
48 
49 TimedThreadNotification empty_initial_notification;
TEST(TimedThreadNotification,EmptyInitialStateStatic)50 TEST(TimedThreadNotification, EmptyInitialStateStatic) {
51   EXPECT_FALSE(empty_initial_notification.try_acquire());
52 }
53 
54 TimedThreadNotification raise_notification;
TEST(TimedThreadNotification,ReleaseStatic)55 TEST(TimedThreadNotification, ReleaseStatic) {
56   raise_notification.release();
57   raise_notification.release();
58   raise_notification.acquire();
59   // Ensure it fails when not notified.
60   EXPECT_FALSE(raise_notification.try_acquire());
61 }
62 
TEST(TimedThreadNotification,TryAcquireForNotified)63 TEST(TimedThreadNotification, TryAcquireForNotified) {
64   TimedThreadNotification notification;
65   notification.release();
66 
67   // Ensure it doesn't block and succeeds when notified.
68   SystemClock::time_point before = SystemClock::now();
69   EXPECT_TRUE(notification.try_acquire_for(kRoundedArbitraryDuration));
70   SystemClock::duration time_elapsed = SystemClock::now() - before;
71   EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
72 }
73 
TEST(TimedThreadNotification,TryAcquireForNotNotifiedPositiveTimeout)74 TEST(TimedThreadNotification, TryAcquireForNotNotifiedPositiveTimeout) {
75   TimedThreadNotification notification;
76 
77   // Ensure it blocks and fails when not notified for the full timeout.
78   SystemClock::time_point before = SystemClock::now();
79   EXPECT_FALSE(notification.try_acquire_for(kRoundedArbitraryDuration));
80   SystemClock::duration time_elapsed = SystemClock::now() - before;
81   EXPECT_GE(time_elapsed, kRoundedArbitraryDuration);
82 }
83 
TEST(TimedThreadNotification,TryAcquireForNotNotifiedZeroLengthTimeout)84 TEST(TimedThreadNotification, TryAcquireForNotNotifiedZeroLengthTimeout) {
85   TimedThreadNotification notification;
86 
87   // Ensure it doesn't block when a zero length duration is used.
88   SystemClock::time_point before = SystemClock::now();
89   EXPECT_FALSE(notification.try_acquire_for(SystemClock::duration::zero()));
90   SystemClock::duration time_elapsed = SystemClock::now() - before;
91   EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
92 }
93 
TEST(TimedThreadNotification,TryAcquireForNotNotifiedNegativeTimeout)94 TEST(TimedThreadNotification, TryAcquireForNotNotifiedNegativeTimeout) {
95   TimedThreadNotification notification;
96 
97   // Ensure it doesn't block when a negative duration is used.
98   SystemClock::time_point before = SystemClock::now();
99   EXPECT_FALSE(notification.try_acquire_for(-kRoundedArbitraryDuration));
100   SystemClock::duration time_elapsed = SystemClock::now() - before;
101   EXPECT_LT(time_elapsed, kRoundedArbitraryDuration);
102 }
103 
TEST(TimedThreadNotification,TryAcquireUntilNotified)104 TEST(TimedThreadNotification, TryAcquireUntilNotified) {
105   TimedThreadNotification notification;
106   notification.release();
107 
108   // Ensure it doesn't block and succeeds when notified.
109   SystemClock::time_point deadline =
110       SystemClock::now() + kRoundedArbitraryDuration;
111   EXPECT_TRUE(notification.try_acquire_until(deadline));
112   EXPECT_LT(SystemClock::now(), deadline);
113 }
114 
TEST(TimedThreadNotification,TryAcquireUntilNotNotifiedFutureDeadline)115 TEST(TimedThreadNotification, TryAcquireUntilNotNotifiedFutureDeadline) {
116   TimedThreadNotification notification;
117 
118   // Ensure it blocks and fails when not notified.
119   SystemClock::time_point deadline =
120       SystemClock::now() + kRoundedArbitraryDuration;
121   EXPECT_FALSE(notification.try_acquire_until(deadline));
122   EXPECT_GE(SystemClock::now(), deadline);
123 }
124 
TEST(TimedThreadNotification,TryAcquireUntilNotNotifiedCurrentDeadline)125 TEST(TimedThreadNotification, TryAcquireUntilNotNotifiedCurrentDeadline) {
126   TimedThreadNotification notification;
127 
128   // Ensure it doesn't block when now is used.
129   SystemClock::time_point deadline =
130       SystemClock::now() + kRoundedArbitraryDuration;
131   EXPECT_FALSE(notification.try_acquire_until(SystemClock::now()));
132   EXPECT_LT(SystemClock::now(), deadline);
133 }
134 
TEST(TimedThreadNotification,TryAcquireUntilNotNotifiedPastDeadline)135 TEST(TimedThreadNotification, TryAcquireUntilNotNotifiedPastDeadline) {
136   TimedThreadNotification notification;
137 
138   // Ensure it doesn't block when a timestamp in the past is used.
139   SystemClock::time_point deadline =
140       SystemClock::now() + kRoundedArbitraryDuration;
141   EXPECT_FALSE(notification.try_acquire_until(SystemClock::now() -
142                                               kRoundedArbitraryDuration));
143   EXPECT_LT(SystemClock::now(), deadline);
144 }
145 
146 }  // namespace
147 }  // namespace pw::sync
148