From 3703b658d594f8594e0036960e37f88256518fbe Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Wed, 26 Aug 2026 22:14:34 +0200 Subject: [PATCH 1/6] CI: Update to ubuntu-26.04 This solves an issue with po4a that does not translates all the documents. However, some build jobs fail now and will be fixed in the following commits. --- .github/workflows/ci.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d04b5052449..f3b44755aaf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ env: jobs: rip-and-test: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 45 steps: - name: Dump GitHub context @@ -74,7 +74,7 @@ jobs: .github/scripts/verify-clean-repo.sh rip-headless: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 45 steps: - name: Dump GitHub context @@ -126,7 +126,7 @@ jobs: .github/scripts/verify-clean-repo.sh rip-rtai: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 45 steps: - name: Dump GitHub context @@ -155,7 +155,7 @@ jobs: .github/scripts/verify-clean-repo.sh rip-and-test-clang: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 45 steps: - name: Dump GitHub context @@ -206,7 +206,7 @@ jobs: .github/scripts/verify-clean-repo.sh cppcheck: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 45 steps: - name: Checkout repository @@ -226,7 +226,7 @@ jobs: scripts/cppcheck.sh shellcheck: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 45 steps: - name: Checkout repository @@ -249,7 +249,7 @@ jobs: scripts/shellcheck.sh htmldocs: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 60 steps: - name: Dump GitHub context @@ -275,15 +275,15 @@ jobs: run: scripts/manpage-name-check.py --enforce docs/build/man - name: Check for derived-id section references run: scripts/docs-anchor-check.py --enforce - - name: Verify no untracked or modified files after build - run: | - #*.po and documentation.pot are modifyed by build. Ignore them for now. - .github/scripts/verify-clean-repo.sh ':(exclude)docs/po/*.po' ':(exclude)docs/po/documentation.pot' - name: HTML checks run: | set -x #-w sets warn only, remove to generate a CI failure on error scripts/htmlcheck.sh -w + - name: Verify no untracked or modified files after build + run: | + #*.po and documentation.pot are modified by build. Ignore them for now. + .github/scripts/verify-clean-repo.sh ':(exclude)docs/po/*.po' ':(exclude)docs/po/documentation.pot' - name: Tar linuxcnc-doc run: | set -x @@ -301,7 +301,7 @@ jobs: timeout-minutes: 75 strategy: matrix: - runner: ["ubuntu-24.04", "ubuntu-24.04-arm"] + runner: ["ubuntu-26.04", "ubuntu-26.04-arm"] image: ["debian:bookworm", "debian:trixie", "debian:sid"] include: - allow_fail: False @@ -391,7 +391,7 @@ jobs: if-no-files-found: error package-indep: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 75 strategy: matrix: @@ -444,7 +444,7 @@ jobs: .github/scripts/build-package-indep.sh - name: Verify no untracked or modified files after build run: | - #*.po and documentation.pot are modifyed by build. Ignore them for now. + #*.po and documentation.pot are modified by build. Ignore them for now. .github/scripts/verify-clean-repo.sh ':(exclude)VERSION' ':(exclude)debian/changelog' ':(exclude)docs/po/*.po' ':(exclude)docs/po/documentation.pot' - name: Install debian packages run: | @@ -481,7 +481,7 @@ jobs: if: (github.event_name == 'release' && github.event.action == 'published') || startsWith(github.ref, 'refs/tags/') permissions: contents: write - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 steps: - name: Download artifacts uses: actions/download-artifact@v8 From 7a600a6735e7eca328540cba12520d36b24aa039 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Wed, 26 Aug 2026 23:13:58 +0200 Subject: [PATCH 2/6] CI: Update to ubuntu-26.04: cppcheck cppcheck passes now. Replace #ifdef AAAAA with #if 0 so cppcheck does not check unused code. "make headers" before cppckeck, so include is populated. --- .github/scripts/build-headers.sh | 11 +++++++++++ .github/workflows/ci.yml | 7 +++++-- src/hal/classicladder/classicladder_gtk.c | 2 +- src/hal/classicladder/drawing.c | 2 +- src/hal/classicladder/vars_names.c | 2 +- 5 files changed, 19 insertions(+), 5 deletions(-) create mode 100755 .github/scripts/build-headers.sh diff --git a/.github/scripts/build-headers.sh b/.github/scripts/build-headers.sh new file mode 100755 index 00000000000..da4b339d46c --- /dev/null +++ b/.github/scripts/build-headers.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -eu #Needed so CI fails when anything is wrong +set -x + +#Any arguments are passed to configure + +cd src +./autogen.sh +./configure "$@" --disable-check-runtime-deps --enable-werror +make headers diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3b44755aaf..ecfe55090d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -217,9 +217,12 @@ jobs: - name: Install dependencies run: | set -x - .github/scripts/use-main-ubuntu-mirror.sh - sudo apt-get -q update + .github/scripts/install-deps.sh sudo apt-get --yes install cppcheck + - name: Build headers + run: | + set -x + .github/scripts/build-headers.sh --with-realtime=uspace - name: Cppcheck run: | set -x diff --git a/src/hal/classicladder/classicladder_gtk.c b/src/hal/classicladder/classicladder_gtk.c index b78690638d5..85a46c33a6b 100644 --- a/src/hal/classicladder/classicladder_gtk.c +++ b/src/hal/classicladder/classicladder_gtk.c @@ -1059,7 +1059,7 @@ void MainSectionWindowInitGtk() //no more used since menu/toolbar added... -#ifdef AAAAAAAAAAAAAAAAAAAAAA +#if 0 hboxbottom = gtk_hbox_new (FALSE,0); gtk_container_add (GTK_CONTAINER (vbox), hboxbottom); gtk_widget_show(hboxbottom); diff --git a/src/hal/classicladder/drawing.c b/src/hal/classicladder/drawing.c index 9a6f65b363f..35d24d39b01 100644 --- a/src/hal/classicladder/drawing.c +++ b/src/hal/classicladder/drawing.c @@ -352,7 +352,7 @@ void DrawElement( cairo_t * cr,int x,int y,int Width,int Height,StrElement Eleme char DisplayColorState = ( DrawingOption==DRAW_NORMAL && !EditDatas.ModeEdit && InfosGene->LadderState==STATE_RUN ); //Cairo.... -#ifdef AAAAAAAAAAAAA +#if 0 GdkGC * DynaGcOff; GdkGC * TheGc; GdkColor DynaGdkColor; diff --git a/src/hal/classicladder/vars_names.c b/src/hal/classicladder/vars_names.c index 97f569ea617..6fae792db71 100644 --- a/src/hal/classicladder/vars_names.c +++ b/src/hal/classicladder/vars_names.c @@ -42,7 +42,7 @@ //===OLD CODE NO MORE USED=== //with names directly in it... //to be deleted, but some precise errors codes aren't present in the new function... -#ifdef AAAAAAAAA +#if 0 char * CreateVarName(int Type, int Offset) { From f84a2739e9827b7d77a46069c89b1582e5247a12 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Wed, 26 Aug 2026 23:21:55 +0200 Subject: [PATCH 3/6] CI: Update to ubuntu-26.04: clang build clang needs -latomic: See https://en.cppreference.com/cpp/atomic/atomic Quote: On GCC and Clang, some of the functionality described here requires linking against -latomic. --- src/rtapi/Submakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtapi/Submakefile b/src/rtapi/Submakefile index bb36cc34260..87890fbcae6 100644 --- a/src/rtapi/Submakefile +++ b/src/rtapi/Submakefile @@ -14,7 +14,7 @@ $(call TOOBJSDEPS, $(RTAPI_APP_SRCS)): EXTRAFLAGS += -DSIM \ -UULAPI -DRTAPI -pthread ../bin/rtapi_app: $(call TOOBJS, $(RTAPI_APP_SRCS)) $(ECHO) Linking $(notdir $@) - $(Q)$(CXX) -rdynamic -o $@ $^ $(LIBDL) -pthread -lrt -lfmt $(LIBUDEV_LIBS) -ldl -lcap $(LDFLAGS) + $(Q)$(CXX) -rdynamic -o $@ $^ $(LIBDL) -pthread -lrt -lfmt -latomic $(LIBUDEV_LIBS) -ldl -lcap $(LDFLAGS) TARGETS += ../bin/rtapi_app USPACE_POSIX_SRCS := rtapi/uspace_posix.cc From bf18fd6d469d1f9a6edd3c322efbde424e5595fb Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Tue, 6 Oct 2026 23:00:40 +0200 Subject: [PATCH 4/6] runtests: Exit on ctrl-c --- scripts/runtests.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/runtests.in b/scripts/runtests.in index 76ccab8ce3d..490a72d52fc 100755 --- a/scripts/runtests.in +++ b/scripts/runtests.in @@ -204,7 +204,7 @@ test_and_remove_shmem() { } TMPDIR=$(mktemp -d /tmp/runtest.XXXXXX) -trap 'rm -rf "$TMPDIR"' 0 1 2 3 15 +trap 'rm -rf "$TMPDIR" ; exit 1' 0 1 2 3 15 run_tests () { From 433fe8d0f4d95087d11088fb75c4dd93a071eab7 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Tue, 6 Oct 2026 23:05:40 +0200 Subject: [PATCH 5/6] runtests: Extract test runner to function --- scripts/runtests.in | 204 +++++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 98 deletions(-) diff --git a/scripts/runtests.in b/scripts/runtests.in index 490a72d52fc..792f3a08e78 100755 --- a/scripts/runtests.in +++ b/scripts/runtests.in @@ -203,9 +203,109 @@ test_and_remove_shmem() { return $ret } -TMPDIR=$(mktemp -d /tmp/runtest.XXXXXX) -trap 'rm -rf "$TMPDIR" ; exit 1' 0 1 2 3 15 +run_one_test() { + if [ "$#" -ne 1 ]; then + echo "ERROR: run_one_test testfile" + return 1 + fi + testname=$1 + testdir=$(dirname "$testname") + # check if there's a "musthave" file with prerequisites from config.h + if [ -e "$testdir/musthave" ] ; then + # one prerequisite per line + while IFS= read -r prereq ; do + if ! grep --quiet --regexp "^#define HAVE_$prereq.*" "$TOPDIR/src/config.h" ; then + echo "Skipping test for missing prerequisite \"$prereq\": $testdir" 1>&2 + SKIP=$((SKIP + 1)) + return 0 + fi + done < "$testdir/musthave" + fi + # skip test if there's a "skip" file + if [ -e "$testdir/skip" ]; then + if ! [ -x "$testdir/skip" ] || ! "$testdir/skip"; then + echo "Skipping disabled test: $testdir" 1>&2 + SKIP=$((SKIP + 1)) + return 0 + fi + fi + if $NOSUDO && [ -e "$testdir/control" ] && \ + grep Restrictions: "$testdir/control" | grep -q sudo; then + if ! [ -x "$testdir/skip" ] || ! "$testdir/skip"; then + echo "Skipping sudo test: $testdir" 1>&2 + SKIP=$((SKIP + 1)) + return 0 + fi + fi + NUM=$((NUM + 1)) + TEST_DIR=$(readlink -f "$testdir") + export TEST_DIR + echo "Running test: $testdir" 1>&2 + if test -n "$SYSTEM_BUILD"; then + # Tell `halcompile` where to install comps + USER_MODULE_DIR=$(readlink -f "$testdir") \ + PATH=$(readlink -f "$testdir"):$PATH \ + run_test "$testname" + else + run_test "$testname" + fi + exitcode=$? + if [ "$exitcode" -ne 0 ]; then + reason="test run exited with $exitcode" + else + if [ -e "$testdir/checkresult" ]; then + "$testdir/checkresult" "$testdir/result" + exitcode=$? + reason="checkresult exited with $exitcode" + elif [ -f "$testdir/expected" ]; then + cmp -s "$testdir/expected" "$testdir/result" + exitcode=$? + reason="result differed from expected" + if [ "$exitcode" -ne 0 ]; then + diff -u "$testdir/expected" "$testdir/result" > "$TMPDIR/diff" + SIZE=$(wc -l < "$TMPDIR/diff") + if [ "$SIZE" -lt 40 ]; then + cat "$TMPDIR/diff" + else + OMIT=$((SIZE-40)) + head -40 "$TMPDIR/diff" + echo "($OMIT more lines omitted)" + fi + fi + else + exitcode=1 + reason="Neither expected nor checkresult existed" + fi + fi + if [ "$exitcode" -ne 0 ]; then + echo "*** $testdir: FAIL: $reason" + if test $PRINT = 1; then + echo "************** result:" + tail -500 "$testdir/result" | sed 's/^/ /' + echo "************** stderr:" + tail -500 "$testdir/stderr" | sed 's/^/ /' + echo "**************" + fi + FAIL=$((FAIL + 1)) + FAIL_NAMES="$FAIL_NAMES"$'\n'"$testdir" + if test $STOP = 1; then + return 0 + fi + else + if [ $NOCLEAN -eq 0 ]; then + rm -f "$testdir/stderr" "$testdir/result" \ + "$testdir"/*.var "$testdir"/*.var.bak + fi + fi + if ! test_and_remove_shmem; then + if [ $? -eq 2 ]; then + # Cannot remove attached segments. Fail hard. + exit 1 + fi + SHMERR=$((SHMERR + 1)) + fi +} run_tests () { if ! test_shmem; then @@ -216,102 +316,7 @@ run_tests () { | sort > "$TMPDIR/alltests" while read -r testname; do - testdir=$(dirname "$testname") - # check if there's a "musthave" file with prerequisites from config.h - if [ -e "$testdir/musthave" ] ; then - # one prerequisite per line - while IFS= read -r prereq ; do - if ! grep --quiet --regexp "^#define HAVE_$prereq.*" "$TOPDIR/src/config.h" ; then - echo "Skipping test for missing prerequisite \"$prereq\": $testdir" 1>&2 - SKIP=$((SKIP + 1)) - continue 3 - fi - done < "$testdir/musthave" - fi - # skip test if there's a "skip" file - if [ -e "$testdir/skip" ]; then - if ! [ -x "$testdir/skip" ] || ! "$testdir/skip"; then - echo "Skipping disabled test: $testdir" 1>&2 - SKIP=$((SKIP + 1)) - continue - fi - fi - if $NOSUDO && [ -e "$testdir/control" ] && \ - grep Restrictions: "$testdir/control" | grep -q sudo; then - if ! [ -x "$testdir/skip" ] || ! "$testdir/skip"; then - echo "Skipping sudo test: $testdir" 1>&2 - SKIP=$((SKIP + 1)) - continue - fi - fi - NUM=$((NUM + 1)) - TEST_DIR=$(readlink -f "$testdir") - export TEST_DIR - echo "Running test: $testdir" 1>&2 - if test -n "$SYSTEM_BUILD"; then - # Tell `halcompile` where to install comps - USER_MODULE_DIR=$(readlink -f "$testdir") \ - PATH=$(readlink -f "$testdir"):$PATH \ - run_test "$testname" - else - run_test "$testname" - fi - exitcode=$? - if [ "$exitcode" -ne 0 ]; then - reason="test run exited with $exitcode" - else - if [ -e "$testdir/checkresult" ]; then - "$testdir/checkresult" "$testdir/result" - exitcode=$? - reason="checkresult exited with $exitcode" - elif [ -f "$testdir/expected" ]; then - cmp -s "$testdir/expected" "$testdir/result" - exitcode=$? - reason="result differed from expected" - if [ "$exitcode" -ne 0 ]; then - diff -u "$testdir/expected" "$testdir/result" > "$TMPDIR/diff" - SIZE=$(wc -l < "$TMPDIR/diff") - if [ "$SIZE" -lt 40 ]; then - cat "$TMPDIR/diff" - else - OMIT=$((SIZE-40)) - head -40 "$TMPDIR/diff" - echo "($OMIT more lines omitted)" - fi - fi - else - exitcode=1 - reason="Neither expected nor checkresult existed" - fi - fi - if [ "$exitcode" -ne 0 ]; then - echo "*** $testdir: FAIL: $reason" - if test $PRINT = 1; then - echo "************** result:" - tail -500 "$testdir/result" | sed 's/^/ /' - echo "************** stderr:" - tail -500 "$testdir/stderr" | sed 's/^/ /' - echo "**************" - fi - FAIL=$((FAIL + 1)) - FAIL_NAMES="$FAIL_NAMES"$'\n'"$testdir" - if test $STOP = 1; then - break - fi - else - if [ $NOCLEAN -eq 0 ]; then - rm -f "$testdir/stderr" "$testdir/result" \ - "$testdir"/*.var "$testdir"/*.var.bak - fi - fi - - if ! test_and_remove_shmem; then - if [ $? -eq 2 ]; then - # Cannot remove attached segments. Fail hard. - exit 1 - fi - SHMERR=$((SHMERR + 1)) - fi + run_one_test "$testname" done < "$TMPDIR/alltests" SUCC=$((NUM-FAIL)) @@ -352,6 +357,9 @@ Usage: EOF } +TMPDIR=$(mktemp -d /tmp/runtest.XXXXXX) +trap 'rm -rf "$TMPDIR" ; exit 1' 0 1 2 3 15 + CLEAN_ONLY=0 NOCLEAN=0 NOSUDO=false From 2e6f5403945e38a9ae864f869557d0c5f0b8dcce Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Tue, 6 Oct 2026 23:08:57 +0200 Subject: [PATCH 6/6] runtests: Parallel test mode This allows to run tests in parallel using bwarp for isolation of the linuxcnc processes --- .github/workflows/ci.yml | 11 ++-- debian/control.top.in | 2 + scripts/runtests.in | 131 +++++++++++++++++++++++++++++++++------ 3 files changed, 121 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecfe55090d8..0b66610d76f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,7 @@ concurrency: env: DEBIAN_FRONTEND: noninteractive + RUNTEST_JOBS: 32 jobs: @@ -56,7 +57,7 @@ jobs: - name: Test run: | set -x - scripts/rip-environment runtests -p -d + scripts/rip-environment runtests -j $RUNTEST_JOBS -p -d - name: Upload UI smoke screenshots if: always() uses: actions/upload-artifact@v7 @@ -120,7 +121,7 @@ jobs: - name: Test run: | set -x - scripts/rip-environment runtests -p ./tests + scripts/rip-environment runtests -j $RUNTEST_JOBS -p ./tests - name: Verify no untracked or modified files after test run: | .github/scripts/verify-clean-repo.sh @@ -188,7 +189,7 @@ jobs: - name: Test run: | set -x - scripts/rip-environment runtests -p -d + scripts/rip-environment runtests -j $RUNTEST_JOBS -p -d - name: Upload UI smoke screenshots if: always() uses: actions/upload-artifact@v7 @@ -317,7 +318,7 @@ jobs: image: ${{ matrix.image }} # IPC_OWNER is needed for shmget IPC_CREAT # SYS_ADMIN is needed for shmctl IPC_SET - options: --cap-add=IPC_OWNER --cap-add=SYS_ADMIN + options: --cap-add=IPC_OWNER --cap-add=SYS_ADMIN --security-opt apparmor=unconfined --security-opt seccomp=unconfined continue-on-error: ${{ matrix.allow_fail }} steps: - name: Dump GitHub context @@ -366,7 +367,7 @@ jobs: passwd -d testrunner adduser testrunner sudo chmod 0777 $(find tests/ -type d) # make test dirs world-writable for the testrunner - su -c "./scripts/runtests -p -d ./tests" testrunner + su -c "./scripts/runtests -j $RUNTEST_JOBS -p -d ./tests" testrunner - name: Verify no untracked or modified files after test run: | .github/scripts/verify-clean-repo.sh ':(exclude)VERSION' ':(exclude)debian/changelog' diff --git a/debian/control.top.in b/debian/control.top.in index f08b04739f4..894a747f90b 100644 --- a/debian/control.top.in +++ b/debian/control.top.in @@ -19,6 +19,8 @@ Build-Depends: autoconf, automake, bwidget (>= 1.7), + bubblewrap, + parallel, desktop-file-utils, intltool, libboost-python-dev, diff --git a/scripts/runtests.in b/scripts/runtests.in index 792f3a08e78..1570e0682f4 100755 --- a/scripts/runtests.in +++ b/scripts/runtests.in @@ -315,17 +315,65 @@ run_tests () { find "$@" -name test.hal -or -name test.sh -or -name test \ | sort > "$TMPDIR/alltests" - while read -r testname; do - run_one_test "$testname" - done < "$TMPDIR/alltests" - - SUCC=$((NUM-FAIL)) - echo "Runtest: $NUM tests run, $SUCC successful, $FAIL failed, $SKIP skipped, $SHMERR shmem errors" - if [ "$FAIL" -ne 0 ]; then - echo "Failed: $FAIL_NAMES" - exit 1; + if [ "$PARALLEL" -gt 0 ]; then + TMPDIR_PAR=$(mktemp -d /tmp/runtest-parallel.XXXXXX) #Save and sumarize results in $TMPDIR_PAR/testlog.txt which is bound from outside + + #ro-bind: / (root) so if any files are written at an unknown location, an error is generated + #dev: add device files + #tmpfs: /tmp /var/tmp (No files from host are needed there) + #tmp-overlay: $HOME, $TOPDIR (Files from host are needed but writes are per instance and discarded) + # Withouth $HOME overlay, some tests fail. There are some files created and changed there. + #bind: $TOPDIR/tests (The test results are stored there and needed on the host) + # Could generate issues when multiple tests write the same result file + #Isolate: ipc, pid, net, proc + BWRAPOPTS=( + "--ro-bind" "/" "/" + "--dev" "/dev" + "--tmpfs" "/tmp" + "--tmpfs" "/var/tmp" + "--overlay-src" "$HOME" "--tmp-overlay" "$HOME" + "--overlay-src" "$TOPDIR" "--tmp-overlay" "$TOPDIR" + "--bind" "$TOPDIR/tests" "$TOPDIR/tests" + "--unshare-ipc" + "--unshare-pid" + "--unshare-net" + "--proc" "/proc" + "--die-with-parent" + ) + CMD="bwrap ${BWRAPOPTS[*]} -- scripts/runtests ${WORKER_OPT[*]} -w {}" + + parallel -j "$PARALLEL" "$CMD" < "$TMPDIR/alltests" 4> "$TMPDIR_PAR/testlog.txt" + + #Create sumary based on testlog + ALL=$(wc -l < "$TMPDIR/alltests") + NUM=$(wc -l < "$TMPDIR_PAR/testlog.txt") + SHMERR=$(grep -c SHMERR < "$TMPDIR_PAR/testlog.txt") + SUCC=$(grep -c SUCCESS < "$TMPDIR_PAR/testlog.txt") + FAIL=$(grep -c FAILED < "$TMPDIR_PAR/testlog.txt") + FAIL_NAMES=$(grep FAILED < "$TMPDIR_PAR/testlog.txt" | sed 's/ FAILED$//') + SKIP=$(grep -c SKIPPED < "$TMPDIR_PAR/testlog.txt") + rm -rf "$TMPDIR_PAR" + + echo "Runtest parallel: $ALL tests $NUM tests run, $SUCC successful, $FAIL failed, $SKIP skipped, $SHMERR shmem errors" + if [ "$FAIL" -ne 0 ]; then + echo "Failed:"$'\n'"$FAIL_NAMES" + exit 1; + else + exit 0; + fi else - exit 0; + while read -r testname; do + run_one_test "$testname" + done < "$TMPDIR/alltests" + + SUCC=$((NUM-FAIL)) + echo "Runtest: $NUM tests run, $SUCC successful, $FAIL failed, $SKIP skipped, $SHMERR shmem errors" + if [ "$FAIL" -ne 0 ]; then + echo "Failed: $FAIL_NAMES" + exit 1; + else + exit 0; + fi fi } @@ -354,6 +402,13 @@ Usage: Enable crash dumps: on a crashing test, print a gdb backtrace of the core, collected from wherever the system put it (coredumpctl or a plain-file core_pattern). Off by default; CI passes it. + + $P -j jobs + Run parallel jobs. + + $P -w test-script + Worker mode, used to run parallel jobs. The test result is returned on file descriptor 4. + Do not use this mode except to test the worker mode. 4>&1 can be used to show the result. EOF } @@ -365,21 +420,36 @@ NOCLEAN=0 NOSUDO=false STOP=0 PRINT=0 -while getopts cnuvsphd opt; do +PARALLEL=0 +WORKER=0 +WORKER_OPT=() +while getopts cnuvsphdj:w opt; do case "$opt" in - c) CLEAN_ONLY=1 ;; - n) NOCLEAN=1 ;; - u) NOSUDO=true ;; - v) VERBOSE=1 ;; - s) STOP=1 ;; - p) PRINT=1 ;; - d) export ENABLE_CRASHDUMPS=1 ;; + c) CLEAN_ONLY=1; WORKER_OPT+=(-c) ;; + n) NOCLEAN=1 ; WORKER_OPT+=(-n) ;; + u) NOSUDO=true; WORKER_OPT+=(-u) ;; + v) VERBOSE=1; WORKER_OPT+=(-v) ;; + s) STOP=1; WORKER_OPT+=(-s) ;; + p) PRINT=1; WORKER_OPT+=(-p) ;; + d) export ENABLE_CRASHDUMPS=1; WORKER_OPT+=(-d) ;; + j) PARALLEL="$OPTARG" ;; + w) WORKER=1 ;; h|?) usage; exit 0 ;; *) usage; exit 1 ;; esac done shift $((OPTIND-1)) +if [ "$PARALLEL" -gt 0 ]; then + #bwrap version needs to be >= 0.11.0 + s=$(bwrap --version) + version="${s##* }" + if [ "$(printf '%s\n' "$version" '0.11.0' | sort -V | head -n1)" != "0.11.0" ]; then + echo "brwap older than 0.11.0, --overlay-src not supported, falling back to single threaded" + PARALLEL=0; + fi +fi + if [ $# -eq 0 ]; then if [ -f test.hal ] || [ -f test.sh ]; then set -- . @@ -390,6 +460,31 @@ fi if [ $CLEAN_ONLY -eq 1 ]; then clean "$@" +elif [ $WORKER -eq 1 ]; then + if [ "$#" -ne 1 ] || [ ! -f "$1" ]; then + echo ERROR: worker mode expects one testfile as argument + exit 1; + fi + if [ "$PARALLEL" -ne 0 ]; then + echo ERROR: worker mode does not take -j argument + exit 1; + fi + run_one_test "$1" + #FD 4 is used in parallel to log test results, so stdout / stderr / fd 3 used above don't interfere + echo -n "$1" >&4 + if [ "$SHMERR" -ne 0 ]; then + echo " SHMERR" >&4 + fi + if [ "$FAIL" -ne 0 ]; then + echo " FAILED" >&4 + exit 1; + elif [ "$SKIP" -ne 0 ]; then + echo " SKIPPED" >&4 + exit 0; + else + echo " SUCCESS" >&4 + exit 0; + fi else run_tests "$@" fi