AnyPS5/core/libs/tests/GuestAio.cpp

91 lines
4.4 KiB
C++

#include "SceTypes.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"
#include "prx/libkernel/File/include/FileFlags.hpp"
#include "prx/libkernel/KernelErrors.hpp"
#include <array>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <string>
extern "C" {
int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode);
int APS5_VABI sceKernelClose(int d);
int APS5_VABI sceKernelAioDeleteRequest(std::int32_t id, std::int32_t* ret);
int APS5_VABI sceKernelAioInitializeImpl(void* param, std::int32_t size);
void APS5_VABI sceKernelAioInitializeParam(void* param);
int APS5_VABI sceKernelAioSubmitReadCommands(KernelAioRwRequest* req, std::int32_t size, std::int32_t prio, std::int32_t* id);
int APS5_VABI sceKernelAioSubmitWriteCommands(KernelAioRwRequest* req, std::int32_t size, std::int32_t prio, std::int32_t* id);
int APS5_VABI sceKernelAioPollRequest(std::int32_t id, std::int32_t* state);
int APS5_VABI sceKernelAioWaitRequest(std::int32_t id, std::int32_t* state, std::uint32_t* usec);
}
static void Require(bool value, int line) {
if (!value) {
std::fprintf(stderr, "Aio check failed at line %d\n", line);
std::abort();
}
}
#define Check(value) Require((value), __LINE__)
int main() {
const auto root = std::filesystem::path("anyps5-aio-test-" +
std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
Check(std::filesystem::create_directory(root));
const auto file = root / "data.bin";
const std::string seed = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
{ std::ofstream stream(file, std::ios::binary); stream << seed; }
Check(sceKernelAioInitializeImpl(nullptr, 0) == 0);
int initParam = 0;
sceKernelAioInitializeParam(&initParam);
const int fd = sceKernelOpen(file.string().c_str(), SCE_KERNEL_O_RDONLY, 0);
Check(fd >= 0);
std::array<char, 16> first{};
std::array<char, 16> second{};
KernelAioResult firstResult{-1, 0};
KernelAioResult secondResult{-1, 0};
KernelAioRwRequest requests[2] = {
{0, first.size(), first.data(), &firstResult, fd},
{32, second.size(), second.data(), &secondResult, fd},
};
std::int32_t id = 0;
Check(sceKernelAioSubmitReadCommands(requests, 2, 0, &id) == 0);
Check(id > 0);
std::int32_t state = 0;
Check(sceKernelAioWaitRequest(id, &state, nullptr) == 0);
Check(state == 3);
Check(firstResult.state == 3 && firstResult.return_value == 16);
Check(secondResult.state == 3 && secondResult.return_value == 16);
Check(std::memcmp(first.data(), seed.data(), 16) == 0);
Check(std::memcmp(second.data(), seed.data() + 32, 16) == 0);
std::int32_t polled = 0;
Check(sceKernelAioPollRequest(id, &polled) == 0);
Check(polled == 3);
std::int32_t deleted = -1;
Check(sceKernelAioDeleteRequest(id, &deleted) == 0);
Check(deleted == 0);
Check(sceKernelClose(fd) == 0);
const int writeFd = sceKernelOpen(file.string().c_str(), SCE_KERNEL_O_RDWR, 0);
Check(writeFd >= 0);
std::array<char, 5> written = {'H', 'E', 'L', 'L', 'O'};
KernelAioResult writeResult{-1, 0};
KernelAioRwRequest writeRequest{0, written.size(), written.data(), &writeResult, writeFd};
std::int32_t writeId = 0;
Check(sceKernelAioSubmitWriteCommands(&writeRequest, 1, 0, &writeId) == 0);
std::int32_t writeState = 0;
Check(sceKernelAioWaitRequest(writeId, &writeState, nullptr) == 0);
Check(writeState == 3 && writeResult.state == 3 && writeResult.return_value == 5);
Check(sceKernelClose(writeFd) == 0);
{ std::ifstream stream(file, std::ios::binary); std::string contents; std::getline(stream, contents);
Check(contents.rfind("HELLO", 0) == 0); }
Check(sceKernelAioSubmitReadCommands(nullptr, 1, 0, &id) == SCE_KERNEL_ERROR_EFAULT);
Check(sceKernelAioSubmitReadCommands(requests, 0, 0, &id) == SCE_KERNEL_ERROR_EINVAL);
Check(sceKernelAioSubmitReadCommands(requests, 1, 0, nullptr) == SCE_KERNEL_ERROR_EFAULT);
Check(sceKernelAioWaitRequest(9999, &state, nullptr) == SCE_KERNEL_ERROR_EINVAL);
Check(sceKernelAioWaitRequest(id, nullptr, nullptr) == SCE_KERNEL_ERROR_EFAULT);
Check(sceKernelAioPollRequest(id, nullptr) == SCE_KERNEL_ERROR_EFAULT);
Check(sceKernelAioPollRequest(0, &polled) == SCE_KERNEL_ERROR_EINVAL);
Check(sceKernelAioDeleteRequest(id, nullptr) == SCE_KERNEL_ERROR_EFAULT);
Check(std::filesystem::remove_all(root) > 0);
}