Files
PS2Recomp/ps2xTest/src/ps2_iop_tests.cpp
T
2026-09-19 21:17:58 -03:00

76 lines
3.7 KiB
C++

#include "MiniTest.h"
#include "ps2x/iop/ps2_path.h"
#include "../../ps2xIOP/tests/iop_compat_test_support.h"
void register_ps2_iop_tests()
{
MiniTest::Case("PS2IopSubsystem", [](TestCase &tc)
{
tc.Run("PS2 path parsing is shared and normalizes ISO/module names", [](TestCase &t)
{
const ps2x::iop::ParsedPs2Path cd = ps2x::iop::parsePs2Path("CDROM0:\\MODULES\\LIBSD.IRX;1");
t.Equals(cd.device, ps2x::iop::Ps2PathDevice::Cdrom,
"device names should be case-insensitive");
t.Equals(cd.path, std::string("MODULES/LIBSD.IRX"),
"separators and ISO version suffixes should normalize once");
t.Equals(ps2x::iop::ps2PathLeafKey(cd), std::string("libsd"),
"module lookup should use a normalized IRX leaf key");
const ps2x::iop::ParsedPs2Path rom = ps2x::iop::parsePs2Path("rom0:ROMVER");
t.Equals(rom.device, ps2x::iop::Ps2PathDevice::Rom0,
"ROM0 should remain a distinct virtual device");
t.IsFalse(static_cast<bool>(ps2x::iop::parsePs2Path("unknown0:file.irx")),
"unsupported devices must not fall through to cdrom0");
});
tc.Run("HLE services activate only after a recognized module load", [](TestCase &t)
{
iop_test::Host host;
ps2x::iop::IopSubsystem subsystem(host);
t.IsFalse(subsystem.canBindRpc(0x80000701u),
"LIBSD RPC must not exist before LIBSD is loaded");
const ps2x::iop::ModuleLoadResult unknown = subsystem.loadModule("rom0:NOT_A_REAL_MODULE");
t.IsTrue(unknown.handled, "the module manager should return a real load result");
t.IsTrue(unknown.moduleId < 0, "unknown ROM modules must fail instead of receiving fake IDs");
const ps2x::iop::ModuleLoadResult loaded = subsystem.loadModule("rom0:LIBSD");
t.IsTrue(loaded.moduleId > 0, "a registered no-BIOS HLE module should load");
t.IsTrue(subsystem.canBindRpc(0x80000701u),
"loading LIBSD should activate its HLE RPC endpoint");
ps2x::iop::RpcRequest request{};
request.sid = 0x80000701u;
request.function = 3u;
t.IsTrue(subsystem.handleRpc(request).handled,
"the activated LIBSD service should handle its RPC");
t.Equals(host.audioCalls, 1u, "the RPC should reach the HLE audio contract");
int32_t stopResult = -1;
t.IsTrue(subsystem.stopModule(loaded.moduleId, &stopResult),
"an HLE module should have a real stoppable lifecycle");
t.Equals(stopResult, 0, "stopping an HLE module should report success");
t.IsFalse(subsystem.canBindRpc(0x80000701u),
"stopping LIBSD should deactivate its RPC endpoint");
});
tc.Run("unknown SID remains unhandled without a loaded IRX", [](TestCase &t)
{
iop_test::Host host;
ps2x::iop::IopSubsystem subsystem(host);
ps2x::iop::RpcRequest request{};
request.sid = 0xDEADC0DEu;
request.function = 0x99u;
const ps2x::iop::RpcResult result = subsystem.handleRpc(request);
t.IsFalse(result.handled, "an unknown SID should not be claimed by the IOP subsystem");
t.Equals(result.resultAddress, 0u, "an unknown SID should not return a guest result address");
t.IsFalse(result.signalNowaitCompletion, "an unknown SID should not signal nowait completion");
t.Equals(result.callbackPolicy, ps2x::iop::CallbackPolicy::RuntimeDefault,
"an unknown SID should preserve runtime callback handling");
});
});
}