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

Reply via email to