1+ #include " pch.h"
2+ #include < kf/Semaphore.h>
3+
4+ SCENARIO (" kf::Semaphore" )
5+ {
6+ constexpr LARGE_INTEGER kOneMillisecond { .QuadPart = -10'000LL }; // 1ms
7+ constexpr LARGE_INTEGER kZeroTimeout {};
8+
9+ GIVEN (" A semaphore with count = 1 and limit = 1" )
10+ {
11+ kf::Semaphore sem (1 , 1 );
12+
13+ WHEN (" Trying to acquire should succeed immediately" )
14+ {
15+ THEN (" Thread doesn't wait" )
16+ {
17+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
18+ }
19+ }
20+
21+ WHEN (" Acquiring twice should deplete the count and then timeout" )
22+ {
23+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
24+
25+ THEN (" Second wait times out" )
26+ {
27+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
28+ }
29+ }
30+
31+ WHEN (" After depleting, release allows acquiring again" )
32+ {
33+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
34+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
35+
36+ sem.release ();
37+
38+ THEN (" Wait succeeds after release" )
39+ {
40+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
41+ }
42+ }
43+ }
44+
45+ GIVEN (" A semaphore with count = 0 and limit = 1" )
46+ {
47+ kf::Semaphore sem (0 , 1 );
48+
49+ WHEN (" Trying to acquire should timeout" )
50+ {
51+ THEN (" Wait fails with timeout" )
52+ {
53+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
54+ }
55+ }
56+
57+ WHEN (" Release makes next acquire succeed and then timeout again" )
58+ {
59+ sem.release ();
60+
61+ THEN (" First wait succeeds immediately and subsequent wait times out" )
62+ {
63+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
64+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
65+ }
66+ }
67+ }
68+
69+ GIVEN (" A semaphore with count = 1000 and limit = 1000" )
70+ {
71+ kf::Semaphore sem (1000 , 1000 );
72+
73+ WHEN (" Acquiring up to count succeeds, extra wait times out" )
74+ {
75+ for (int i = 0 ; i < 1000 ; ++i)
76+ {
77+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
78+ }
79+
80+ THEN (" Next wait times out" )
81+ {
82+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
83+ }
84+ }
85+
86+ WHEN (" Releasing after depletion allows acquire to succeed" )
87+ {
88+ for (int i = 0 ; i < 1000 ; ++i)
89+ {
90+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
91+ }
92+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
93+
94+ sem.release ();
95+
96+ THEN (" Wait succeeds after release" )
97+ {
98+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
99+ }
100+ }
101+ }
102+
103+ GIVEN (" A semaphore with count = 0, limit = 2 and multi-adjust release" )
104+ {
105+ kf::Semaphore sem (0 , 2 );
106+
107+ WHEN (" Release with adjustment 2" )
108+ {
109+ sem.release (2 );
110+
111+ THEN (" Two immediate acquires succeed, third times out" )
112+ {
113+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
114+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
115+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
116+ }
117+ }
118+
119+ WHEN (" Multiple single releases allow multiple acquires" )
120+ {
121+ sem.release ();
122+ sem.release ();
123+
124+ THEN (" Two immediate acquires succeed, next times out" )
125+ {
126+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
127+ REQUIRE (STATUS_SUCCESS == sem.wait (&kZeroTimeout ));
128+ REQUIRE (STATUS_TIMEOUT == sem.wait (&kOneMillisecond ));
129+ }
130+ }
131+ }
132+ }
0 commit comments