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)