test: Detect dead connections

When the connection to a board dies, assume it is dead forever until
some user action is taken. Skip all remaining tests. This avoids CI
runs taking an hour, with hundreds of 30-second timeouts all to no
avail.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2024-10-09 18:29:03 -06:00 committed by Tom Rini
parent 681b8f86e4
commit 85d7dae377
2 changed files with 55 additions and 2 deletions

View file

@ -24,6 +24,7 @@ import pytest
import re
from _pytest.runner import runtestprotocol
import sys
from u_boot_spawn import BootFail, Timeout, Unexpected, handle_exception
# Globals: The HTML log file, and the connection to the U-Boot console.
log = None
@ -254,6 +255,7 @@ def pytest_configure(config):
ubconfig.board_identity = board_identity
ubconfig.gdbserver = gdbserver
ubconfig.dtb = build_dir + '/arch/sandbox/dts/test.dtb'
ubconfig.connection_ok = True
env_vars = (
'board_type',
@ -420,8 +422,21 @@ def u_boot_console(request):
Returns:
The fixture value.
"""
console.ensure_spawned()
if not ubconfig.connection_ok:
pytest.skip('Cannot get target connection')
return None
try:
console.ensure_spawned()
except OSError as err:
handle_exception(ubconfig, console, log, err, 'Lab failure', True)
except Timeout as err:
handle_exception(ubconfig, console, log, err, 'Lab timeout', True)
except BootFail as err:
handle_exception(ubconfig, console, log, err, 'Boot fail', True,
console.get_spawn_output())
except Unexpected:
handle_exception(ubconfig, console, log, err, 'Unexpected test output',
False)
return console
anchors = {}

View file

@ -8,6 +8,7 @@ Logic to spawn a sub-process and interact with its stdio.
import os
import re
import pty
import pytest
import signal
import select
import time
@ -27,6 +28,43 @@ class BootFail(Exception):
class Unexpected(Exception):
"""An exception sub-class that indicates that unexpected test was seen."""
def handle_exception(ubconfig, console, log, err, name, fatal, output=''):
"""Handle an exception from the console
Exceptions can occur when there is unexpected output or due to the board
crashing or hanging. Some exceptions are likely fatal, where retrying will
just chew up time to no available. In those cases it is best to cause
further tests be skipped.
Args:
ubconfig (ArbitraryAttributeContainer): ubconfig object
log (Logfile): Place to log errors
console (ConsoleBase): Console to clean up, if fatal
err (Exception): Exception which was thrown
name (str): Name of problem, to log
fatal (bool): True to abort all tests
output (str): Extra output to report on boot failure. This can show the
target's console output as it tried to boot
"""
msg = f'{name}: '
if fatal:
msg += 'Marking connection bad - no other tests will run'
else:
msg += 'Assuming that lab is healthy'
print(msg)
log.error(msg)
log.error(f'Error: {err}')
if output:
msg += f'; output {output}'
if fatal:
ubconfig.connection_ok = False
console.cleanup_spawn()
pytest.exit(msg)
class Spawn:
"""Represents the stdio of a freshly created sub-process. Commands may be
sent to the process, and responses waited for.