feat(games): manually add games (e.g. SPT) with launch + own logs
Some titles never show up in a Steam/Lutris/Heroic scan — standalone mod
launchers like SPT (Single-Player Tarkov), itch.io downloads, hand-installed
executables. Add a user-authored custom-games list (core/customgames.py) shown
alongside the other sources in `rigdoctor games` and the GUI.
Each entry can carry a launch command and a log directory:
- `rigdoctor games add "SPT" --command .../tarkov.sh` (logs/ auto-detected)
- `rigdoctor games play "SPT"` launches it under the crash-capture wrapper
(wrap.run gains an explicit game-name override, since there's no SteamAppId)
- the diagnostic now feeds the game's own logs to the analysis: gamelogs
.collect(game=...) tails the registered log dir (SPT's server/launcher logs)
alongside the kernel log, freshness-scoped by mtime.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
"""Tests for user-added games (M6): add/remove/scan of titles no launcher reports (e.g. SPT)."""
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
from rigdoctor.core import customgames
|
||||
|
||||
|
||||
class CustomGamesTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self._tmp = tempfile.TemporaryDirectory()
|
||||
self._file = Path(self._tmp.name) / "custom-games.json"
|
||||
self._patch = mock.patch.object(customgames.config, "CUSTOM_GAMES_FILE", self._file)
|
||||
self._patch.start()
|
||||
|
||||
def tearDown(self):
|
||||
self._patch.stop()
|
||||
self._tmp.cleanup()
|
||||
|
||||
def test_missing_file_scans_empty(self):
|
||||
self.assertEqual(customgames.scan(), [])
|
||||
self.assertEqual(customgames.names(), [])
|
||||
|
||||
def test_add_then_scan_returns_game(self):
|
||||
self.assertTrue(customgames.add("SPT"))
|
||||
games = customgames.scan()
|
||||
self.assertEqual(len(games), 1)
|
||||
self.assertEqual(games[0].name, "SPT")
|
||||
self.assertEqual(games[0].launcher, "custom")
|
||||
self.assertTrue(self._file.exists()) # persisted
|
||||
|
||||
def test_add_is_idempotent_case_insensitive(self):
|
||||
self.assertTrue(customgames.add("SPT"))
|
||||
self.assertFalse(customgames.add("spt")) # already present
|
||||
self.assertFalse(customgames.add(" ")) # blank
|
||||
self.assertEqual(customgames.names(), ["SPT"])
|
||||
|
||||
def test_remove(self):
|
||||
customgames.add("SPT")
|
||||
customgames.add("Minecraft")
|
||||
self.assertTrue(customgames.remove("spt")) # case-insensitive
|
||||
self.assertEqual(customgames.names(), ["Minecraft"])
|
||||
self.assertFalse(customgames.remove("nope"))
|
||||
|
||||
def test_scan_sorted_by_name(self):
|
||||
for n in ("Zomboid", "Apex", "SPT"):
|
||||
customgames.add(n)
|
||||
self.assertEqual([g.name for g in customgames.scan()], ["Apex", "SPT", "Zomboid"])
|
||||
|
||||
def test_command_and_logdir_stored_and_resolved(self):
|
||||
logs = Path(self._tmp.name) / "logs"
|
||||
logs.mkdir()
|
||||
sh = Path(self._tmp.name) / "tarkov.sh"
|
||||
sh.write_text("#!/bin/sh\n")
|
||||
self.assertTrue(customgames.add("SPT", command=str(sh), logdir=str(logs)))
|
||||
self.assertEqual(customgames.command("SPT"), [str(sh)])
|
||||
self.assertEqual(customgames.log_dir("SPT"), str(logs))
|
||||
|
||||
def test_logdir_inferred_from_sibling_logs(self):
|
||||
# A command with a sibling logs/ dir (SPT's layout) → logdir auto-detected.
|
||||
sh = Path(self._tmp.name) / "tarkov.sh"
|
||||
sh.write_text("#!/bin/sh\n")
|
||||
(Path(self._tmp.name) / "logs").mkdir()
|
||||
self.assertTrue(customgames.add("SPT", command=str(sh)))
|
||||
self.assertEqual(customgames.log_dir("SPT"), str(Path(self._tmp.name) / "logs"))
|
||||
|
||||
def test_no_command_resolves_to_none(self):
|
||||
customgames.add("SPT")
|
||||
self.assertIsNone(customgames.command("SPT"))
|
||||
self.assertIsNone(customgames.command("missing"))
|
||||
self.assertIsNone(customgames.log_dir("SPT"))
|
||||
|
||||
def test_corrupt_file_degrades_to_empty(self):
|
||||
self._file.parent.mkdir(parents=True, exist_ok=True)
|
||||
self._file.write_text("{not json")
|
||||
self.assertEqual(customgames.scan(), [])
|
||||
# and a subsequent add still works (overwrites the garbage)
|
||||
self.assertTrue(customgames.add("SPT"))
|
||||
self.assertEqual(customgames.names(), ["SPT"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user