Skip to content

Commit db514cc

Browse files
KellesiVlada KanivetsSergiusTheBestCopilot
authored
Add tests for Semaphore (KF-30, #70)
* add tests for Semaphore * Remove threads from SemaphoreTest * Update test/SemaphoreTest.cpp Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Vlada Kanivets <[email protected]> Co-authored-by: Sergey Podobry <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 4659b92 commit db514cc

File tree

3 files changed

+135
-2
lines changed

3 files changed

+135
-2
lines changed

include/kf/Semaphore.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ namespace kf
2121
return &m_semaphore;
2222
}
2323

24-
NTSTATUS wait(_In_opt_ PLARGE_INTEGER timeout = nullptr)
24+
NTSTATUS wait(_In_opt_ const LARGE_INTEGER* timeout = nullptr)
2525
{
2626
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
27-
return KeWaitForSingleObject(&m_semaphore, Executive, KernelMode, false, timeout);
27+
return KeWaitForSingleObject(&m_semaphore, Executive, KernelMode, false, const_cast<LARGE_INTEGER*>(timeout));
2828
}
2929

3030
void release(LONG adjustment = 1)

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ wdk_add_driver(kf-test WINVER NTDDI_WIN10 STL
6363
AutoSpinLockTest.cpp
6464
EResourceSharedLockTest.cpp
6565
RecursiveAutoSpinLockTest.cpp
66+
SemaphoreTest.cpp
6667
UStringBuilderTest.cpp
6768
USimpleStringTest.cpp
6869
)

test/SemaphoreTest.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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

Comments
 (0)