Skip to content

Commit 1157fd0

Browse files
committed
Merge patch series "labgrid: Provide an integration with Labgrid"
Simon Glass <sjg@chromium.org> says: Labgrid provides access to a hardware lab in an automated way. It is possible to boot U-Boot on boards in the lab without physically touching them. It relies on relays, USB UARTs and SD muxes, among other things. By way of background, about 4 years ago I wrong a thing called Labman[1] which allowed my lab of about 30 devices to be operated remotely, using tbot for the console and build integration. While it worked OK and I used it for many bisects, I didn't take it any further. It turns out that there was already an existing program, called Labgrid, which I did not know about at time (thank you Tom for telling me). It is more rounded than Labman and has a number of advantages: - does not need udev rules, mostly - has several existing users who rely on it - supports multiple machines exporting their devices It lacks a 'lab check' feature and a few other things, but these can be remedied. On and off over the past several weeks I have been experimenting with Labgrid. I have managed to create an initial U-Boot integration (this series) by adding various features to Labgrid[2] and the U-Boot test hooks. I hope that this might inspire others to set up boards and run tests automatically, rather than relying on infrequent, manual test. Perhaps it may even be possible to have a number of labs available. Included in the integration are a number of simple scripts which make it easy to connect to boards and run tests: ub-int <target> Build and boot on a target, starting an interactive session ub-cli <target> Build and boot on a target, ensure U-Boot starts and provide an interactive session from there ub-smoke <target> Smoke test U-Boot to check that it boots to a prompt on a target ub-bisect <target> Bisect a git tree to locate a failure on a particular target ub-pyt <target> <testspec> Run U-Boot pytests on a target Some of these help to provide the same tbot[4] workflow which I have relied on for several years, albeit much simpler versions. The goal here is to create some sort of script which can collect patches from the mailing list, apply them and test them on a selection of boards. I suspect that script already exists, so please let me know what you suggest. I hope you find this interesting and take a look! [1] https://github.com/sjg20/u-boot/tree/lab6a [2] labgrid-project/labgrid#1411 [3] https://github.com/sjg20/uboot-test-hooks/tree/labgrid [4] https://tbot.tools/index.html Link: https://lore.kernel.org/r/20241112141326.643128-1-sjg@chromium.org
2 parents 42b49f3 + 1888b09 commit 1157fd0

6 files changed

Lines changed: 374 additions & 54 deletions

File tree

.gitlab-ci.yml

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
variables:
44
DEFAULT_TAG: ""
55
MIRROR_DOCKER: docker.io
6+
SJG_LAB: ""
67

78
default:
89
tags:
@@ -17,6 +18,7 @@ stages:
1718
- testsuites
1819
- test.py
1920
- world build
21+
- sjg-lab
2022

2123
.buildman_and_testpy_template: &buildman_and_testpy_dfn
2224
stage: test.py
@@ -521,3 +523,156 @@ coreboot test.py:
521523
TEST_PY_TEST_SPEC: "not sleep"
522524
TEST_PY_ID: "--id qemu"
523525
<<: *buildman_and_testpy_dfn
526+
527+
.lab_template: &lab_dfn
528+
stage: sjg-lab
529+
rules:
530+
- if: $SJG_LAB == "1"
531+
when: always
532+
- when: manual
533+
tags: [ 'lab' ]
534+
script:
535+
- if [[ -z "${SJG_LAB}" ]]; then
536+
exit 0;
537+
fi
538+
# Environment:
539+
# SRC - source tree
540+
# OUT - output directory for builds
541+
- export SRC="$(pwd)"
542+
- export OUT="${SRC}/build/${BOARD}"
543+
- export PATH=$PATH:~/bin
544+
- export PATH=$PATH:/vid/software/devel/ubtest/u-boot-test-hooks/bin
545+
546+
# Load it on the device
547+
- ret=0
548+
- echo "role ${ROLE}"
549+
- export strategy="-s uboot -e off"
550+
- export USE_LABGRID_SJG=1
551+
# export verbose="-v"
552+
- ${SRC}/test/py/test.py --role ${ROLE} --build-dir "${OUT}"
553+
--capture=tee-sys -k "not bootstd" || ret=$?
554+
- U_BOOT_BOARD_IDENTITY="${ROLE}" u-boot-test-release || true
555+
- if [[ $ret -ne 0 ]]; then
556+
exit $ret;
557+
fi
558+
artifacts:
559+
when: always
560+
paths:
561+
- "build/${BOARD}/test-log.html"
562+
- "build/${BOARD}/multiplexed_log.css"
563+
expire_in: 1 week
564+
565+
rpi3:
566+
variables:
567+
ROLE: rpi3
568+
<<: *lab_dfn
569+
570+
opi_pc:
571+
variables:
572+
ROLE: opi_pc
573+
<<: *lab_dfn
574+
575+
pcduino3_nano:
576+
variables:
577+
ROLE: pcduino3_nano
578+
<<: *lab_dfn
579+
580+
samus:
581+
variables:
582+
ROLE: samus
583+
<<: *lab_dfn
584+
585+
link:
586+
variables:
587+
ROLE: link
588+
<<: *lab_dfn
589+
590+
jerry:
591+
variables:
592+
ROLE: jerry
593+
<<: *lab_dfn
594+
595+
minnowmax:
596+
variables:
597+
ROLE: minnowmax
598+
<<: *lab_dfn
599+
600+
opi_pc2:
601+
variables:
602+
ROLE: opi_pc2
603+
<<: *lab_dfn
604+
605+
bpi:
606+
variables:
607+
ROLE: bpi
608+
<<: *lab_dfn
609+
610+
rpi2:
611+
variables:
612+
ROLE: rpi2
613+
<<: *lab_dfn
614+
615+
bob:
616+
variables:
617+
ROLE: bob
618+
<<: *lab_dfn
619+
620+
ff3399:
621+
variables:
622+
ROLE: ff3399
623+
<<: *lab_dfn
624+
625+
coral:
626+
variables:
627+
ROLE: coral
628+
<<: *lab_dfn
629+
630+
rpi3z:
631+
variables:
632+
ROLE: rpi3z
633+
<<: *lab_dfn
634+
635+
bbb:
636+
variables:
637+
ROLE: bbb
638+
<<: *lab_dfn
639+
640+
kevin:
641+
variables:
642+
ROLE: kevin
643+
<<: *lab_dfn
644+
645+
pine64:
646+
variables:
647+
ROLE: pine64
648+
<<: *lab_dfn
649+
650+
c4:
651+
variables:
652+
ROLE: c4
653+
<<: *lab_dfn
654+
655+
rpi4:
656+
variables:
657+
ROLE: rpi4
658+
<<: *lab_dfn
659+
660+
rpi0:
661+
variables:
662+
ROLE: rpi0
663+
<<: *lab_dfn
664+
665+
snow:
666+
variables:
667+
ROLE: snow
668+
<<: *lab_dfn
669+
670+
pcduino3:
671+
variables:
672+
ROLE: pcduino3
673+
<<: *lab_dfn
674+
675+
nyan-big:
676+
variables:
677+
ROLE: nyan-big
678+
<<: *lab_dfn

test/py/conftest.py

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import pytest
2424
import re
2525
from _pytest.runner import runtestprotocol
26+
import subprocess
2627
import sys
2728
from u_boot_spawn import BootFail, Timeout, Unexpected, handle_exception
2829

@@ -65,12 +66,16 @@ def pytest_addoption(parser):
6566

6667
parser.addoption('--build-dir', default=None,
6768
help='U-Boot build directory (O=)')
69+
parser.addoption('--build-dir-extra', default=None,
70+
help='U-Boot build directory for extra build (O=)')
6871
parser.addoption('--result-dir', default=None,
6972
help='U-Boot test result/tmp directory')
7073
parser.addoption('--persistent-data-dir', default=None,
7174
help='U-Boot test persistent generated data directory')
7275
parser.addoption('--board-type', '--bd', '-B', default='sandbox',
7376
help='U-Boot board type')
77+
parser.addoption('--board-type-extra', '--bde', default='sandbox',
78+
help='U-Boot extra board type')
7479
parser.addoption('--board-identity', '--id', default='na',
7580
help='U-Boot board identity/instance')
7681
parser.addoption('--build', default=False, action='store_true',
@@ -80,6 +85,9 @@ def pytest_addoption(parser):
8085
parser.addoption('--gdbserver', default=None,
8186
help='Run sandbox under gdbserver. The argument is the channel '+
8287
'over which gdbserver should communicate, e.g. localhost:1234')
88+
parser.addoption('--role', help='U-Boot board role (for Labgrid-sjg)')
89+
parser.addoption('--use-running-system', default=False, action='store_true',
90+
help="Assume that U-Boot is ready and don't wait for a prompt")
8391

8492
def run_build(config, source_dir, build_dir, board_type, log):
8593
"""run_build: Build U-Boot
@@ -125,26 +133,71 @@ def get_details(config):
125133
Returns:
126134
tuple:
127135
str: Board type (U-Boot build name)
136+
str: Extra board type (where two U-Boot builds are needed)
128137
str: Identity for the lab board
129138
str: Build directory
139+
str: Extra build directory (where two U-Boot builds are needed)
130140
str: Source directory
131141
"""
132-
board_type = config.getoption('board_type')
133-
board_identity = config.getoption('board_identity')
142+
role = config.getoption('role')
143+
144+
# Get a few provided parameters
134145
build_dir = config.getoption('build_dir')
146+
build_dir_extra = config.getoption('build_dir_extra')
147+
if role:
148+
# When using a role, build_dir and build_dir_extra are normally not set,
149+
# since they are picked up from Labgrid-sjg via the u-boot-test-getrole
150+
# script
151+
board_identity = role
152+
cmd = ['u-boot-test-getrole', role, '--configure']
153+
env = os.environ.copy()
154+
if build_dir:
155+
env['U_BOOT_BUILD_DIR'] = build_dir
156+
if build_dir_extra:
157+
env['U_BOOT_BUILD_DIR_EXTRA'] = build_dir_extra
158+
proc = subprocess.run(cmd, capture_output=True, encoding='utf-8',
159+
env=env)
160+
if proc.returncode:
161+
raise ValueError(proc.stderr)
162+
# For debugging
163+
# print('conftest: lab:', proc.stdout)
164+
vals = {}
165+
for line in proc.stdout.splitlines():
166+
item, value = line.split(' ', maxsplit=1)
167+
k = item.split(':')[-1]
168+
vals[k] = value
169+
# For debugging
170+
# print('conftest: lab info:', vals)
171+
172+
# Read the build directories here, in case none were provided in the
173+
# command-line arguments
174+
(board_type, board_type_extra, default_build_dir,
175+
default_build_dir_extra, source_dir) = (vals['board'],
176+
vals['board_extra'], vals['build_dir'], vals['build_dir_extra'],
177+
vals['source_dir'])
178+
else:
179+
board_type = config.getoption('board_type')
180+
board_type_extra = config.getoption('board_type_extra')
181+
board_identity = config.getoption('board_identity')
182+
183+
source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))
184+
default_build_dir = source_dir + '/build-' + board_type
185+
default_build_dir_extra = source_dir + '/build-' + board_type_extra
135186

136-
source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))
137-
default_build_dir = source_dir + '/build-' + board_type
187+
# Use the provided command-line arguments if present, else fall back to
138188
if not build_dir:
139189
build_dir = default_build_dir
190+
if not build_dir_extra:
191+
build_dir_extra = default_build_dir_extra
140192

141-
return board_type, board_identity, build_dir, source_dir
193+
return (board_type, board_type_extra, board_identity, build_dir,
194+
build_dir_extra, source_dir)
142195

143196
def pytest_xdist_setupnodes(config, specs):
144197
"""Clear out any 'done' file from a previous build"""
145198
global build_done_file
146199

147-
build_dir = get_details(config)[2]
200+
build_dir = get_details(config)[3]
148201

149202
build_done_file = Path(build_dir) / 'build.done'
150203
if build_done_file.exists():
@@ -184,7 +237,8 @@ def parse_config(conf_file):
184237
global console
185238
global ubconfig
186239

187-
board_type, board_identity, build_dir, source_dir = get_details(config)
240+
(board_type, board_type_extra, board_identity, build_dir, build_dir_extra,
241+
source_dir) = get_details(config)
188242

189243
board_type_filename = board_type.replace('-', '_')
190244
board_identity_filename = board_identity.replace('-', '_')
@@ -249,20 +303,25 @@ class ArbitraryAttributeContainer(object):
249303
ubconfig.test_py_dir = TEST_PY_DIR
250304
ubconfig.source_dir = source_dir
251305
ubconfig.build_dir = build_dir
306+
ubconfig.build_dir_extra = build_dir_extra
252307
ubconfig.result_dir = result_dir
253308
ubconfig.persistent_data_dir = persistent_data_dir
254309
ubconfig.board_type = board_type
310+
ubconfig.board_type_extra = board_type_extra
255311
ubconfig.board_identity = board_identity
256312
ubconfig.gdbserver = gdbserver
313+
ubconfig.use_running_system = config.getoption('use_running_system')
257314
ubconfig.dtb = build_dir + '/arch/sandbox/dts/test.dtb'
258315
ubconfig.connection_ok = True
259316

260317
env_vars = (
261318
'board_type',
319+
'board_type_extra',
262320
'board_identity',
263321
'source_dir',
264322
'test_py_dir',
265323
'build_dir',
324+
'build_dir_extra',
266325
'result_dir',
267326
'persistent_data_dir',
268327
)

test/py/tests/test_spi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ def test_spi_negative(u_boot_console):
695695

696696
# Read to relocation address
697697
output = u_boot_console.run_command('bdinfo')
698-
m = re.search('relocaddr\s*= (.+)', output)
698+
m = re.search(r'relocaddr\s*= (.+)', output)
699699
res_area = int(m.group(1), 16)
700700

701701
start = 0

0 commit comments

Comments
 (0)