Files
AnyPS5/core/libs/tests/GuestAppContentDownload.cpp
T

84 lines
4.0 KiB
C++

#include "prx/libSceAppContent/include/Api.hpp"
#include "prx/libc/include/General.hpp"
#include "ProcessParametersFixture.hpp"
#include <array>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <initializer_list>
#include <stdexcept>
#include <string>
static void Require(bool condition, const char* message) {
if (condition) return;
std::fprintf(stderr, "AppContent download: %s\n", message);
std::exit(1);
}
int main(int argc, char** argv) {
Require(argc == 2, "expected a quota in MiB");
const auto quotaMiB = std::stoull(argv[1]);
static std::array<std::byte, 64> process{};
Require(ProcessParametersFixture::Install(process.data(), process.size()), "could not install process parameters");
const std::uint32_t sdkVersion = 0x01500000;
std::memcpy(process.data() + 16, &sdkVersion, sizeof(sdkVersion));
const auto original = std::filesystem::current_path();
const auto directory = original / ("appcontent-download-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
Require(std::filesystem::create_directory(directory), "could not create test directory");
std::filesystem::current_path(directory);
std::filesystem::create_directories("app0/sce_sys");
{
std::ofstream param("app0/sce_sys/param.json", std::ios::binary);
param << R"({"titleId":"PPSA00000","localizedParameters":{"en-US":{"titleName":"Example"}},"downloadDataSize":)" << quotaMiB << '}';
Require(static_cast<bool>(param), "could not write metadata");
}
AppContentInitParam init{};
AppContentBootParam boot{};
Require(sceAppContentInitialize(&init, &boot) == 0, "could not initialize");
AppContentMountPoint mount{};
std::memcpy(mount.data, "/download0", 11);
std::size_t available = 12345;
Require(sceAppContentDownloadDataGetAvailableSpaceKb(nullptr, &available) == static_cast<int>(0x80D90002u), "null mount validation changed");
Require(available == 12345, "invalid query wrote output");
const auto backing = ResolvePath_nid_no_patch("/download0");
if (quotaMiB > 18014398509481983ull) {
const bool existed = std::filesystem::exists(backing);
bool overflow = false;
try {
sceAppContentDownloadDataGetAvailableSpaceKb(&mount, &available);
} catch (const std::overflow_error&) {
overflow = true;
}
Require(overflow, "unrepresentable quota did not throw overflow_error");
Require(available == 12345, "overflow changed output");
Require(std::filesystem::exists(backing) == existed, "overflow created storage");
} else {
Require(sceAppContentDownloadDataGetAvailableSpaceKb(&mount, &available) == 0, "valid quota query failed");
if (quotaMiB == 0) {
Require(available == 0, "zero quota returned space");
} else if (quotaMiB == 1) {
Require(std::filesystem::space(backing).available > 2 * 1024 * 1024, "test needs 2 MiB of host space");
Require(available == 1024, "empty one-MiB quota is incorrect");
std::filesystem::create_directory(backing / "nested");
for (const auto bytes : {0u, 1u, 1023u, 1024u, 1025u}) {
const auto file = backing / "nested" / std::to_string(bytes);
{ std::ofstream output(file, std::ios::binary); }
std::filesystem::resize_file(file, bytes);
}
Require(sceAppContentDownloadDataGetAvailableSpaceKb(&mount, &available) == 0 && available == 1019, "per-file KiB rounding is incorrect");
std::filesystem::resize_file(backing / "nested" / "1025", 1024 * 1024);
Require(sceAppContentDownloadDataGetAvailableSpaceKb(&mount, &available) == 0 && available == 0, "over-quota usage did not clamp to zero");
} else {
Require(available > 0, "largest representable quota returned no space");
}
}
std::filesystem::current_path(original);
std::filesystem::remove_all(directory);
}