test/py: Support --build when running tests in parallel

At present when -n is used, all workers try to build U-Boot at once.
Add a lock to ensure that only one of them builds, with the others using
the build that is produced.

The lock file is removed on startup.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2022-08-06 17:51:57 -06:00 committed by Tom Rini
parent 486680272e
commit 45a226a16b
2 changed files with 27 additions and 4 deletions

View File

@ -15,9 +15,11 @@
import atexit import atexit
import configparser import configparser
import errno import errno
import filelock
import io import io
import os import os
import os.path import os.path
from pathlib import Path
import pytest import pytest
import re import re
from _pytest.runner import runtestprotocol from _pytest.runner import runtestprotocol
@ -27,6 +29,8 @@ import sys
log = None log = None
console = None console = None
TEST_PY_DIR = os.path.dirname(os.path.abspath(__file__))
def mkdir_p(path): def mkdir_p(path):
"""Create a directory path. """Create a directory path.
@ -111,6 +115,18 @@ def run_build(config, source_dir, build_dir, board_type, log):
runner.close() runner.close()
log.status_pass('OK') log.status_pass('OK')
def pytest_xdist_setupnodes(config, specs):
"""Clear out any 'done' file from a previous build"""
global build_done_file
build_dir = config.getoption('build_dir')
board_type = config.getoption('board_type')
source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))
if not build_dir:
build_dir = source_dir + '/build-' + board_type
build_done_file = Path(build_dir) / 'build.done'
if build_done_file.exists():
os.remove(build_done_file)
def pytest_configure(config): def pytest_configure(config):
"""pytest hook: Perform custom initialization at startup time. """pytest hook: Perform custom initialization at startup time.
@ -145,8 +161,7 @@ def pytest_configure(config):
global console global console
global ubconfig global ubconfig
test_py_dir = os.path.dirname(os.path.abspath(__file__)) source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))
source_dir = os.path.dirname(os.path.dirname(test_py_dir))
board_type = config.getoption('board_type') board_type = config.getoption('board_type')
board_type_filename = board_type.replace('-', '_') board_type_filename = board_type.replace('-', '_')
@ -177,7 +192,13 @@ def pytest_configure(config):
log = multiplexed_log.Logfile(result_dir + '/test-log.html') log = multiplexed_log.Logfile(result_dir + '/test-log.html')
if config.getoption('build'): if config.getoption('build'):
run_build(config, source_dir, build_dir, board_type, log) worker_id = os.environ.get("PYTEST_XDIST_WORKER")
with filelock.FileLock(os.path.join(build_dir, 'build.lock')):
build_done_file = Path(build_dir) / 'build.done'
if (not worker_id or worker_id == 'master' or
not build_done_file.exists()):
run_build(config, source_dir, build_dir, board_type, log)
build_done_file.touch()
class ArbitraryAttributeContainer(object): class ArbitraryAttributeContainer(object):
pass pass
@ -209,7 +230,7 @@ def pytest_configure(config):
else: else:
parse_config('include/autoconf.mk') parse_config('include/autoconf.mk')
ubconfig.test_py_dir = test_py_dir ubconfig.test_py_dir = TEST_PY_DIR
ubconfig.source_dir = source_dir ubconfig.source_dir = source_dir
ubconfig.build_dir = build_dir ubconfig.build_dir = build_dir
ubconfig.result_dir = result_dir ubconfig.result_dir = result_dir

View File

@ -2,6 +2,7 @@ atomicwrites==1.4.1
attrs==19.3.0 attrs==19.3.0
coverage==4.5.4 coverage==4.5.4
extras==1.0.0 extras==1.0.0
filelock==3.0.12
fixtures==3.0.0 fixtures==3.0.0
importlib-metadata==0.23 importlib-metadata==0.23
linecache2==1.0.0 linecache2==1.0.0
@ -15,6 +16,7 @@ pyelftools==0.27
pygit2==1.9.2 pygit2==1.9.2
pyparsing==2.4.2 pyparsing==2.4.2
pytest==6.2.5 pytest==6.2.5
pytest-xdist==2.5.0
python-mimeparse==1.6.0 python-mimeparse==1.6.0
python-subunit==1.3.0 python-subunit==1.3.0
requests==2.25.1 requests==2.25.1