mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
113 lines
6.0 KiB
Python
113 lines
6.0 KiB
Python
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
|
|
BIN = Path(__file__).resolve().parents[1] / 'linuxfs/overlay/usr/local/bin'
|
|
|
|
|
|
class SteamCompatEnvironmentTest(unittest.TestCase):
|
|
def test_library_launch_preserves_guest_environment_without_steam_client_libraries(self):
|
|
source = (BIN / 'droiddeck-session').read_text()
|
|
setup = source[source.index(' _bl_compat_env='):source.index(' export SDL_VIDEO_X11_DGAMOUSE=')]
|
|
launch = next(line for line in source.splitlines()
|
|
if 'droiddeck-steam-compat "$steam_root"' in line)
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
helper = root / 'droiddeck-steam-compat'
|
|
helper.write_text('#!/usr/bin/env python3\nimport json, os, sys\n'
|
|
'json.dump({"env": dict(os.environ), "args": sys.argv[1:]}, '
|
|
'open(os.environ["BRIDGE_CAPTURE"], "w"))\n')
|
|
helper.chmod(0o755)
|
|
for inherited in ({}, {'LD_LIBRARY_PATH': '/guest/driver:/guest/libs'},
|
|
{'LD_LIBRARY_PATH': '', 'STEAM_RUNTIME': ''},
|
|
{'LD_LIBRARY_PATH': '/custom path/lib', 'STEAM_RUNTIME': '0'}):
|
|
with self.subTest(inherited=inherited):
|
|
env = dict(os.environ, PATH=str(root) + os.pathsep + os.environ['PATH'],
|
|
BRIDGE_CAPTURE=str(root / 'captured.json'),
|
|
VK_ICD_FILENAMES='/guest/driver/turnip.json', steam_root='/steam')
|
|
for key in ('LD_LIBRARY_PATH', 'STEAM_RUNTIME'):
|
|
env.pop(key, None)
|
|
env.update(inherited)
|
|
result = subprocess.run(['bash', '-c', setup + '\n' + launch + '\nwait $!\n'
|
|
'printf "%s\\n" "$STEAM_RUNTIME" "$LD_LIBRARY_PATH"'],
|
|
env=env, capture_output=True, text=True, timeout=10)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
bridge = json.loads((root / 'captured.json').read_text())
|
|
self.assertEqual(bridge['args'], ['/steam'])
|
|
for key in ('LD_LIBRARY_PATH', 'STEAM_RUNTIME', 'VK_ICD_FILENAMES'):
|
|
self.assertEqual(bridge['env'].get(key), env.get(key), key)
|
|
client_path = '/steam/steamrtarm64:/steam/steamrtarm64/panorama'
|
|
if inherited.get('LD_LIBRARY_PATH'):
|
|
client_path += ':' + inherited['LD_LIBRARY_PATH']
|
|
self.assertEqual(result.stdout.splitlines(), ['1', client_path])
|
|
|
|
def test_session_exit_stops_the_library_helper(self):
|
|
source = (BIN / 'droiddeck-session').read_text()
|
|
launch = next(line for line in source.splitlines()
|
|
if 'droiddeck-steam-compat "$steam_root"' in line)
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
pid = root / 'pid'
|
|
helper = root / 'droiddeck-steam-compat'
|
|
helper.write_text('#!/bin/sh\necho $$ > "$PID_FILE"\nexec sleep 30\n')
|
|
helper.chmod(0o755)
|
|
env = dict(os.environ, PATH=str(root) + os.pathsep + os.environ['PATH'],
|
|
PID_FILE=str(pid), steam_root='/steam', steam_x64='0')
|
|
subprocess.run(['bash', '-c', '_bl_compat_env=(env)\n' + launch + '\n'
|
|
'until [ -s "$PID_FILE" ]; do sleep 0.05; done\n'
|
|
'kill $(jobs -p)\nwait'],
|
|
env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=10)
|
|
helper_pid = int(pid.read_text())
|
|
try:
|
|
os.kill(helper_pid, 0)
|
|
except ProcessLookupError:
|
|
return
|
|
os.kill(helper_pid, 9)
|
|
self.fail('droiddeck-steam-compat outlived the session')
|
|
|
|
def test_the_x86_64_client_gets_only_the_file_dialog_bridge(self):
|
|
source = (BIN / 'droiddeck-session').read_text()
|
|
start = source.index(' if [ "$steam_x64" = 1 ]; then\n { droiddeck-steam-compat --files-only')
|
|
block = source[start:source.index(' fi\n', start) + len(' fi\n')]
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
helper = root / 'droiddeck-steam-compat'
|
|
helper.write_text('#!/bin/sh\necho "$@" >> "$ARGS_FILE"\n')
|
|
helper.chmod(0o755)
|
|
for x64, expected in (('1', '--files-only /steam'), ('0', '/steam')):
|
|
with self.subTest(x64=x64):
|
|
args = root / ('args-' + x64)
|
|
env = dict(os.environ, PATH=str(root) + os.pathsep + os.environ['PATH'],
|
|
ARGS_FILE=str(args), steam_root='/steam', steam_x64=x64)
|
|
subprocess.run(['bash', '-c', '_bl_compat_env=(env)\n' + block + 'wait\n'], env=env, timeout=10, check=True)
|
|
self.assertEqual(args.read_text().split('\n')[0], expected)
|
|
|
|
def test_files_only_mode_installs_only_the_file_dialog_hook(self):
|
|
import runpy
|
|
compat = runpy.run_path(str(BIN / 'droiddeck-steam-compat'))
|
|
calls = []
|
|
|
|
class Page:
|
|
def __init__(self, port, path):
|
|
self.ws = None
|
|
def evaluate(self, expression):
|
|
calls.append(('evaluate', expression[:40]))
|
|
return True
|
|
def call(self, method, params):
|
|
calls.append((method, params['name']))
|
|
|
|
helper = compat['Helper']('/steam', 1234, files_only=True)
|
|
helper.attach.__globals__.update(shared_context=lambda port: '/devtools/page/1', Page=Page)
|
|
self.assertTrue(helper.attach())
|
|
bindings = [name for method, name in calls if method == 'Runtime.addBinding']
|
|
self.assertEqual(bindings, [compat['FILE_BINDING']])
|
|
self.assertIn(('evaluate', compat['FILE_JS'][:40]), calls)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|