feat(m9): systemd --user trigger modes + game-launch watcher — 0.23.0
D6 trigger modes, no root: - core/service.py: write/enable `systemd --user` units; apply_mode(manual/ always-on/game-launch) reconciles the recorder + watcher services; status(). - core/watcher.py + `rigdoctor watch`: poll Steam RunningAppID, auto-bracket a focused capture (D12 zero-config fallback; wrapper stays primary). - CLI `rigdoctor service status|mode`; config `trigger_mode`. - GUI Settings: "Recording trigger" dropdown (Apply runs apply_mode off-thread). - Tests for unit generation, mode reconciliation, watcher transitions/parse. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Tests for the M9/D12 game-launch watcher (RunningAppID parse + transitions)."""
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
from rigdoctor.core import watcher
|
||||
|
||||
_REGISTRY = """"Registry"
|
||||
{
|
||||
\t"HKCU"
|
||||
\t{
|
||||
\t\t"Software"
|
||||
\t\t{
|
||||
\t\t\t"Valve"
|
||||
\t\t\t{
|
||||
\t\t\t\t"Steam"
|
||||
\t\t\t\t{
|
||||
\t\t\t\t\t"RunningAppID"\t\t"%s"
|
||||
\t\t\t\t}
|
||||
\t\t\t}
|
||||
\t\t}
|
||||
\t}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class TransitionTests(unittest.TestCase):
|
||||
def test_transitions(self):
|
||||
self.assertEqual(watcher.transition(0, 570), "start")
|
||||
self.assertEqual(watcher.transition(570, 0), "stop")
|
||||
self.assertIsNone(watcher.transition(570, 570))
|
||||
self.assertIsNone(watcher.transition(0, 0))
|
||||
|
||||
|
||||
class FindKeyTests(unittest.TestCase):
|
||||
def test_case_insensitive_nested(self):
|
||||
data = {"Registry": {"HKCU": {"steam": {"runningappid": "42"}}}}
|
||||
self.assertEqual(watcher._find_key(data, "RunningAppID"), "42")
|
||||
|
||||
def test_missing(self):
|
||||
self.assertIsNone(watcher._find_key({"a": {"b": "c"}}, "RunningAppID"))
|
||||
|
||||
|
||||
class RunningAppIdTests(unittest.TestCase):
|
||||
def _with_registry(self, content):
|
||||
d = tempfile.mkdtemp()
|
||||
path = Path(d) / "registry.vdf"
|
||||
path.write_text(content)
|
||||
return path
|
||||
|
||||
def test_reads_running_appid(self):
|
||||
path = self._with_registry(_REGISTRY % "570")
|
||||
with mock.patch.object(watcher, "_registry_path", return_value=path):
|
||||
self.assertEqual(watcher.running_appid(), 570)
|
||||
|
||||
def test_zero_when_idle(self):
|
||||
path = self._with_registry(_REGISTRY % "0")
|
||||
with mock.patch.object(watcher, "_registry_path", return_value=path):
|
||||
self.assertEqual(watcher.running_appid(), 0)
|
||||
|
||||
def test_zero_when_no_registry(self):
|
||||
with mock.patch.object(watcher, "_registry_path", return_value=None):
|
||||
self.assertEqual(watcher.running_appid(), 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user