aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorsnowstormxd <214507868+snowstormxd@users.noreply.github.com>2026-11-01 18:37:51 +0000
committersnowstormxd <214507868+snowstormxd@users.noreply.github.com>2026-11-01 20:52:30 +0000
commit8e777214b02be0f254abdcc1adbc195e765e36a6 (patch)
treef205fffbad3c78bdbfff2d54356d43b421666942 /tools
parentac22c4087d9a6380c1937337530a5d4e54808ad1 (diff)
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)
Diffstat (limited to 'tools')
-rw-r--r--tools/integration/game_discovery_test.cpp75
1 files changed, 75 insertions, 0 deletions
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 <chrono>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <source_location>
+
+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";
+}