91 lines
4.6 KiB
Python
91 lines
4.6 KiB
Python
"""Régressions P0 avec vrais Executor/Guard/Recovery et fenêtres GTK privées."""
|
|
from unittest.mock import patch
|
|
from common import *
|
|
from lab import Lab, Surfaces, build_helper, until
|
|
from login_focus import checkpoint, UUID
|
|
from session_v2.executor import Executor
|
|
from session_v2.guard import Guard
|
|
from session_v2.ipc import Sway
|
|
from session_v2.storage import private_dir, read, atomic
|
|
from session_v2.startup import status, acknowledge
|
|
from session_v2.errors import Failure
|
|
|
|
|
|
def run_case(case):
|
|
with Lab() as lab:
|
|
apps = Surfaces(lab, build_helper(lab.directory))
|
|
try:
|
|
lab.command('workspace "10"')
|
|
apps.create('limusic-app')
|
|
lab.command('workspace "1"')
|
|
kitty = apps.create('kitty')
|
|
firefox = apps.create('firefox')
|
|
runtime = private_dir(lab.directory / 'runtime')
|
|
data = checkpoint()
|
|
sway = Sway(lab.socket)
|
|
commands, captures, injected = [], [], []
|
|
raw_command = sway.command
|
|
def command(text):
|
|
commands.append(text)
|
|
return raw_command(text)
|
|
sway.command = command
|
|
def corrupt_layout():
|
|
lab.command(f'[con_id={firefox["id"]}] focus')
|
|
lab.command('layout splitv')
|
|
injected.append(True)
|
|
class Provider:
|
|
def resolve(self, expected, nodes): return {UUID: nodes[0]['id']}
|
|
def capture(self, nodes):
|
|
captures.append(True)
|
|
# Trois vérifications : avant focus, après resume, après finish.
|
|
if case in ('last-capture-layout', 'last-capture-swap') and len(captures) == 3:
|
|
if case == 'last-capture-layout': corrupt_layout()
|
|
else:
|
|
lab.command(f'[con_id={firefox["id"]}] swap container with con_id {kitty["id"]}')
|
|
injected.append(True)
|
|
return {UUID: nodes[0]['id']}
|
|
raw_finish = Guard.finish
|
|
def finish(guard):
|
|
answer = raw_finish(guard)
|
|
if case == 'guard-finish-layout' and not injected: corrupt_layout()
|
|
return answer
|
|
def guard(*args):
|
|
value = Guard(*args)
|
|
if case in ('guard-replacement', 'guard-extra'):
|
|
if case == 'guard-replacement':
|
|
lab.command(f'[con_id={kitty["id"]}] kill')
|
|
until(lambda: not any(n['id'] == kitty['id'] for n in lab.windows()))
|
|
new = apps.create('kitty')
|
|
assert new['id'] != kitty['id']
|
|
injected.append(new['id'])
|
|
return value
|
|
status(runtime, sway.session, data, True)
|
|
with patch('session_v2.executor.Guard', side_effect=guard), patch.object(Guard, 'finish', finish), \
|
|
patch('session_v2.guard.discover', return_value=[]), \
|
|
patch('session_v2.executor.launch', side_effect=AssertionError('LAUNCH_FORBIDDEN')):
|
|
try: Executor(sway, Catalog(), Provider(), runtime, build(lab.directory), lab.env).apply(data, True)
|
|
except Failure as exc: reason = exc.code
|
|
else: raise AssertionError('P0_FALSE_SUCCESS')
|
|
report = read(runtime / 'session-v2-restore-attempt.json')
|
|
assert injected and report['status'] == 'failed', report
|
|
assert read(runtime / 'session-v2-recovery.json')['status'] != 'complete'
|
|
if case.startswith('guard-') and case != 'guard-finish-layout':
|
|
assert commands == [], commands
|
|
assert reason == 'APPLICATION_MEMBERSHIP_CHANGED', reason
|
|
else:
|
|
expected = 'RECOVERY_ORDER_CHANGED' if case == 'last-capture-swap' else 'FINAL_TREE_MISMATCH'
|
|
assert reason == expected, reason
|
|
if case.startswith('last-capture'): assert len(captures) == 3
|
|
try: acknowledge(runtime, sway.session, 'restored', report['transaction_id'])
|
|
except Failure: pass
|
|
else: raise AssertionError('P0_FALSE_ACK')
|
|
row = {'scenario': case, 'reason': reason, 'commands': commands, 'report': report,
|
|
'captures': len(captures), 'no_ack': True, 'real_login_validated': False}
|
|
atomic(private_dir(EVIDENCE) / ('p0-'+case+'.json'), row)
|
|
print(case, 'PASS', reason, flush=True)
|
|
finally: apps.close()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
for case in ('guard-replacement', 'guard-extra', 'last-capture-layout', 'last-capture-swap', 'guard-finish-layout'):
|
|
run_case(case)
|