From 8e777214b02be0f254abdcc1adbc195e765e36a6 Mon Sep 17 00:00:00 2001 From: snowstormxd <214507868+snowstormxd@users.noreply.github.com> Date: Sun, 1 Nov 2026 18:37:51 +0000 Subject: game_list: discover loose dumps without walking their RomFS payloads Defer RomFS construction, reuse one discovery result, omit recursive folder sizing, and release rows discarded by cancellation. Add scan suspension and regression coverage for extracted layouts and Unicode paths. Assisted-by: Codex (implementation, selective integration and automated validation) --- tools/integration/game_discovery_test.cpp | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tools/integration/game_discovery_test.cpp (limited to 'tools') diff --git a/tools/integration/game_discovery_test.cpp b/tools/integration/game_discovery_test.cpp new file mode 100644 index 0000000000..a5cfe0fc5a --- /dev/null +++ b/tools/integration/game_discovery_test.cpp @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "qt_common/game_list/discovery.h" +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +void Check(bool condition, + std::source_location location = std::source_location::current()) { + if (!condition) { + std::cerr << "Game discovery regression failed at line " << location.line() + << '\n'; + std::exit(1); + } +} + +int main() { + const auto temp = fs::temp_directory_path(); + const auto root = + temp / ("eglantine-discovery-" + + std::to_string( + std::chrono::steady_clock::now().time_since_epoch().count())); + Check(fs::equivalent(root.parent_path(), temp) && fs::create_directory(root)); + struct Cleanup { + fs::path path; + ~Cleanup() { fs::remove_all(path); } + } cleanup{root}; + const auto touch = [](const fs::path &path) { + fs::create_directories(path.parent_path()); + std::ofstream{path}.put('x'); + }; + const auto dump = [&](const fs::path &path) { + touch(path / "exefs/main"); + touch(path / "exefs/main.npdm"); + }; + const auto supported = [](const fs::path &path) { + return path.filename() == "main" || path.extension() == ".nsp"; + }; + const auto discover = [&](const fs::path &path, bool deep) { + return GameListDiscovery::Discover(path, deep, supported, + [] { return false; }); + }; + + const auto game = root / fs::path{u8"MKW-églantine"}; + dump(game / "base"); + dump(game / "updates/0100000000000800"); + for (unsigned i = 0; i < 400; ++i) { + touch(game / "base/romfs/assets" / std::to_string(i) / "false-game.nsp"); + } + touch(root / "standalone.nsp"); + touch(root / "unrelated/romfs/actual-game.nsp"); + + const auto deep = discover(root, true); + Check(deep.files.size() == 4 && deep.skipped_romfs == 1 && deep.errors == 0); + Check(deep.directories.size() < 20); + Check(discover(root, false).files.size() == 3); + Check(discover(game / "base", false).files.size() == 1); + Check(discover(game / "base/exefs", false).files.size() == 1); + Check(discover(root / "missing", true).files.empty()); + + touch(root / "incomplete/exefs/main"); + touch(root / "incomplete/romfs/actual-game.nsp"); + Check(discover(root, true).files.size() == 6); + + unsigned calls{}; + const auto cancelled = GameListDiscovery::Discover( + root, true, supported, [&] { return ++calls > 3; }); + Check(calls < 10 && cancelled.directories.size() <= 1); + std::cout << "Discovery: loose layouts, payload pruning, Unicode, shallow " + "scans and cancellation passed\n"; +} -- cgit v1.2.3