Re: [PATCH v4 8/8] selftests/verification: add tlob selftests
From: Gabriele Monaco
Date: Wed Jul 22 2026 - 09:44:54 EST
On Wed, 2026-07-08 at 23:38 +0800, wen.yang@xxxxxxxxx wrote:
> From: Wen Yang <wen.yang@xxxxxxxxx>
>
> Add seven ftrace-style test scripts for the tlob RV monitor under
> tools/testing/selftests/verification/test.d/tlob/. The tests cover
> uprobe binding management, budget violation detection, and per-state
> time accounting.
>
> Helper binaries tlob_target and tlob_sym are included in the same
> directory so the suite is self-contained. tlob_sym resolves ELF
> symbol offsets for uprobe registration; tlob_target provides busy-spin,
> sleep, and preempt workloads.
>
> ftracetest is updated to walk up the directory tree when searching for
> test.d/functions, so monitor subdirectories can be passed as the test
> directory without placing a dummy functions shim in each new directory.
I believe this last part deserves its own patch, so ftrace folks won't lose
track of it (and it's probably a good idea for them to Ack it, make sure they're
Cc'd).
>
> Signed-off-by: Wen Yang <wen.yang@xxxxxxxxx>
> ---
> tools/testing/selftests/ftrace/ftracetest | 18 +-
> .../testing/selftests/verification/.gitignore | 2 +
> tools/testing/selftests/verification/Makefile | 19 +-
> .../verification/test.d/tlob/Makefile | 28 +++
> .../test.d/tlob/run_tlob_tests.sh | 90 ++++++++
> .../verification/test.d/tlob/tlob_sym.c | 209 ++++++++++++++++++
> .../verification/test.d/tlob/tlob_target.c | 138 ++++++++++++
> .../verification/test.d/tlob/uprobe_bind.tc | 37 ++++
> .../test.d/tlob/uprobe_detail_running.tc | 51 +++++
> .../test.d/tlob/uprobe_detail_sleeping.tc | 50 +++++
> .../test.d/tlob/uprobe_detail_waiting.tc | 66 ++++++
> .../verification/test.d/tlob/uprobe_multi.tc | 64 ++++++
> .../test.d/tlob/uprobe_no_event.tc | 19 ++
> .../test.d/tlob/uprobe_violation.tc | 67 ++++++
> 14 files changed, 854 insertions(+), 4 deletions(-)
> create mode 100644 tools/testing/selftests/verification/test.d/tlob/Makefile
> create mode 100755
> tools/testing/selftests/verification/test.d/tlob/run_tlob_tests.sh
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/tlob_sym.c
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/tlob_target.c
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/uprobe_bind.tc
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/uprobe_detail_running.tc
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/uprobe_detail_sleeping.tc
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/uprobe_detail_waiting.tc
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/uprobe_multi.tc
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/uprobe_no_event.tc
> create mode 100644
> tools/testing/selftests/verification/test.d/tlob/uprobe_violation.tc
>
> diff --git a/tools/testing/selftests/ftrace/ftracetest
> b/tools/testing/selftests/ftrace/ftracetest
> index 0a56bf209f6c..91c007b0a74a 100755
> --- a/tools/testing/selftests/ftrace/ftracetest
> +++ b/tools/testing/selftests/ftrace/ftracetest
> @@ -159,9 +159,21 @@ parse_opts() { # opts
> if [ -n "$OPT_TEST_CASES" ]; then
> TEST_CASES=$OPT_TEST_CASES
> fi
> - if [ -n "$OPT_TEST_DIR" -a -f "$OPT_TEST_DIR"/test.d/functions ]; then
> - TOP_DIR=$OPT_TEST_DIR
> - TEST_DIR=$TOP_DIR/test.d
> + if [ -n "$OPT_TEST_DIR" ]; then
> + # Walk up from OPT_TEST_DIR to find the nearest ancestor containing
> + # test.d/functions, allowing monitor subdirectories to be passed
> directly.
> + dir=$OPT_TEST_DIR
> + while [ "$dir" != "/" ]; do
> + if [ -f "$dir/test.d/functions" ]; then
> + TOP_DIR=$dir
> + TEST_DIR=$TOP_DIR/test.d
> + break
> + fi
> + dir=$(dirname "$dir")
> + done
> + if [ -z "$TOP_DIR" ]; then
> + errexit "no test.d/functions found above $OPT_TEST_DIR"
> + fi
This won't happen, before calling parse_opts, the script initialises
TOP_DIR to `absdir $0` (ftracetest's folder). You can leave it as it is,
no need to catch an error since it was gracefully continuing anyway.
> fi
> }
>
> diff --git a/tools/testing/selftests/verification/.gitignore
> b/tools/testing/selftests/verification/.gitignore
> index 2659417cb2c7..cbbd03ee16c7 100644
> --- a/tools/testing/selftests/verification/.gitignore
> +++ b/tools/testing/selftests/verification/.gitignore
> @@ -1,2 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
> logs
> +test.d/tlob/tlob_sym
> +test.d/tlob/tlob_target
> diff --git a/tools/testing/selftests/verification/Makefile
> b/tools/testing/selftests/verification/Makefile
> index aa8790c22a71..0b32bdfdb8db 100644
> --- a/tools/testing/selftests/verification/Makefile
> +++ b/tools/testing/selftests/verification/Makefile
> @@ -1,8 +1,25 @@
> # SPDX-License-Identifier: GPL-2.0
> -all:
>
> TEST_PROGS := verificationtest-ktap
> TEST_FILES := test.d settings
> EXTRA_CLEAN := $(OUTPUT)/logs/*
>
> +# Subdirectories that provide binaries used by the test runner.
> +# Each entry must contain a Makefile that accepts OUTDIR= and
> +# deposits its binaries there.
Does the entry's Makefile support OUTDIR ? It doesn't look like it.
By the way, reimplementing things like this is probably going to break a
few things like installation (e.g. for distros to package the
kselftests) and clean target. Perhaps we could refactor it to use
standard kselftests methods. See my mockup at the end.
> +BUILD_SUBDIRS := test.d/tlob
> +
> include ../lib.mk
> +
> +all: $(patsubst %,_build_%,$(BUILD_SUBDIRS))
> +
> +clean: $(patsubst %,_clean_%,$(BUILD_SUBDIRS))
> +
> +.PHONY: $(patsubst %,_build_%,$(BUILD_SUBDIRS)) \
> + $(patsubst %,_clean_%,$(BUILD_SUBDIRS))
> +
> +$(patsubst %,_build_%,$(BUILD_SUBDIRS)): _build_%:
> + $(MAKE) -C $* OUTDIR="$(OUTPUT)" TOOLS_INCLUDES="$(TOOLS_INCLUDES)"
> +
> +$(patsubst %,_clean_%,$(BUILD_SUBDIRS)): _clean_%:
> + $(MAKE) -C $* OUTDIR="$(OUTPUT)" clean
> diff --git a/tools/testing/selftests/verification/test.d/tlob/Makefile
> b/tools/testing/selftests/verification/test.d/tlob/Makefile
> new file mode 100644
> index 000000000000..05a2d2599c4e
> --- /dev/null
> +++ b/tools/testing/selftests/verification/test.d/tlob/Makefile
> @@ -0,0 +1,28 @@
> +# SPDX-License-Identifier: GPL-2.0
> +# Builds tlob selftest helper binaries in the directory of this Makefile.
> +#
> +# Invoked by ../../Makefile via BUILD_SUBDIRS; outputs tlob_sym and
> +# tlob_target alongside the .tc scripts so they are self-contained.
> +
> +CFLAGS += $(TOOLS_INCLUDES)
> +
> +# For standalone execution via vng
> +FTRACETEST := ../../../ftrace/ftracetest
> +LOGDIR ?= ../../logs
Are those needed? They aren't used in the Makefile nor exported to the
executed scripts, I'd just drop them.
> +
> +.PHONY: all
> +all: tlob_sym tlob_target
> +
> +tlob_sym: tlob_sym.c
> + $(CC) $(CFLAGS) -o $@ $<
> +
> +tlob_target: tlob_target.c
> + $(CC) $(CFLAGS) -o $@ $<
> +
> +.PHONY: run_tests
> +run_tests: all
> + @./run_tlob_tests.sh
> +
> +.PHONY: clean
> +clean:
> + $(RM) tlob_sym tlob_target
> diff --git
> a/tools/testing/selftests/verification/test.d/tlob/run_tlob_tests.sh
> b/tools/testing/selftests/verification/test.d/tlob/run_tlob_tests.sh
> new file mode 100755
> index 000000000000..cd949756e713
> --- /dev/null
> +++ b/tools/testing/selftests/verification/test.d/tlob/run_tlob_tests.sh
> @@ -0,0 +1,90 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Standalone runner for tlob selftests
> +# Usage: ./run_tlob_tests.sh [options]
> +#
> +# Options:
> +# -v, --verbose Verbose output
> +# -k, --keep Keep test logs
> +# -l, --logdir DIR Log directory (default: ../../logs)
> +# -h, --help Show this help
I get you want a way to run tlob tests alone, but can we reduce the
amount of code to maintain? Why do we need to parse and forward
arguments? Cannot we just pass "$@" to ftracetest?
See that in my mockup later.
> +
> +set -e
> +
> +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
> +FTRACETEST="$SCRIPT_DIR/../../../ftrace/ftracetest"
> +LOGDIR="$SCRIPT_DIR/../../logs"
> +VERBOSE=""
> +KEEP=""
> +EXTRA_ARGS=""
> +
> +# Parse arguments
> +while [[ $# -gt 0 ]]; do
> + case $1 in
> + -v|--verbose)
> + VERBOSE="-v"
> + shift
> + ;;
> + -k|--keep)
> + KEEP="-k"
> + shift
> + ;;
> + -l|--logdir)
> + LOGDIR="$2"
> + shift 2
> + ;;
> + -h|--help)
> + echo "Usage: $0 [options]"
> + echo ""
> + echo "Options:"
> + echo " -v, --verbose Verbose output"
> + echo " -k, --keep Keep test logs"
> + echo " -l, --logdir DIR Log directory (default: ../../logs)"
> + echo " -h, --help Show this help"
> + echo ""
> + echo "Examples:"
> + echo " $0 # Run all tlob tests"
> + echo " $0 -v # Run with verbose output"
> + echo " $0 -v -l /tmp/tlob-logs # Custom log directory"
> + echo ""
> + echo "With vng:"
> + echo " vng -v --rwdir $LOGDIR -- $0"
> + exit 0
> + ;;
> + *)
> + EXTRA_ARGS="$EXTRA_ARGS $1"
> + shift
> + ;;
> + esac
> +done
> +
> +# Build test helpers
> +echo "Building tlob test helpers..."
> +make -C "$SCRIPT_DIR" all
> +
> +# Check ftracetest exists
> +if [ ! -x "$FTRACETEST" ]; then
> + echo "Error: $FTRACETEST not found or not executable"
> + echo "Make sure you're running from the correct directory"
> + exit 1
> +fi
> +
> +# Create log directory
> +mkdir -p "$LOGDIR"
> +
> +# Run tests
> +echo "Running tlob selftests..."
> +echo "Log directory: $LOGDIR"
> +echo ""
> +
> +# Export RV_BINDIR so test scripts can find tlob_target and tlob_sym
> +export RV_BINDIR="$SCRIPT_DIR"
> +
> +# Pass the test directory, not individual .tc files
> +# ftracetest will discover all .tc files in the directory
> +"$FTRACETEST" -K $VERBOSE $KEEP --rv --logdir "$LOGDIR" \
> + "$SCRIPT_DIR" $EXTRA_ARGS
> +
> +echo ""
> +echo "Tests completed. Logs saved to: $LOGDIR"
I tried to refactor it to follow more standard selftest building,
avoiding to maintain things ourselves. The only drawback is that you'd
have to move the tlob_*.c files to selftests/verification , then we can
still use RV_BINDIR but support it only via Makefile and
run_tlob_tests.sh (so let's drop defining it in all tests and save
inconvenience if things ever change).
By the way, this isn't necessarily bad, RV_BINDIR is a general term that
any other selftest can end up using (and shouldn't point to tlob's
directory).
I didn't do it to avoid confusion, but it may be more appropriate to
change the name (e.g. RVTEST_ROOT or VERIFICATIONTEST_ROOT)?
Now you won't need separate Makefiles and everything should work
seamlessly.
(I tested this in vng with both your script and the Makefile, but this
is far from a deep testing, it should apply cleanly on your tree)