[+] Tests for exact Win32 WaitForMultipleObject semantics for emulation layers

This commit is contained in:
Reece Wilson 2024-08-02 02:25:33 +01:00
parent f8d50da176
commit 209a28c0ee
2 changed files with 174 additions and 1 deletions

@ -1 +1 @@
Subproject commit c6ce29a188350e8977cc6bfb2c020c836ad3895b Subproject commit 5947e6a2c3a782f1363d1ae308b52441eb52879b

View File

@ -85,6 +85,177 @@ TEST(Loop, Semaphore)
ASSERT_TRUE(loop->WaitAll(100)); ASSERT_TRUE(loop->WaitAll(100));
} }
TEST(Loop, Semaphore2)
{
auto semaA = AuLoop::NewLSSemaphore(1);
auto semaB = AuLoop::NewLSSemaphore(0);
auto loop = AuLoop::NewLoopQueue();
// Add initial loop sources
ASSERT_TRUE(loop->SourceAdd(semaA));
ASSERT_TRUE(loop->SourceAdd(semaB));
auto semACallback = AuMakeShared<AuLoop::ILoopSourceSubscriberFunctional>([](const AuSPtr<AuLoop::ILoopSource> &source) -> bool
{
AuLogInfo("Hello from semaphore a's work queue [ FAIL ]");
return false;
});
auto semBCallback = AuMakeShared<AuLoop::ILoopSourceSubscriberFunctional>([](const AuSPtr<AuLoop::ILoopSource> &source) -> bool
{
AuLogInfo("Hello from semaphore b's work queue [ FAIL ]");
return false;
});
// Add optional subscriptions
ASSERT_TRUE(loop->AddCallback(semaA, semACallback));
ASSERT_TRUE(loop->AddCallback(semaB, semBCallback));
// Commit source changes
ASSERT_TRUE(loop->Commit());
ASSERT_TRUE(!loop->WaitAll(1000));
ASSERT_TRUE(semaA->IsSignaled());
ASSERT_TRUE(!semaB->IsSignaled());
}
TEST(WFMO_WithUserlandFastPath, SemaphoreWaitForMultipleObjects)
{
auto semaA = AuLoop::NewLSSemaphore(0);
auto semaB = AuLoop::NewLSSemaphore(1);
auto semaC = AuLoop::NewLSSemaphore(1);
AuList<AuSPtr<AuLoop::ILoopSource>> signaled;
AuLoop::WaitMultipleLoopSourcesEx({ semaA, semaB, semaC },
signaled,
AuLoop::kWaitMultipleFlagAny | AuLoop::kWaitMultipleFlagBreakAfterOne /*nt-like yield*/,
{});
ASSERT_TRUE(signaled.size() == 1);
ASSERT_TRUE(!semaA->IsSignaled());
ASSERT_TRUE(!semaB->IsSignaled());
ASSERT_TRUE(semaC->IsSignaled());
}
TEST(WFMO_WithUserlandFastPath, SemaphoreWaitForMultipleObjects2)
{
auto semaA = AuLoop::NewLSSemaphore(0);
auto semaB = AuLoop::NewLSSemaphore(1);
auto semaC = AuLoop::NewLSSemaphore(1);
AuList<AuSPtr<AuLoop::ILoopSource>> signaled;
AuLoop::WaitMultipleLoopSourcesEx({ semaA, semaB, semaC },
signaled,
AuLoop::kWaitMultipleFlagAny,
{});
ASSERT_TRUE(signaled.size() == 2);
ASSERT_TRUE(!semaA->IsSignaled());
ASSERT_TRUE(!semaB->IsSignaled());
ASSERT_TRUE(!semaC->IsSignaled());
}
TEST(WFMO_WithUserlandFastPath, SemaphoreWaitForMultipleObjects3)
{
auto semaA = AuLoop::NewLSSemaphore(0);
auto semaB = AuLoop::NewLSSemaphore(1);
auto semaC = AuLoop::NewLSSemaphore(1);
AuList<AuSPtr<AuLoop::ILoopSource>> signaled;
AuLoop::WaitMultipleLoopSourcesEx({ semaA, semaB, semaC },
signaled,
0,
{ 4 });
ASSERT_TRUE(signaled.empty());
ASSERT_TRUE(!semaA->IsSignaled());
ASSERT_TRUE(semaB->IsSignaled());
ASSERT_TRUE(semaC->IsSignaled());
}
TEST(WFMO_NoUserlandFastPath, SemaphoreWaitForMultipleObjects)
{
auto semaA = AuLoop::NewLSSemaphoreSlow(0);
auto semaB = AuLoop::NewLSSemaphoreSlow(1);
auto semaC = AuLoop::NewLSSemaphoreSlow(1);
AuList<AuSPtr<AuLoop::ILoopSource>> signaled;
AuLoop::WaitMultipleLoopSourcesEx({ semaA, semaB, semaC },
signaled,
AuLoop::kWaitMultipleFlagAny | AuLoop::kWaitMultipleFlagBreakAfterOne /*nt-like yield*/,
{});
ASSERT_TRUE(signaled.size() == 1);
ASSERT_TRUE(!semaA->IsSignaled());
ASSERT_TRUE(!semaB->IsSignaled());
ASSERT_TRUE(semaC->IsSignaled());
}
TEST(WFMO_NoUserlandFastPath, SemaphoreWaitForMultipleObjects2)
{
auto semaA = AuLoop::NewLSSemaphoreSlow(0);
auto semaB = AuLoop::NewLSSemaphoreSlow(1);
auto semaC = AuLoop::NewLSSemaphoreSlow(1);
AuList<AuSPtr<AuLoop::ILoopSource>> signaled;
AuLoop::WaitMultipleLoopSourcesEx({ semaA, semaB, semaC },
signaled,
AuLoop::kWaitMultipleFlagAny,
{});
ASSERT_TRUE(signaled.size() == 2);
ASSERT_TRUE(!semaA->IsSignaled());
ASSERT_TRUE(!semaB->IsSignaled());
ASSERT_TRUE(!semaC->IsSignaled());
}
TEST(WFMO_NoUserlandFastPath, SemaphoreWaitForMultipleObjects3)
{
auto semaA = AuLoop::NewLSSemaphoreSlow(0);
auto semaB = AuLoop::NewLSSemaphoreSlow(1);
auto semaC = AuLoop::NewLSSemaphoreSlow(1);
AuList<AuSPtr<AuLoop::ILoopSource>> signaled;
AuLoop::WaitMultipleLoopSourcesEx({ semaA, semaB, semaC },
signaled,
0,
{ 4 });
ASSERT_TRUE(signaled.empty());
ASSERT_TRUE(!semaA->IsSignaled());
ASSERT_TRUE(semaB->IsSignaled());
ASSERT_TRUE(semaC->IsSignaled());
}
#if defined(AURORA_PLATFORM_MODERNNT_DERIVED)
TEST(WinNT, SemaphoreTest)
{
auto semaA = AuLoop::NewLSSemaphoreSlow(0);
ReleaseSemaphore((HANDLE)AuLoop::DbgLoopSourceToWriteFd(semA), 1, nullptr);
ASSERT_TRUE(semaA->IsSignaled());
}
TEST(WinNT, SemaphoreTest2)
{
auto event = AuLoop::NewLSEventSlow(false, false, false);
SetEvent((HANDLE)AuLoop::DbgLoopSourceToWriteFd(event));
ASSERT_TRUE(event->IsSignaled());
}
#endif
TEST(Loop, Timer0) TEST(Loop, Timer0)
{ {
SysBenchmark("Hello?"); SysBenchmark("Hello?");
@ -178,6 +349,8 @@ TEST(Loop, Timer4)
ASSERT_FALSE(loop->WaitAll(100)); ASSERT_FALSE(loop->WaitAll(100));
} }
// OLD COMMENTS + REMARKS FROM LATE 2021
// //
// Note: kernel loop queues also support async file and pipe transactions. // Note: kernel loop queues also support async file and pipe transactions.
// See the specialized tests for loop queue related interfaces // See the specialized tests for loop queue related interfaces