diff --git a/tests/e2e/test_titles.py b/tests/e2e/test_titles.py index 82d0afb..a380147 100644 --- a/tests/e2e/test_titles.py +++ b/tests/e2e/test_titles.py @@ -123,6 +123,9 @@ class Titles(harness.FrameTestCase): self.assertFalse(run['started']) self.assertEqual(run['message'], f'Tool 4183110 "Steam Linux Runtime 4.0" is found for appID {appid}, ' 'but is not installed') + # The headset smoke test finds this in Steam's logs, where compat_log.txt has + # binary bytes in it: only grep -a returns the line (Frame, 2026-09-27). + self.assertIn(run['message'], ssh('grep -arshF "but is not installed" ~/.local/share/Steam/logs/')) # With the runtime installed, it starts. ctl('runtime', 'SteamLinuxRuntime_4', 'installed') ok('POST', '/api/titles', {'action': 'launch', 'id': 'Tiny_PC_Game'}) diff --git a/tests/fakeframe/rootfs/usr/local/lib/fakeframe/fakesteam.py b/tests/fakeframe/rootfs/usr/local/lib/fakeframe/fakesteam.py index c7adcc0..7c9ee78 100755 --- a/tests/fakeframe/rootfs/usr/local/lib/fakeframe/fakesteam.py +++ b/tests/fakeframe/rootfs/usr/local/lib/fakeframe/fakesteam.py @@ -40,6 +40,10 @@ HOME = fs.HOME STEAM_DIR = HOME + '/.steam' PID_FILE, TOKEN_FILE, PIPE = (f'{STEAM_DIR}/steam.{n}' for n in ('pid', 'token', 'pipe')) CONSOLE_LOG = fs.STEAM_ROOT + '/logs/console_log.txt' # guess: which file Steam logs devkit launches to +# Steam logs compat tool lookups here, and on the Frame the file has binary bytes +# in it, so plain grep only says "binary file matches" (headset smoke test, +# 2026-09-27, BUILD_ID 20260922.6101926). The fake starts it with a NUL to match. +COMPAT_LOG = fs.STEAM_ROOT + '/logs/compat_log.txt' DEVTOOLS_PORT = 8080 TARGET_ID = 'F0CA11ED5EA4ED0000000000000000AB' GAME_LOGS = '/var/log/fakeframe' @@ -67,6 +71,14 @@ def console(line): f.write(time.strftime('[%Y-%m-%d %H:%M:%S] ') + line + '\n') +def compat(line): + os.makedirs(os.path.dirname(COMPAT_LOG), exist_ok=True) + with open(COMPAT_LOG, 'ab') as f: + if f.tell() == 0: + f.write(b'\0\n') + f.write((time.strftime('[%Y-%m-%d %H:%M:%S] ') + line + '\n').encode()) + + def respond(path, text=None, error=None): """Answer a devkit request the way devkit_utils.wait_on_file_response expects.""" lock = path + '.lock' @@ -210,6 +222,7 @@ def cmd_run_game(q): name = fs.RUNTIME_NAMES.get(tool, tool) record.update(started=False, message=f'Tool {fs.RUNTIME_APPIDS.get(tool, 0)} "{name}" is found for ' f'appID {game["appid"]}, but is not installed') + compat(record['message']) elif tool and tool.startswith('proton'): # How Steam ran a sideloaded .exe on the Frame (docs/sideloading.md). prefix = f"{fs.STEAM_ROOT}/steamapps/compatdata/{game['appid']}/pfx" diff --git a/tests/smoke/frame_smoke.py b/tests/smoke/frame_smoke.py index 14e8ff0..740e048 100644 --- a/tests/smoke/frame_smoke.py +++ b/tests/smoke/frame_smoke.py @@ -115,9 +115,13 @@ def status(build): def steam_log_lines(*patterns): - """Steam log lines holding any of the fixed strings (which files: not verified, so all).""" + """Steam log lines holding any of the fixed strings (which files: not verified, so all). + + -a: compat_log.txt has binary bytes in it, and without it grep only says + "binary file matches" (seen on the Frame, 2026-09-27). + """ pats = ' '.join(f'-e {shlex.quote(p)}' for p in patterns) - out = ssh(f"grep -rshF {pats} ~/.local/share/Steam/logs/ 2>/dev/null || true") + out = ssh(f"grep -arshF {pats} ~/.local/share/Steam/logs/ 2>/dev/null || true") return out.strip().splitlines()