diff options
Diffstat (limited to 'tools/integration/game_discovery_test.cpp')
| -rw-r--r-- | tools/integration/game_discovery_test.cpp | 75 |
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"; +} |
