After commit 5ef166838394 ("test: add file-prefix for all fast-tests on
Linux") each test within a suite has its own --file-prefix filled with
the test name to enable parallel execution. It brought a couple of
drawbacks though:
* Solution only applied to one test suite.
* Each working directory occupied ~25MB, with hundreds of tests this
easily overfilled /run filesystems of small VMs. Currently executing
fast-tests suite consumes 2.8GB of RAM, and adding more tests created
problems for github CI.
* While it enabled parallel execution of tests within a single build
directory, --file-prefix argument could no longer be specified
externally (caused duplicate argument error). Specifying custom
--file-prefix was necessary when multiple builds ran in the same
environment, so the corresponding workflow became broken.
Move --file-prefix logic into a separate shell script, preserving
existing argument and cleaning the work directory after the test.
Apply it uniformly to all tests.
Signed-off-by: Marat Khalili <[email protected]>
---
v2: addressed AI comments and CI failures
* Added missing SPDX header to the new shell script.
* Fixed typo in handling dump_test_names.
* Following AI suggestion changed EUID check to UID check.
* Abandoned attempts to cover telemetry test, it is now out of scope.
app/test/suites/meson.build | 43 +++++-----
app/test/suites/run_test_with_temp_prefix.sh | 84 ++++++++++++++++++++
2 files changed, 108 insertions(+), 19 deletions(-)
create mode 100755 app/test/suites/run_test_with_temp_prefix.sh
diff --git a/app/test/suites/meson.build b/app/test/suites/meson.build
index 786c459c24b3..de3c28a64df0 100644
--- a/app/test/suites/meson.build
+++ b/app/test/suites/meson.build
@@ -23,6 +23,15 @@ if not has_hugepage
endif
endif
+if is_linux
+ # use wrapper providing per-test work directories to allow parallel runs
+ test_runner = find_program('run_test_with_temp_prefix.sh')
+ test_args_prefix = [dpdk_test]
+else
+ test_runner = dpdk_test
+ test_args_prefix = []
+endif
+
# process source files to determine the different unit test suites
# - fast_tests
# - perf_tests
@@ -41,14 +50,16 @@ foreach suite:test_suites
if developer_mode
warning('Test "@0@" is not defined in any test
suite'.format(t))
endif
- test(t, dpdk_test,
+ test(t, test_runner,
+ args: test_args_prefix,
env: ['DPDK_TEST=' + t],
timeout: timeout_seconds,
is_parallel: false)
endforeach
elif suite_name == 'stress-tests'
foreach t: suite_tests
- test(t, dpdk_test,
+ test(t, test_runner,
+ args: test_args_prefix,
env: ['DPDK_TEST=' + t],
timeout: timeout_seconds_stress,
is_parallel: false,
@@ -57,7 +68,8 @@ foreach suite:test_suites
elif suite_name != 'fast-tests'
# simple cases - tests without parameters or special handling
foreach t: suite_tests
- test(t, dpdk_test,
+ test(t, test_runner,
+ args: test_args_prefix,
env: ['DPDK_TEST=' + t],
timeout: timeout_seconds,
is_parallel: false,
@@ -81,7 +93,7 @@ foreach suite:test_suites
nohuge = params[1] == 'NOHUGE_OK'
asan = params[2] == 'ASAN_OK'
- test_args = []
+ test_args = test_args_prefix
if nohuge
test_args += test_no_huge_args
elif not has_hugepage
@@ -94,25 +106,17 @@ foreach suite:test_suites
test_args += ['-d', dpdk_drivers_build_dir]
endif
- # use unique file-prefix to allow parallel runs
- file_prefix = []
- trace_prefix = []
- if is_linux
- file_prefix = ['--file-prefix=' + test_name.underscorify()]
- trace_prefix = [file_prefix[0] + '_with_traces']
- endif
-
- test(test_name, dpdk_test,
- args : test_args + file_prefix,
+ test(test_name, test_runner,
+ args: test_args,
env: ['DPDK_TEST=' + test_name],
timeout : timeout_seconds_fast,
is_parallel : false,
suite : 'fast-tests')
if not is_windows and test_name == 'trace_autotest'
- trace_extra = ['--trace=.*',
-
'--trace-dir=@0@'.format(meson.current_build_dir())]
- test(test_name + '_with_traces', dpdk_test,
- args : test_args + trace_extra + trace_prefix,
+ test_args += ['--trace=.*']
+ test_args +=
['--trace-dir=@0@'.format(meson.current_build_dir())]
+ test(test_name + '_with_traces', test_runner,
+ args: test_args,
env: ['DPDK_TEST=' + test_name],
timeout : timeout_seconds_fast,
is_parallel : false,
@@ -165,7 +169,8 @@ dump_test_names = [
'dump_struct_sizes',
]
foreach arg : dump_test_names
- test(arg, dpdk_test,
+ test(arg, test_runner,
+ args: test_args_prefix,
env : ['DPDK_TEST=' + arg],
timeout : timeout_seconds_fast,
is_parallel : false,
diff --git a/app/test/suites/run_test_with_temp_prefix.sh
b/app/test/suites/run_test_with_temp_prefix.sh
new file mode 100755
index 000000000000..e7137b29a68f
--- /dev/null
+++ b/app/test/suites/run_test_with_temp_prefix.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2026 Huawei Technologies Co., Ltd
+# Run dpdk test with a temporary prefix and clean it up afterwards
+set -eEuo pipefail
+
+# Get value of the long option with name in the first argument, from the rest.
+get_arg_value() {
+ local arg_name="$1"
+ shift 1
+
+ local arg_value=''
+ local grab_next=false
+ local arg
+
+ for arg in "$@"; do
+ if $grab_next; then
+ arg_value="$arg"
+ grab_next=false
+ elif [[ "$arg" == "${arg_name}="* ]]; then
+ arg_value="${arg#*=}"
+ elif [[ "$arg" == "$arg_name" ]]; then
+ grab_next=true
+ fi
+ done
+
+ printf "%s\n" "$arg_value"
+}
+
+# Delete work directory passing through the return code
+delete_work_directory() {
+ local -r test_rc="$1"
+ [[ -z "${WORK_DIRECTORY:-}" ]] || rm -rf "$WORK_DIRECTORY"
+ return "$test_rc"
+}
+
+main() {
+ if [[ $# -eq 0 ]]; then
+ printf "Usage: %s <test_command> [arguments...]\n" "$0" >&2
+ printf "%s %s\n" \
+ "Runs a DPDK test with a temporary file prefix" \
+ "and cleans up the working directory." >&2
+ printf "Ensure the DPDK_TEST environment variable is set.\n" >&2
+ exit 1
+ fi
+ local test_command=("$@")
+
+ if [[ -z "${DPDK_TEST:-}" ]]; then
+ printf "Ensure the DPDK_TEST environment variable is set.\n" >&2
+ exit 1
+ fi
+ local -r dpdk_test="$DPDK_TEST"
+
+ # Make sure file prefix is determined and set in test args
+ local file_prefix="$(get_arg_value --file-prefix "${test_command[@]}")"
+ if [[ -z "$file_prefix" ]]; then
+ # If not yet specified, set --file-prefix to test name
+ file_prefix="$dpdk_test"
+ if [[ -n "$(get_arg_value --trace "${test_command[@]}")" ]];
then
+ # Some tests runs twice, with and without traces
+ file_prefix="${file_prefix}_with_traces"
+ fi
+ test_command+=("--file-prefix=$file_prefix")
+ fi
+
+ # Make sure runtime directory is determined and set in the environment
+ local runtime_directory="${RUNTIME_DIRECTORY:-}"
+ if [[ -z "$runtime_directory" ]]; then
+ # Follow the algorithm in eal_filesystem.c
+ if [[ "$UID" -eq 0 ]]; then
+ runtime_directory='/var/run'
+ else
+ runtime_directory="${XDG_RUNTIME_DIR:-/tmp}"
+ fi
+ export RUNTIME_DIRECTORY="$runtime_directory"
+ fi
+
+ WORK_DIRECTORY="$runtime_directory/dpdk/$file_prefix"
+ trap 'delete_work_directory "$?"' EXIT
+
+ "${test_command[@]}"
+}
+
+main "$@"
--
2.43.0