From 60282f02e8631cb7f473344d05396b0be91aabd3 Mon Sep 17 00:00:00 2001 From: "Salipalli(Temp), Venkata Satya Raja Preetam Jagan" Date: Thu, 15 Oct 2026 15:27:15 +0530 Subject: [PATCH] Add IGT display Tests - added dmabuf test - Added kms_vblank test with subtest filtering (excludes suspend/rpm) - Added kms_sysfs_edid_timing test for EDID validation - Added kms_setmode test for mode setting validation - Created README.md documentation for all tests - Added per-suite YAML definitions and send-to-lava integration. - All tests now use /usr/libexec/igt-gpu-tools/ as default path and support optional binary path override via CLI arguments. Signed-off-by: Salipalli(Temp), Venkata Satya Raja Preetam Jagan --- .../Display/igt-gpu-tools/dmabuf/README.md | 64 ++++++ .../Display/igt-gpu-tools/dmabuf/dmabuf.yaml | 20 ++ .../Display/igt-gpu-tools/dmabuf/run.sh | 176 ++++++++++++++++ .../igt-gpu-tools/kms_setmode/README.md | 80 ++++++++ .../kms_setmode/kms_setmode.yaml | 20 ++ .../Display/igt-gpu-tools/kms_setmode/run.sh | 176 ++++++++++++++++ .../kms_sysfs_edid_timing/README.md | 75 +++++++ .../kms_sysfs_edid_timing.yaml | 20 ++ .../kms_sysfs_edid_timing/run.sh | 176 ++++++++++++++++ .../igt-gpu-tools/kms_vblank/README.md | 79 ++++++++ .../igt-gpu-tools/kms_vblank/kms_vblank.yaml | 21 ++ .../Display/igt-gpu-tools/kms_vblank/run.sh | 189 ++++++++++++++++++ Runner/utils/functestlib.sh | 103 ++++++++++ 13 files changed, 1199 insertions(+) create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/README.md create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/dmabuf.yaml create mode 100755 Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/run.sh create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/README.md create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/kms_setmode.yaml create mode 100755 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/run.sh create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/README.md create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/kms_sysfs_edid_timing.yaml create mode 100755 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/run.sh create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/README.md create mode 100644 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/kms_vblank.yaml create mode 100755 Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/run.sh diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/README.md b/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/README.md new file mode 100644 index 000000000..4ab650bb7 --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/README.md @@ -0,0 +1,64 @@ +# dmabuf Test + +## Overview +The dmabuf test is an IGT (Intel GPU Tools) test that validates DMA-BUF (Direct Memory Access Buffer) functionality in the display subsystem. This test verifies the kernel's ability to handle DMA-BUF operations for graphics memory sharing. + +## Test Description +This test validates: +- DMA-BUF allocation and management +- Memory sharing between different subsystems +- Buffer import/export operations +- Kernel selftests for DMA-BUF functionality + +## Prerequisites +- IGT GPU tools must be installed on the target device +- Display hardware must be available +- Weston compositor will be stopped during test execution + +## Usage + +### Basic Usage (Default) +```bash +./run-test.sh dmabuf +``` +The test will automatically use the binary at `/usr/libexec/igt-gpu-tools/dmabuf` + +### With Custom Binary Path +```bash +./run-test.sh dmabuf --dmabuf-path /custom/path/to/dmabuf +``` + +Or: +```bash +./run-test.sh dmabuf /custom/path/to/dmabuf +``` + +### Help +```bash +cd Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf +./run.sh --help +``` + +## Test Results +The test generates: +- **Result file**: `dmabuf.res` - Contains PASS/FAIL/SKIP status +- **Log file**: `dmabuf_log.txt` - Contains detailed test output + +## Expected Behavior +- **PASS**: All subtests succeed or some subtests succeed with others skipped +- **SKIP**: All subtests are skipped (e.g., when kernel selftests are not available) +- **FAIL**: One or more subtests fail or the test exits with a non-zero code + +## Common Issues +1. **Test Skipped**: If the test shows "SKIP", it typically means the required kernel selftests are not available on the system. This is not necessarily an error - it indicates the test requirements are not met. + +2. **Binary Not Found**: Ensure IGT GPU tools are installed: + ```bash + # Check if binary exists + ls -l /usr/libexec/igt-gpu-tools/dmabuf + ``` + +## Notes +- The test automatically stops Weston before execution +- Exit code 77 indicates a SKIP condition (standard IGT behavior) +- Test output is parsed for SUCCESS, FAIL, and SKIP counts diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/dmabuf.yaml b/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/dmabuf.yaml new file mode 100644 index 000000000..0a69e2963 --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/dmabuf.yaml @@ -0,0 +1,20 @@ +metadata: + name: dmabuf + format: "Lava-Test Test Definition 1.0" + description: "Validates DMA-BUF buffer sharing between DRM/KMS and other kernel subsystems using the IGT dmabuf test suite. Stops any active Weston compositor before running and restores it afterwards." + os: + - linux + scope: + - functional + +params: + DMABUF_PATH: "/usr/libexec/igt-gpu-tools/dmabuf" + IGT_TIMEOUT: "300" + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf + - export IGT_TIMEOUT="${IGT_TIMEOUT}" + - ./run.sh --dmabuf-path "${DMABUF_PATH}" || true + - $REPO_PATH/Runner/utils/send-to-lava.sh dmabuf.res || true diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/run.sh b/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/run.sh new file mode 100755 index 000000000..fdd6c71bc --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/dmabuf/run.sh @@ -0,0 +1,176 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# ---- Source init_env & tools ---- +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then INIT_ENV="$SEARCH/init_env"; break; fi + SEARCH="$(dirname "$SEARCH")" +done +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 1 +fi + +# Only source if not already loaded (idempotent) +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" +fi +# Always source functestlib.sh, using $TOOLS exported by init_env +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" +# Source display helpers: Weston/Wayland lifecycle, DRM utilities, weston_restore_runtime +. "$TOOLS/lib_display.sh" + +# EXIT trap: safety-net cleanup when the script exits normally (PIDs already cleared). +# Signal traps: kill the IGT child, restore Weston, then record an interrupted FAIL. +weston_stopped_by_test=0 +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after test completion"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi' EXIT +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after signal interruption"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi; test_result_finish "FAIL" "test interrupted by signal"' INT TERM HUP + +TESTNAME="dmabuf" +RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" +test_result_init "$TESTNAME" "$RES_FILE" +# Default IGT test binary location +DEFAULT_IGT_PATH="/usr/libexec/igt-gpu-tools" +DMABUF_CMD="$DEFAULT_IGT_PATH/$TESTNAME" +# Configurable timeout in seconds for the IGT invocation +IGT_TIMEOUT="${IGT_TIMEOUT:-300}" + +test_path="$(find_test_case_by_name "$TESTNAME" 2>/dev/null)" +if [ -z "$test_path" ] || [ ! -d "$test_path" ]; then + test_path="$SCRIPT_DIR" +fi + +if [ ! -w "$test_path" ]; then + log_error "Cannot write to test directory: $test_path" + test_result_finish "FAIL" "Cannot write to test directory: $test_path" +fi + +while [ $# -gt 0 ]; do + case "$1" in + --dmabuf-path) + shift + if [ -n "${1:-}" ]; then + DMABUF_CMD="$1" + else + log_error "Missing value for --dmabuf-path parameter" + test_result_finish "FAIL" "Missing value for --dmabuf-path parameter" + fi + ;; + --help|-h) + log_info "Usage: $0 [--dmabuf-path BINARY_PATH] | [BINARY_PATH]" + log_info "Default binary path: $DEFAULT_IGT_PATH/$TESTNAME" + exit 0 + ;; + -*) + log_warn "Unknown argument: $1" + ;; + *) + DMABUF_CMD="$1" + ;; + esac + shift +done + +if ! cd "$test_path"; then + log_error "cd failed: $test_path" + test_result_finish "FAIL" "cd failed: $test_path" +fi + +log_info "-------------------Starting $TESTNAME Testcase-----------------------------" + +# Check if the binary exists and is executable +if [ ! -x "$DMABUF_CMD" ]; then + log_skip "$TESTNAME: dmabuf binary not found or not executable at: $DMABUF_CMD" + log_skip "Please ensure IGT GPU tools are installed or specify the binary path with --dmabuf-path" + test_result_finish "SKIP" "dmabuf binary not found or not executable" +fi + +log_info "Using dmabuf binary at: $DMABUF_CMD" + +# Validate IGT_TIMEOUT is a positive integer before stopping Weston +case "$IGT_TIMEOUT" in + ''|*[!0-9]*|0) + log_error "IGT_TIMEOUT must be a positive integer, got: '${IGT_TIMEOUT}'" + test_result_finish "FAIL" "invalid IGT_TIMEOUT: ${IGT_TIMEOUT}" + ;; +esac + +if weston_is_running; then + if ! weston_stop; then + log_error "Failed to stop Weston" + test_result_finish "FAIL" "Failed to stop Weston before test" + fi + weston_stopped_by_test=1 +fi + +log_file="$test_path/${TESTNAME}_log.txt" +log_info "Running $TESTNAME (timeout: ${IGT_TIMEOUT}s)" +run_with_managed_timeout "$IGT_TIMEOUT" "$test_path" "$TESTNAME" "$DMABUF_CMD" > "$log_file" 2>&1 +RC=$? + +log_info "Logs written to: $log_file" + +success_count=$(grep -c "SUCCESS" "$log_file" 2>/dev/null || echo "0") +fail_count=$(grep -c "FAIL" "$log_file" 2>/dev/null || echo "0") +skip_count=$(grep -c "SKIP" "$log_file" 2>/dev/null || echo "0") + +success_count=${success_count:-0} +fail_count=${fail_count:-0} +skip_count=${skip_count:-0} + +case "$success_count" in ''|*[!0-9]*) success_count=0 ;; esac +case "$fail_count" in ''|*[!0-9]*) fail_count=0 ;; esac +case "$skip_count" in ''|*[!0-9]*) skip_count=0 ;; esac + +total_subtests=$((success_count + fail_count + skip_count)) + +# Restore Weston before writing the final result; report FAIL if recovery fails +if [ "$weston_stopped_by_test" -eq 1 ]; then + log_info "Restarting Weston after test completion" + if ! weston_restore_runtime; then + log_fail "$TESTNAME: Weston failed to restart after test" + test_result_finish "FAIL" "Weston failed to restart after test" + fi + weston_stopped_by_test=0 +fi + +log_info "Subtest Results: SUCCESS=$success_count, FAIL=$fail_count, SKIP=$skip_count, TOTAL=$total_subtests" +log_info "results will be written to \"$RES_FILE\"" +log_info "-------------------Completed $TESTNAME Testcase----------------------------" + +if [ "$RC" -eq 143 ] || [ "$RC" -eq 124 ]; then + log_fail "$TESTNAME : Test Failed (timeout after ${IGT_TIMEOUT}s)" + test_result_finish "FAIL" "timeout after ${IGT_TIMEOUT}s" +elif [ "$RC" -eq 77 ]; then + log_skip "$TESTNAME : Test Skipped (IGT exit code 77)" + test_result_finish "SKIP" "IGT exit code 77" +elif [ "$RC" -ne 0 ]; then + log_fail "$TESTNAME : Test Failed (exit code: $RC)" + test_result_finish "FAIL" "exit code: $RC" +elif [ "$fail_count" -gt 0 ]; then + log_fail "$TESTNAME : Test Failed - $fail_count subtest(s) failed out of $total_subtests" + test_result_finish "FAIL" "$fail_count subtest(s) failed out of $total_subtests" +elif [ "$skip_count" -gt 0 ] && [ "$success_count" -eq 0 ]; then + log_skip "$TESTNAME : Test Skipped - All $skip_count subtest(s) were skipped" + test_result_finish "SKIP" "all $skip_count subtest(s) were skipped" +else + if [ "$success_count" -gt 0 ]; then + if [ "$skip_count" -gt 0 ]; then + log_pass "$TESTNAME : Test Passed - $success_count subtest(s) succeeded, $skip_count skipped" + test_result_finish "PASS" "$success_count subtest(s) succeeded, $skip_count skipped" + else + log_pass "$TESTNAME : Test Passed - All $success_count subtest(s) succeeded" + test_result_finish "PASS" "all $success_count subtest(s) succeeded" + fi + else + log_pass "$TESTNAME : Test Passed (return code $RC)" + test_result_finish "PASS" "return code $RC" + fi +fi diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/README.md b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/README.md new file mode 100644 index 000000000..5efbbba3d --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/README.md @@ -0,0 +1,80 @@ +# kms_setmode Test + +## Overview +The kms_setmode test is an IGT (Intel GPU Tools) test that validates mode setting functionality in the KMS (Kernel Mode Setting) display subsystem. This test verifies the kernel's ability to set and switch between different display modes. + +## Test Description +This test validates: +- Display mode setting operations +- Mode switching between different resolutions and refresh rates +- Multi-monitor mode configuration +- Display pipeline configuration +- CRTC (Cathode Ray Tube Controller) and connector management +- Mode validation and compatibility checking + +## Prerequisites +- IGT GPU tools must be installed on the target device +- Display hardware must be available and connected +- Weston compositor will be stopped during test execution + +## Usage + +### Basic Usage (Default) +```bash +./run-test.sh kms_setmode +``` +The test will automatically use the binary at `/usr/libexec/igt-gpu-tools/kms_setmode` + +### With Custom Binary Path +```bash +./run-test.sh kms_setmode --kms-setmode-path /custom/path/to/kms_setmode +``` + +Or: +```bash +./run-test.sh kms_setmode /custom/path/to/kms_setmode +``` + +### Help +```bash +cd Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode +./run.sh --help +``` + +## Test Results +The test generates: +- **Result file**: `kms_setmode.res` - Contains PASS/FAIL/SKIP status +- **Log file**: `kms_setmode_log.txt` - Contains detailed test output + +## Expected Behavior +- **PASS**: All subtests succeed or some subtests succeed with others skipped +- **SKIP**: All subtests are skipped (e.g., when display hardware is not available) +- **FAIL**: One or more subtests fail or the test exits with a non-zero code + +## Common Issues +1. **No Display Connected**: The test requires an active display connection. Ensure a monitor is connected. + +2. **Mode Not Supported**: Some display modes may not be supported by the hardware or monitor. This will result in test skips for those specific modes. + +3. **Display Flicker**: During mode switching tests, you may observe brief display flicker or blanking. This is expected behavior. + +4. **Binary Not Found**: Ensure IGT GPU tools are installed: + ```bash + # Check if binary exists + ls -l /usr/libexec/igt-gpu-tools/kms_setmode + ``` + +## Test Coverage +The test typically covers: +- Single display mode setting +- Multiple display configurations +- Mode switching sequences +- Invalid mode rejection +- Display pipeline state validation + +## Notes +- The test automatically stops Weston before execution +- Mode setting tests may cause brief display disruptions +- Test output is parsed for SUCCESS, FAIL, and SKIP counts +- The test validates both successful mode sets and proper error handling for invalid modes +- Results may vary based on display hardware capabilities and connected monitors diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/kms_setmode.yaml b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/kms_setmode.yaml new file mode 100644 index 000000000..ad8cbfff9 --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/kms_setmode.yaml @@ -0,0 +1,20 @@ +metadata: + name: kms-setmode + format: "Lava-Test Test Definition 1.0" + description: "Validates KMS mode-setting across all connected DRM connectors using the IGT kms_setmode test suite. Stops any active Weston compositor before running and restores it afterwards." + os: + - linux + scope: + - functional + +params: + KMS_SETMODE_PATH: "/usr/libexec/igt-gpu-tools/kms_setmode" + IGT_TIMEOUT: "300" + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode + - export IGT_TIMEOUT="${IGT_TIMEOUT}" + - ./run.sh --kms-setmode-path "${KMS_SETMODE_PATH}" || true + - $REPO_PATH/Runner/utils/send-to-lava.sh kms_setmode.res || true diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/run.sh b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/run.sh new file mode 100755 index 000000000..89c839688 --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_setmode/run.sh @@ -0,0 +1,176 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# ---- Source init_env & tools ---- +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then INIT_ENV="$SEARCH/init_env"; break; fi + SEARCH="$(dirname "$SEARCH")" +done +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 1 +fi + +# Only source if not already loaded (idempotent) +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" +fi +# Always source functestlib.sh, using $TOOLS exported by init_env +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" +# Source display helpers: Weston/Wayland lifecycle, DRM utilities, weston_restore_runtime +. "$TOOLS/lib_display.sh" + +# EXIT trap: safety-net cleanup when the script exits normally (PIDs already cleared). +# Signal traps: kill the IGT child, restore Weston, then record an interrupted FAIL. +weston_stopped_by_test=0 +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after test completion"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi' EXIT +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after signal interruption"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi; test_result_finish "FAIL" "test interrupted by signal"' INT TERM HUP + +TESTNAME="kms_setmode" +RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" +test_result_init "$TESTNAME" "$RES_FILE" +# Default IGT test binary location +DEFAULT_IGT_PATH="/usr/libexec/igt-gpu-tools" +KMS_SETMODE_CMD="$DEFAULT_IGT_PATH/$TESTNAME" +# Configurable timeout in seconds for the IGT invocation +IGT_TIMEOUT="${IGT_TIMEOUT:-300}" + +test_path="$(find_test_case_by_name "$TESTNAME" 2>/dev/null)" +if [ -z "$test_path" ] || [ ! -d "$test_path" ]; then + test_path="$SCRIPT_DIR" +fi + +if [ ! -w "$test_path" ]; then + log_error "Cannot write to test directory: $test_path" + test_result_finish "FAIL" "Cannot write to test directory: $test_path" +fi + +while [ $# -gt 0 ]; do + case "$1" in + --kms-setmode-path) + shift + if [ -n "${1:-}" ]; then + KMS_SETMODE_CMD="$1" + else + log_error "Missing value for --kms-setmode-path parameter" + test_result_finish "FAIL" "Missing value for --kms-setmode-path parameter" + fi + ;; + --help|-h) + log_info "Usage: $0 [--kms-setmode-path BINARY_PATH] | [BINARY_PATH]" + log_info "Default binary path: $DEFAULT_IGT_PATH/$TESTNAME" + exit 0 + ;; + -*) + log_warn "Unknown argument: $1" + ;; + *) + KMS_SETMODE_CMD="$1" + ;; + esac + shift +done + +if ! cd "$test_path"; then + log_error "cd failed: $test_path" + test_result_finish "FAIL" "cd failed: $test_path" +fi + +log_info "-------------------Starting $TESTNAME Testcase-----------------------------" + +# Check if the binary exists and is executable +if [ ! -x "$KMS_SETMODE_CMD" ]; then + log_skip "$TESTNAME: kms_setmode binary not found or not executable at: $KMS_SETMODE_CMD" + log_skip "Please ensure IGT GPU tools are installed or specify the binary path with --kms-setmode-path" + test_result_finish "SKIP" "kms_setmode binary not found or not executable" +fi + +log_info "Using kms_setmode binary at: $KMS_SETMODE_CMD" + +# Validate IGT_TIMEOUT is a positive integer before stopping Weston +case "$IGT_TIMEOUT" in + ''|*[!0-9]*|0) + log_error "IGT_TIMEOUT must be a positive integer, got: '${IGT_TIMEOUT}'" + test_result_finish "FAIL" "invalid IGT_TIMEOUT: ${IGT_TIMEOUT}" + ;; +esac + +if weston_is_running; then + if ! weston_stop; then + log_error "Failed to stop Weston" + test_result_finish "FAIL" "Failed to stop Weston before test" + fi + weston_stopped_by_test=1 +fi + +log_file="$test_path/${TESTNAME}_log.txt" +log_info "Running $TESTNAME (timeout: ${IGT_TIMEOUT}s)" +run_with_managed_timeout "$IGT_TIMEOUT" "$test_path" "$TESTNAME" "$KMS_SETMODE_CMD" > "$log_file" 2>&1 +RC=$? + +log_info "Logs written to: $log_file" + +success_count=$(grep -c "SUCCESS" "$log_file" 2>/dev/null || echo "0") +fail_count=$(grep -c "FAIL" "$log_file" 2>/dev/null || echo "0") +skip_count=$(grep -c "SKIP" "$log_file" 2>/dev/null || echo "0") + +success_count=${success_count:-0} +fail_count=${fail_count:-0} +skip_count=${skip_count:-0} + +case "$success_count" in ''|*[!0-9]*) success_count=0 ;; esac +case "$fail_count" in ''|*[!0-9]*) fail_count=0 ;; esac +case "$skip_count" in ''|*[!0-9]*) skip_count=0 ;; esac + +total_subtests=$((success_count + fail_count + skip_count)) + +# Restore Weston before writing the final result; report FAIL if recovery fails +if [ "$weston_stopped_by_test" -eq 1 ]; then + log_info "Restarting Weston after test completion" + if ! weston_restore_runtime; then + log_fail "$TESTNAME: Weston failed to restart after test" + test_result_finish "FAIL" "Weston failed to restart after test" + fi + weston_stopped_by_test=0 +fi + +log_info "Subtest Results: SUCCESS=$success_count, FAIL=$fail_count, SKIP=$skip_count, TOTAL=$total_subtests" +log_info "results will be written to \"$RES_FILE\"" +log_info "-------------------Completed $TESTNAME Testcase----------------------------" + +if [ "$RC" -eq 143 ] || [ "$RC" -eq 124 ]; then + log_fail "$TESTNAME : Test Failed (timeout after ${IGT_TIMEOUT}s)" + test_result_finish "FAIL" "timeout after ${IGT_TIMEOUT}s" +elif [ "$RC" -eq 77 ]; then + log_skip "$TESTNAME : Test Skipped (IGT exit code 77)" + test_result_finish "SKIP" "IGT exit code 77" +elif [ "$RC" -ne 0 ]; then + log_fail "$TESTNAME : Test Failed (exit code: $RC)" + test_result_finish "FAIL" "exit code: $RC" +elif [ "$fail_count" -gt 0 ]; then + log_fail "$TESTNAME : Test Failed - $fail_count subtest(s) failed out of $total_subtests" + test_result_finish "FAIL" "$fail_count subtest(s) failed out of $total_subtests" +elif [ "$skip_count" -gt 0 ] && [ "$success_count" -eq 0 ]; then + log_skip "$TESTNAME : Test Skipped - All $skip_count subtest(s) were skipped" + test_result_finish "SKIP" "all $skip_count subtest(s) were skipped" +else + if [ "$success_count" -gt 0 ]; then + if [ "$skip_count" -gt 0 ]; then + log_pass "$TESTNAME : Test Passed - $success_count subtest(s) succeeded, $skip_count skipped" + test_result_finish "PASS" "$success_count subtest(s) succeeded, $skip_count skipped" + else + log_pass "$TESTNAME : Test Passed - All $success_count subtest(s) succeeded" + test_result_finish "PASS" "all $success_count subtest(s) succeeded" + fi + else + log_pass "$TESTNAME : Test Passed (return code $RC)" + test_result_finish "PASS" "return code $RC" + fi +fi diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/README.md b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/README.md new file mode 100644 index 000000000..02ee0ad69 --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/README.md @@ -0,0 +1,75 @@ +# kms_sysfs_edid_timing Test + +## Overview +The kms_sysfs_edid_timing test is an IGT (Intel GPU Tools) test that validates EDID (Extended Display Identification Data) timing information exposed through the sysfs interface. This test verifies the kernel's ability to correctly parse and expose display timing information. + +## Test Description +This test validates: +- EDID data parsing and exposure via sysfs +- Display timing information accuracy +- Sysfs interface for EDID access +- Display mode information retrieval +- Monitor capability detection + +## Prerequisites +- IGT GPU tools must be installed on the target device +- Display hardware must be available and connected +- A monitor with valid EDID data must be connected +- Weston compositor will be stopped during test execution + +## Usage + +### Basic Usage (Default) +```bash +./run-test.sh kms_sysfs_edid_timing +``` +The test will automatically use the binary at `/usr/libexec/igt-gpu-tools/kms_sysfs_edid_timing` + +### With Custom Binary Path +```bash +./run-test.sh kms_sysfs_edid_timing --kms-sysfs-edid-timing-path /custom/path/to/kms_sysfs_edid_timing +``` + +Or: +```bash +./run-test.sh kms_sysfs_edid_timing /custom/path/to/kms_sysfs_edid_timing +``` + +### Help +```bash +cd Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing +./run.sh --help +``` + +## Test Results +The test generates: +- **Result file**: `kms_sysfs_edid_timing.res` - Contains PASS/FAIL/SKIP status +- **Log file**: `kms_sysfs_edid_timing_log.txt` - Contains detailed test output + +## Expected Behavior +- **PASS**: All subtests succeed or some subtests succeed with others skipped +- **SKIP**: All subtests are skipped (e.g., when no display is connected or EDID is not available) +- **FAIL**: One or more subtests fail or the test exits with a non-zero code + +## Common Issues +1. **No Display Connected**: The test requires a monitor with valid EDID data. Ensure a display is properly connected. + +2. **EDID Not Available**: Some displays may not provide EDID data or the data may be corrupted. This will result in test skips. + +3. **Sysfs Access**: Ensure the sysfs interface is accessible and properly mounted: + ```bash + # Check sysfs DRM entries + ls -l /sys/class/drm/ + ``` + +4. **Binary Not Found**: Ensure IGT GPU tools are installed: + ```bash + # Check if binary exists + ls -l /usr/libexec/igt-gpu-tools/kms_sysfs_edid_timing + ``` + +## Notes +- The test automatically stops Weston before execution +- EDID data is display-specific and test results may vary based on the connected monitor +- Test output is parsed for SUCCESS, FAIL, and SKIP counts +- This test is non-destructive and only reads EDID information diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/kms_sysfs_edid_timing.yaml b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/kms_sysfs_edid_timing.yaml new file mode 100644 index 000000000..ad641c9bf --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/kms_sysfs_edid_timing.yaml @@ -0,0 +1,20 @@ +metadata: + name: kms-sysfs-edid-timing + format: "Lava-Test Test Definition 1.0" + description: "Validates EDID timing information exposed through the DRM sysfs interface using the IGT kms_sysfs_edid_timing test suite. Stops any active Weston compositor before running and restores it afterwards." + os: + - linux + scope: + - functional + +params: + KMS_SYSFS_EDID_TIMING_PATH: "/usr/libexec/igt-gpu-tools/kms_sysfs_edid_timing" + IGT_TIMEOUT: "300" + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing + - export IGT_TIMEOUT="${IGT_TIMEOUT}" + - ./run.sh --kms-sysfs-edid-timing-path "${KMS_SYSFS_EDID_TIMING_PATH}" || true + - $REPO_PATH/Runner/utils/send-to-lava.sh kms_sysfs_edid_timing.res || true diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/run.sh b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/run.sh new file mode 100755 index 000000000..5182e92c4 --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_sysfs_edid_timing/run.sh @@ -0,0 +1,176 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# ---- Source init_env & tools ---- +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then INIT_ENV="$SEARCH/init_env"; break; fi + SEARCH="$(dirname "$SEARCH")" +done +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 1 +fi + +# Only source if not already loaded (idempotent) +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" +fi +# Always source functestlib.sh, using $TOOLS exported by init_env +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" +# Source display helpers: Weston/Wayland lifecycle, DRM utilities, weston_restore_runtime +. "$TOOLS/lib_display.sh" + +# EXIT trap: safety-net cleanup when the script exits normally (PIDs already cleared). +# Signal traps: kill the IGT child, restore Weston, then record an interrupted FAIL. +weston_stopped_by_test=0 +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after test completion"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi' EXIT +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after signal interruption"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi; test_result_finish "FAIL" "test interrupted by signal"' INT TERM HUP + +TESTNAME="kms_sysfs_edid_timing" +RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" +test_result_init "$TESTNAME" "$RES_FILE" +# Default IGT test binary location +DEFAULT_IGT_PATH="/usr/libexec/igt-gpu-tools" +KMS_SYSFS_EDID_TIMING_CMD="$DEFAULT_IGT_PATH/$TESTNAME" +# Configurable timeout in seconds for the IGT invocation +IGT_TIMEOUT="${IGT_TIMEOUT:-300}" + +test_path="$(find_test_case_by_name "$TESTNAME" 2>/dev/null)" +if [ -z "$test_path" ] || [ ! -d "$test_path" ]; then + test_path="$SCRIPT_DIR" +fi + +if [ ! -w "$test_path" ]; then + log_error "Cannot write to test directory: $test_path" + test_result_finish "FAIL" "Cannot write to test directory: $test_path" +fi + +while [ $# -gt 0 ]; do + case "$1" in + --kms-sysfs-edid-timing-path) + shift + if [ -n "${1:-}" ]; then + KMS_SYSFS_EDID_TIMING_CMD="$1" + else + log_error "Missing value for --kms-sysfs-edid-timing-path parameter" + test_result_finish "FAIL" "Missing value for --kms-sysfs-edid-timing-path parameter" + fi + ;; + --help|-h) + log_info "Usage: $0 [--kms-sysfs-edid-timing-path BINARY_PATH] | [BINARY_PATH]" + log_info "Default binary path: $DEFAULT_IGT_PATH/$TESTNAME" + exit 0 + ;; + -*) + log_warn "Unknown argument: $1" + ;; + *) + KMS_SYSFS_EDID_TIMING_CMD="$1" + ;; + esac + shift +done + +if ! cd "$test_path"; then + log_error "cd failed: $test_path" + test_result_finish "FAIL" "cd failed: $test_path" +fi + +log_info "-------------------Starting $TESTNAME Testcase-----------------------------" + +# Check if the binary exists and is executable +if [ ! -x "$KMS_SYSFS_EDID_TIMING_CMD" ]; then + log_skip "$TESTNAME: kms_sysfs_edid_timing binary not found or not executable at: $KMS_SYSFS_EDID_TIMING_CMD" + log_skip "Please ensure IGT GPU tools are installed or specify the binary path with --kms-sysfs-edid-timing-path" + test_result_finish "SKIP" "kms_sysfs_edid_timing binary not found or not executable" +fi + +log_info "Using kms_sysfs_edid_timing binary at: $KMS_SYSFS_EDID_TIMING_CMD" + +# Validate IGT_TIMEOUT is a positive integer before stopping Weston +case "$IGT_TIMEOUT" in + ''|*[!0-9]*|0) + log_error "IGT_TIMEOUT must be a positive integer, got: '${IGT_TIMEOUT}'" + test_result_finish "FAIL" "invalid IGT_TIMEOUT: ${IGT_TIMEOUT}" + ;; +esac + +if weston_is_running; then + if ! weston_stop; then + log_error "Failed to stop Weston" + test_result_finish "FAIL" "Failed to stop Weston before test" + fi + weston_stopped_by_test=1 +fi + +log_file="$test_path/${TESTNAME}_log.txt" +log_info "Running $TESTNAME (timeout: ${IGT_TIMEOUT}s)" +run_with_managed_timeout "$IGT_TIMEOUT" "$test_path" "$TESTNAME" "$KMS_SYSFS_EDID_TIMING_CMD" > "$log_file" 2>&1 +RC=$? + +log_info "Logs written to: $log_file" + +success_count=$(grep -c "SUCCESS" "$log_file" 2>/dev/null || echo "0") +fail_count=$(grep -c "FAIL" "$log_file" 2>/dev/null || echo "0") +skip_count=$(grep -c "SKIP" "$log_file" 2>/dev/null || echo "0") + +success_count=${success_count:-0} +fail_count=${fail_count:-0} +skip_count=${skip_count:-0} + +case "$success_count" in ''|*[!0-9]*) success_count=0 ;; esac +case "$fail_count" in ''|*[!0-9]*) fail_count=0 ;; esac +case "$skip_count" in ''|*[!0-9]*) skip_count=0 ;; esac + +total_subtests=$((success_count + fail_count + skip_count)) + +# Restore Weston before writing the final result; report FAIL if recovery fails +if [ "$weston_stopped_by_test" -eq 1 ]; then + log_info "Restarting Weston after test completion" + if ! weston_restore_runtime; then + log_fail "$TESTNAME: Weston failed to restart after test" + test_result_finish "FAIL" "Weston failed to restart after test" + fi + weston_stopped_by_test=0 +fi + +log_info "Subtest Results: SUCCESS=$success_count, FAIL=$fail_count, SKIP=$skip_count, TOTAL=$total_subtests" +log_info "results will be written to \"$RES_FILE\"" +log_info "-------------------Completed $TESTNAME Testcase----------------------------" + +if [ "$RC" -eq 143 ] || [ "$RC" -eq 124 ]; then + log_fail "$TESTNAME : Test Failed (timeout after ${IGT_TIMEOUT}s)" + test_result_finish "FAIL" "timeout after ${IGT_TIMEOUT}s" +elif [ "$RC" -eq 77 ]; then + log_skip "$TESTNAME : Test Skipped (IGT exit code 77)" + test_result_finish "SKIP" "IGT exit code 77" +elif [ "$RC" -ne 0 ]; then + log_fail "$TESTNAME : Test Failed (exit code: $RC)" + test_result_finish "FAIL" "exit code: $RC" +elif [ "$fail_count" -gt 0 ]; then + log_fail "$TESTNAME : Test Failed - $fail_count subtest(s) failed out of $total_subtests" + test_result_finish "FAIL" "$fail_count subtest(s) failed out of $total_subtests" +elif [ "$skip_count" -gt 0 ] && [ "$success_count" -eq 0 ]; then + log_skip "$TESTNAME : Test Skipped - All $skip_count subtest(s) were skipped" + test_result_finish "SKIP" "all $skip_count subtest(s) were skipped" +else + if [ "$success_count" -gt 0 ]; then + if [ "$skip_count" -gt 0 ]; then + log_pass "$TESTNAME : Test Passed - $success_count subtest(s) succeeded, $skip_count skipped" + test_result_finish "PASS" "$success_count subtest(s) succeeded, $skip_count skipped" + else + log_pass "$TESTNAME : Test Passed - All $success_count subtest(s) succeeded" + test_result_finish "PASS" "all $success_count subtest(s) succeeded" + fi + else + log_pass "$TESTNAME : Test Passed (return code $RC)" + test_result_finish "PASS" "return code $RC" + fi +fi diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/README.md b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/README.md new file mode 100644 index 000000000..9cc5c4439 --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/README.md @@ -0,0 +1,79 @@ +# kms_vblank Test + +## Overview +The kms_vblank test is an IGT (Intel GPU Tools) test that validates vertical blanking (VBLANK) functionality in the KMS (Kernel Mode Setting) display subsystem. This test verifies the kernel's ability to handle VBLANK events and timing. + +## Test Description +This test validates: +- VBLANK event generation and handling +- VBLANK timing accuracy +- VBLANK synchronization across multiple pipes +- VBLANK wait operations +- Display refresh timing + +## Prerequisites +- IGT GPU tools must be installed on the target device +- Display hardware must be available and connected +- Weston compositor will be stopped during test execution + +## Usage + +### Basic Usage (Default) +```bash +./run-test.sh kms_vblank +``` +The test will automatically use the binary at `/usr/libexec/igt-gpu-tools/kms_vblank` with default subtest filtering. + +**Default Arguments**: `--run-subtest '*,!*suspend*,!*rpm*'` +- Runs all subtests except those related to suspend and runtime power management +- These subtests are excluded to prevent hanging or system instability + +### With Custom Binary Path +```bash +./run-test.sh kms_vblank --kms-vblank-path /custom/path/to/kms_vblank +``` + +### With Custom Subtest Filter +```bash +./run-test.sh kms_vblank --run-subtest 'pipe-A-*' +``` + +### Help +```bash +cd Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank +./run.sh --help +``` + +## Test Results +The test generates: +- **Result file**: `kms_vblank.res` - Contains PASS/FAIL/SKIP status +- **Log file**: `kms_vblank_log.txt` - Contains detailed test output + +## Expected Behavior +- **PASS**: All subtests succeed or some subtests succeed with others skipped +- **SKIP**: All subtests are skipped (e.g., when display hardware is not available) +- **FAIL**: One or more subtests fail or the test exits with a non-zero code + +## Subtest Filtering +The default subtest filter excludes: +- `*suspend*` - Suspend-related tests that may hang the system +- `*rpm*` - Runtime power management tests that may cause issues + +This filtering ensures the test runs reliably without hanging. You can override this with the `--run-subtest` parameter if needed. + +## Common Issues +1. **Test Hangs**: If the test hangs, ensure you're using the default subtest filter which excludes problematic tests. + +2. **No Display Connected**: The test requires an active display connection. Ensure a monitor is connected. + +3. **Binary Not Found**: Ensure IGT GPU tools are installed: + ```bash + # Check if binary exists + ls -l /usr/libexec/igt-gpu-tools/kms_vblank + ``` + +## Notes +- The test automatically stops Weston before execution +- VBLANK tests are timing-sensitive and may show variations based on display refresh rate +- Test output is parsed for SUCCESS, FAIL, and SKIP counts +- The default subtest filter is recommended for automated testing diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/kms_vblank.yaml b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/kms_vblank.yaml new file mode 100644 index 000000000..7f79b01ea --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/kms_vblank.yaml @@ -0,0 +1,21 @@ +metadata: + name: kms-vblank + format: "Lava-Test Test Definition 1.0" + description: "Validates DRM vblank event delivery and timing using the IGT kms_vblank test suite. Suspend and RPM subtests are excluded by default. Stops any active Weston compositor before running and restores it afterwards." + os: + - linux + scope: + - functional + +params: + KMS_VBLANK_PATH: "/usr/libexec/igt-gpu-tools/kms_vblank" + RUN_SUBTEST: "*,!*suspend*,!*rpm*" + IGT_TIMEOUT: "300" + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank + - export IGT_TIMEOUT="${IGT_TIMEOUT}" + - ./run.sh --kms-vblank-path "${KMS_VBLANK_PATH}" --run-subtest "${RUN_SUBTEST}" || true + - $REPO_PATH/Runner/utils/send-to-lava.sh kms_vblank.res || true diff --git a/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/run.sh b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/run.sh new file mode 100755 index 000000000..c6e12c44e --- /dev/null +++ b/Runner/suites/Multimedia/Display/igt-gpu-tools/kms_vblank/run.sh @@ -0,0 +1,189 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# ---- Source init_env & tools ---- +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then INIT_ENV="$SEARCH/init_env"; break; fi + SEARCH="$(dirname "$SEARCH")" +done +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 1 +fi + +# Only source if not already loaded (idempotent) +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" +fi +# Always source functestlib.sh, using $TOOLS exported by init_env +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" +# Source display helpers: Weston/Wayland lifecycle, DRM utilities, weston_restore_runtime +. "$TOOLS/lib_display.sh" + +# EXIT trap: safety-net cleanup when the script exits normally (PIDs already cleared). +# Signal traps: kill the IGT child, restore Weston, then record an interrupted FAIL. +weston_stopped_by_test=0 +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after test completion"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi' EXIT +trap 'if [ "$weston_stopped_by_test" -eq 1 ]; then if managed_timeout_cancel_bounded 5; then log_info "Restarting Weston after signal interruption"; weston_restore_runtime || true; else log_warn "IGT child may still hold DRM ownership; skipping Weston restore to avoid conflict"; fi; weston_stopped_by_test=0; else managed_timeout_cancel_bounded 5 || true; fi; test_result_finish "FAIL" "test interrupted by signal"' INT TERM HUP + +TESTNAME="kms_vblank" +RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" +test_result_init "$TESTNAME" "$RES_FILE" +# Default IGT test binary location +DEFAULT_IGT_PATH="/usr/libexec/igt-gpu-tools" +KMS_VBLANK_CMD="$DEFAULT_IGT_PATH/$TESTNAME" +# Default pattern to exclude problematic subtests +DEFAULT_PATTERN="*,!*suspend*,!*rpm*" +RUN_SUBTEST="$DEFAULT_PATTERN" +# Configurable timeout in seconds for the IGT invocation +IGT_TIMEOUT="${IGT_TIMEOUT:-300}" + +test_path="$(find_test_case_by_name "$TESTNAME" 2>/dev/null)" +if [ -z "$test_path" ] || [ ! -d "$test_path" ]; then + test_path="$SCRIPT_DIR" +fi + +if [ ! -w "$test_path" ]; then + log_error "Cannot write to test directory: $test_path" + test_result_finish "FAIL" "Cannot write to test directory: $test_path" +fi + +while [ $# -gt 0 ]; do + case "$1" in + --kms-vblank-path) + shift + if [ -n "${1:-}" ]; then + KMS_VBLANK_CMD="$1" + else + log_error "Missing value for --kms-vblank-path parameter" + test_result_finish "FAIL" "Missing value for --kms-vblank-path parameter" + fi + ;; + --run-subtest) + shift + if [ -n "${1:-}" ]; then + RUN_SUBTEST="$1" + else + log_error "Missing value for --run-subtest parameter" + test_result_finish "FAIL" "Missing value for --run-subtest parameter" + fi + ;; + --help|-h) + log_info "Usage: $0 [--kms-vblank-path BINARY_PATH] [--run-subtest PATTERN]" + log_info "Default binary path: $DEFAULT_IGT_PATH/$TESTNAME" + log_info "Default subtest filter: $DEFAULT_PATTERN" + exit 0 + ;; + -*) + log_warn "Unknown argument: $1" + ;; + *) + KMS_VBLANK_CMD="$1" + ;; + esac + shift +done + +if ! cd "$test_path"; then + log_error "cd failed: $test_path" + test_result_finish "FAIL" "cd failed: $test_path" +fi + +log_info "-------------------Starting $TESTNAME Testcase-----------------------------" + +# Check if the binary exists and is executable +if [ ! -x "$KMS_VBLANK_CMD" ]; then + log_skip "$TESTNAME: kms_vblank binary not found or not executable at: $KMS_VBLANK_CMD" + log_skip "Please ensure IGT GPU tools are installed or specify the binary path with --kms-vblank-path" + test_result_finish "SKIP" "kms_vblank binary not found or not executable" +fi + +log_info "Using kms_vblank binary at: $KMS_VBLANK_CMD" + +# Validate IGT_TIMEOUT is a positive integer before stopping Weston +case "$IGT_TIMEOUT" in + ''|*[!0-9]*|0) + log_error "IGT_TIMEOUT must be a positive integer, got: '${IGT_TIMEOUT}'" + test_result_finish "FAIL" "invalid IGT_TIMEOUT: ${IGT_TIMEOUT}" + ;; +esac + +if weston_is_running; then + if ! weston_stop; then + log_error "Failed to stop Weston" + test_result_finish "FAIL" "Failed to stop Weston before test" + fi + weston_stopped_by_test=1 +fi + +log_file="$test_path/${TESTNAME}_log.txt" +log_info "Running with subtest pattern: $RUN_SUBTEST (timeout: ${IGT_TIMEOUT}s)" +run_with_managed_timeout "$IGT_TIMEOUT" "$test_path" "$TESTNAME" "$KMS_VBLANK_CMD" --run-subtest "$RUN_SUBTEST" > "$log_file" 2>&1 +RC=$? + +log_info "Logs written to: $log_file" + +success_count=$(grep -c "SUCCESS" "$log_file" 2>/dev/null || echo "0") +fail_count=$(grep -c "FAIL" "$log_file" 2>/dev/null || echo "0") +skip_count=$(grep -c "SKIP" "$log_file" 2>/dev/null || echo "0") + +success_count=${success_count:-0} +fail_count=${fail_count:-0} +skip_count=${skip_count:-0} + +case "$success_count" in ''|*[!0-9]*) success_count=0 ;; esac +case "$fail_count" in ''|*[!0-9]*) fail_count=0 ;; esac +case "$skip_count" in ''|*[!0-9]*) skip_count=0 ;; esac + +total_subtests=$((success_count + fail_count + skip_count)) + +# Restore Weston before writing the final result; report FAIL if recovery fails +if [ "$weston_stopped_by_test" -eq 1 ]; then + log_info "Restarting Weston after test completion" + if ! weston_restore_runtime; then + log_fail "$TESTNAME: Weston failed to restart after test" + test_result_finish "FAIL" "Weston failed to restart after test" + fi + weston_stopped_by_test=0 +fi + +log_info "Subtest Results: SUCCESS=$success_count, FAIL=$fail_count, SKIP=$skip_count, TOTAL=$total_subtests" +log_info "results will be written to \"$RES_FILE\"" +log_info "-------------------Completed $TESTNAME Testcase----------------------------" + +if [ "$RC" -eq 143 ] || [ "$RC" -eq 124 ]; then + log_fail "$TESTNAME : Test Failed (timeout after ${IGT_TIMEOUT}s)" + test_result_finish "FAIL" "timeout after ${IGT_TIMEOUT}s" +elif [ "$RC" -eq 77 ]; then + log_skip "$TESTNAME : Test Skipped (IGT exit code 77)" + test_result_finish "SKIP" "IGT exit code 77" +elif [ "$RC" -ne 0 ]; then + log_fail "$TESTNAME : Test Failed (exit code: $RC)" + test_result_finish "FAIL" "exit code: $RC" +elif [ "$fail_count" -gt 0 ]; then + log_fail "$TESTNAME : Test Failed - $fail_count subtest(s) failed out of $total_subtests" + test_result_finish "FAIL" "$fail_count subtest(s) failed out of $total_subtests" +elif [ "$skip_count" -gt 0 ] && [ "$success_count" -eq 0 ]; then + log_skip "$TESTNAME : Test Skipped - All $skip_count subtest(s) were skipped" + test_result_finish "SKIP" "all $skip_count subtest(s) were skipped" +else + if [ "$success_count" -gt 0 ]; then + if [ "$skip_count" -gt 0 ]; then + log_pass "$TESTNAME : Test Passed - $success_count subtest(s) succeeded, $skip_count skipped" + test_result_finish "PASS" "$success_count subtest(s) succeeded, $skip_count skipped" + else + log_pass "$TESTNAME : Test Passed - All $success_count subtest(s) succeeded" + test_result_finish "PASS" "all $success_count subtest(s) succeeded" + fi + else + log_pass "$TESTNAME : Test Passed (return code $RC)" + test_result_finish "PASS" "return code $RC" + fi +fi diff --git a/Runner/utils/functestlib.sh b/Runner/utils/functestlib.sh index 5050b5924..6d9470784 100755 --- a/Runner/utils/functestlib.sh +++ b/Runner/utils/functestlib.sh @@ -3091,6 +3091,109 @@ run_with_managed_timeout() { return "$mt_status" } +# managed_timeout_cancel_bounded [grace_secs] +# +# Bounded TERM→KILL cancellation for a run_with_managed_timeout child. +# Safe to call from a signal trap even when the watcher has already been +# killed by a process-group signal. +# +# Improvements over a plain kill+wait: +# - grace_secs is validated as a positive integer (default: 5) +# - The watcher's sleep subprocess is stopped first via MANAGED_TIMEOUT_* +# state so it cannot race and send SIGKILL after we have already handled +# the command +# - Both the watcher and the command use bounded poll loops after SIGTERM +# and after SIGKILL, because even SIGKILL can be delayed for tasks +# blocked in kernel I/O +# - All PID and file state is cleared after cleanup so repeated trap +# invocations cannot act on stale values +# +# Arguments: +# grace_secs positive integer seconds to wait after SIGTERM before +# escalating to SIGKILL (default: 5) +managed_timeout_cancel_bounded() { + mtcb_grace="${1:-5}" + case "$mtcb_grace" in + ''|*[!0-9]*|0) mtcb_grace=5 ;; + esac + + mtcb_cmd_pid="${MANAGED_TIMEOUT_CMD_PID:-}" + mtcb_watcher_pid="${MANAGED_TIMEOUT_WATCHER_PID:-}" + mtcb_sleep_pid="${MANAGED_TIMEOUT_WATCHER_SLEEP_PID:-}" + mtcb_sleep_pid_file="${MANAGED_TIMEOUT_SLEEP_PID_FILE:-}" + mtcb_marker_file="${MANAGED_TIMEOUT_MARKER_FILE:-}" + # Tracks whether any child survived past the SIGKILL deadline. + # Callers check this to decide whether DRM ownership is safely released. + mtcb_still_alive=0 + + # Stop the watcher's sleep subprocess first so it cannot race and send + # SIGKILL to the command after we have already handled it. + if [ -z "$mtcb_sleep_pid" ] && [ -n "$mtcb_sleep_pid_file" ] && [ -r "$mtcb_sleep_pid_file" ]; then + mtcb_sleep_pid="$(cat "$mtcb_sleep_pid_file" 2>/dev/null || true)" + fi + if [ -n "$mtcb_sleep_pid" ]; then + kill "$mtcb_sleep_pid" 2>/dev/null || true + fi + + # Kill the watcher with a bounded wait. + if [ -n "$mtcb_watcher_pid" ]; then + kill "$mtcb_watcher_pid" 2>/dev/null || true + mtcb_i=0 + while [ "$mtcb_i" -lt "$mtcb_grace" ] && kill -0 "$mtcb_watcher_pid" 2>/dev/null; do + sleep 1; mtcb_i=$((mtcb_i + 1)) + done + kill -KILL "$mtcb_watcher_pid" 2>/dev/null || true + mtcb_i=0 + while [ "$mtcb_i" -lt 3 ] && kill -0 "$mtcb_watcher_pid" 2>/dev/null; do + sleep 1; mtcb_i=$((mtcb_i + 1)) + done + # Only reap if the process has already exited; an unconditional wait + # can block indefinitely when the child is stuck in kernel I/O. + if ! kill -0 "$mtcb_watcher_pid" 2>/dev/null; then + wait "$mtcb_watcher_pid" 2>/dev/null || true + else + mtcb_still_alive=1 + fi + fi + + # Kill the command with a bounded wait after both SIGTERM and SIGKILL. + if [ -n "$mtcb_cmd_pid" ]; then + kill "$mtcb_cmd_pid" 2>/dev/null || true + mtcb_i=0 + while [ "$mtcb_i" -lt "$mtcb_grace" ] && kill -0 "$mtcb_cmd_pid" 2>/dev/null; do + sleep 1; mtcb_i=$((mtcb_i + 1)) + done + kill -KILL "$mtcb_cmd_pid" 2>/dev/null || true + # Bound the wait after SIGKILL: tasks in kernel I/O can still delay exit. + mtcb_i=0 + while [ "$mtcb_i" -lt 3 ] && kill -0 "$mtcb_cmd_pid" 2>/dev/null; do + sleep 1; mtcb_i=$((mtcb_i + 1)) + done + # Only reap if the process has already exited; an unconditional wait + # can block indefinitely when the child is stuck in kernel I/O. + if kill -0 "$mtcb_cmd_pid" 2>/dev/null; then + mtcb_status=1 + else + wait "$mtcb_cmd_pid" 2>/dev/null || true + fi + fi + + # Remove temp files left by the watcher. + if [ -n "$mtcb_sleep_pid_file" ]; then + rm -f "$mtcb_sleep_pid_file" 2>/dev/null || true + fi + if [ -n "$mtcb_marker_file" ]; then + rm -f "$mtcb_marker_file" 2>/dev/null || true + fi + + # Clear all state so repeated trap invocations cannot act on stale PIDs. + MANAGED_TIMEOUT_CMD_PID="" + MANAGED_TIMEOUT_WATCHER_PID="" + MANAGED_TIMEOUT_WATCHER_SLEEP_PID="" + MANAGED_TIMEOUT_SLEEP_PID_FILE="" + MANAGED_TIMEOUT_MARKER_FILE="" +} + # Purpose: Run a command with a timeout and capture stdout and stderr. # Arguments: # $1 - Timeout in seconds.