diff --git a/Runner/suites/Multimedia/DSP_AudioPD/run.sh b/Runner/suites/Multimedia/DSP_AudioPD/run.sh index 55eafac7..264061dc 100755 --- a/Runner/suites/Multimedia/DSP_AudioPD/run.sh +++ b/Runner/suites/Multimedia/DSP_AudioPD/run.sh @@ -2,6 +2,9 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. # SPDX-License-Identifier: BSD-3-Clause + +TESTNAME="DSP_AudioPD" + # Robustly find and source init_env SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" INIT_ENV="" @@ -14,23 +17,38 @@ while [ "$SEARCH" != "/" ]; do SEARCH=$(dirname "$SEARCH") done +RES_FALLBACK="$SCRIPT_DIR/${TESTNAME}.res" + if [ -z "$INIT_ENV" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 - exit 1 + echo "$TESTNAME SKIP" >"$RES_FALLBACK" 2>/dev/null || true + exit 0 fi # Only source if not already loaded (idempotent) -if [ -z "$__INIT_ENV_LOADED" ]; then +if [ -z "${__INIT_ENV_LOADED:-}" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" + export __INIT_ENV_LOADED=1 fi + # Always source functestlib.sh, using $TOOLS exported by init_env # shellcheck disable=SC1090,SC1091 . "$TOOLS/functestlib.sh" -TESTNAME="DSP_AudioPD" test_path=$(find_test_case_by_name "$TESTNAME") -cd "$test_path" || exit 1 +if [ -z "$test_path" ] || [ ! -d "$test_path" ]; then + log_skip "$TESTNAME SKIP - test path not found" + echo "$TESTNAME SKIP" >"$RES_FALLBACK" 2>/dev/null || true + exit 0 +fi + +if ! cd "$test_path"; then + log_skip "$TESTNAME SKIP - cannot cd into $test_path" + echo "$TESTNAME SKIP" >"$RES_FALLBACK" 2>/dev/null || true + exit 0 +fi + # shellcheck disable=SC2034 res_file="./$TESTNAME.res" @@ -38,47 +56,121 @@ log_info "---------------------------------------------------------------------- log_info "-------------------Starting $TESTNAME Testcase----------------------------" log_info "=== Test Initialization ===" -log_info "Checking if dependency binary is available" -check_dependencies adsprpcd +# Dependencies (single call; log list; SKIP if missing) +deps_list="adsprpcd tr awk grep sleep" +log_info "Checking dependencies: ""$deps_list""" +if ! check_dependencies "$deps_list"; then + log_skip "$TESTNAME SKIP - missing one or more dependencies: $deps_list" + echo "$TESTNAME SKIP" >"$res_file" + exit 0 +fi + +STARTED_BY_TEST=0 +PID="" + +check_adsprpcd_wait_state() { + pid="$1" + pid=$(sanitize_pid "$pid") -if is_process_running "adsprpcd"; then + case "$pid" in + ''|*[!0-9]*) + return 1 + ;; + esac + + # Prefer /proc//wchan (more commonly available) + if [ -r "/proc/$pid/wchan" ]; then + wchan=$(tr -d '\r\n' <"/proc/$pid/wchan" 2>/dev/null) + + # Accept suffixes like ".constprop.0" + case "$wchan" in + do_sys_poll*|ep_poll*|do_epoll_wait*|poll_schedule_timeout*) + log_info "adsprpcd PID $pid wchan='$wchan' (accepted)" + return 0 + ;; + *) + log_info "adsprpcd PID $pid wchan='$wchan' (not in expected set)" + return 1 + ;; + esac + fi + + # Fallback: /proc//stack (may be missing depending on kernel config) + if [ -r "/proc/$pid/stack" ]; then + if grep -qE "(do_sys_poll|ep_poll|do_epoll_wait|poll_schedule_timeout)" "/proc/$pid/stack" 2>/dev/null; then + log_info "adsprpcd PID $pid stack contains expected wait symbol" + return 0 + fi + log_info "adsprpcd PID $pid stack does not contain expected wait symbols" + return 1 + fi + + # Neither interface is available -> SKIP + log_skip "Kernel does not expose /proc/$pid/(wchan|stack); cannot validate adsprpcd wait state" + echo "$TESTNAME SKIP" >"$res_file" + return 2 +} + +if is_process_running "adsprpcd"; then log_info "adsprpcd is running" - PID=$(get_pid "adsprpcd") + PID=$(get_one_pid_by_name "adsprpcd" 2>/dev/null || true) + PID=$(sanitize_pid "$PID") else log_info "adsprpcd is not running" log_info "Manually starting adsprpcd daemon" - adsprpcd & - PID=$! + adsprpcd >/dev/null 2>&1 & + PID=$(sanitize_pid "$!") + STARTED_BY_TEST=1 + + # adsprpcd might daemonize/fork; if $! isn't alive, discover PID by name + if [ -n "$PID" ] && ! wait_pid_alive "$PID" 2; then + PID="" + fi + if [ -z "$PID" ]; then + PID=$(get_one_pid_by_name "adsprpcd" 2>/dev/null || true) + PID=$(sanitize_pid "$PID") + fi fi + log_info "PID is $PID" -sleep 5 -if [ -z "$PID" ]; then - log_info "Failed to start the binary" - exit 1 -else - log_info "Binary is running successfully" -fi +if [ -z "$PID" ] || ! wait_pid_alive "$PID" 10; then + log_fail "Failed to start adsprpcd or PID did not become alive" + echo "$TESTNAME FAIL" >"$res_file" -check_stack_trace() { - pid=$1 - if grep -q "do_sys_poll" < "/proc/$pid/stack" 2>/dev/null; then - return 0 - else - return 1 + # Kill only if we started it and PID is valid + if [ "$STARTED_BY_TEST" -eq 1 ]; then + PID_CLEAN=$(sanitize_pid "$PID") + if [ -n "$PID_CLEAN" ]; then + kill_process "$PID_CLEAN" || true + fi fi -} + exit 0 +fi -# Print overall test result -if check_stack_trace "$PID"; then +# Evaluate +check_adsprpcd_wait_state "$PID" +rc=$? + +if [ "$rc" -eq 0 ]; then log_pass "$TESTNAME : Test Passed" - echo "$TESTNAME PASS" > "$res_file" - kill_process "$PID" - exit 0 + echo "$TESTNAME PASS" >"$res_file" +elif [ "$rc" -eq 2 ]; then + # SKIP already written by the function + : else log_fail "$TESTNAME : Test Failed" - echo "$TESTNAME FAIL" > "$res_file" - kill_process "$PID" - exit 1 + echo "$TESTNAME FAIL" >"$res_file" fi -log_info "-------------------Completed $TESTNAME Testcase----------------------------" \ No newline at end of file + +log_info "-------------------Completed $TESTNAME Testcase----------------------------" + +# Kill only if we started it +if [ "$STARTED_BY_TEST" -eq 1 ]; then + PID_CLEAN=$(sanitize_pid "$PID") + if [ -n "$PID_CLEAN" ]; then + kill_process "$PID_CLEAN" || true + fi +fi + +exit 0 diff --git a/Runner/utils/functestlib.sh b/Runner/utils/functestlib.sh index abc55efe..58eba107 100755 --- a/Runner/utils/functestlib.sh +++ b/Runner/utils/functestlib.sh @@ -4334,42 +4334,110 @@ ensure_network_online() { return 1 } +# Return the first numeric token found in input (helps when tools return multi-PID / noisy output) +sanitize_pid() { + # Return first numeric token from input (single PID) or empty + printf '%s' "$1" \ + | tr -d '\r' \ + | tr -c '0-9 \n' ' ' \ + | awk '{print $1; exit}' +} + +# Get a single PID (first match) for a given process name. +# Prefer pgrep, then get_pid, then a ps fallback. +get_one_pid_by_name() { + name="$1" + [ -z "$name" ] && return 1 + + pid="" + + # Prefer pgrep + if command -v pgrep >/dev/null 2>&1; then + pid=$(pgrep -x "$name" 2>/dev/null | awk 'NR==1{print; exit}') + pid=$(sanitize_pid "$pid") + [ -n "$pid" ] && { printf '%s\n' "$pid"; return 0; } + fi + + # Fallback to get_pid (should already return first PID after your update) + if command -v get_pid >/dev/null 2>&1; then + pid=$(get_pid "$name" 2>/dev/null) + pid=$(sanitize_pid "$pid") + [ -n "$pid" ] && { printf '%s\n' "$pid"; return 0; } + fi + + # Final fallback: ps + pid=$(ps -e 2>/dev/null | awk -v n="$name" '$NF==n {print $1; exit}') + pid=$(sanitize_pid "$pid") + [ -n "$pid" ] && { printf '%s\n' "$pid"; return 0; } + + return 1 +} + +# Wait until PID is alive (kill -0 succeeds) or timeout seconds elapse. +wait_pid_alive() { + pid="$1" + timeout="${2:-10}" + + pid=$(sanitize_pid "$pid") + case "$pid" in + ''|*[!0-9]*) + return 1 + ;; + esac + + i=0 + while [ "$i" -lt "$timeout" ]; do + if kill -0 "$pid" 2>/dev/null; then + return 0 + fi + sleep 1 + i=$((i + 1)) + done + return 1 +} + +# Kill process for the given PID kill_process() { PID="$1" KILL_TERM_GRACE="${KILL_TERM_GRACE:-5}" KILL_KILL_GRACE="${KILL_KILL_GRACE:-5}" SELF_PID="$$" - + + case "$PID" in + ''|*[!0-9]*) + log_warn "Refusing to kill non-numeric PID '$PID'" + return 1 + ;; + esac + # Safety checks if [ "$PID" -eq 1 ] || [ "$PID" -eq "$SELF_PID" ]; then log_warn "Refusing to kill PID $PID (init or self)" return 1 fi - - # Check if process exists + if ! kill -0 "$PID" 2>/dev/null; then log_info "Process $PID not running" return 0 fi - + log_info "Sending SIGTERM to PID $PID" kill -TERM "$PID" 2>/dev/null sleep "$KILL_TERM_GRACE" - + if kill -0 "$PID" 2>/dev/null; then log_info "Sending SIGKILL to PID $PID" kill -KILL "$PID" 2>/dev/null sleep "$KILL_KILL_GRACE" fi - - # Final check + if kill -0 "$PID" 2>/dev/null; then log_warn "Failed to kill process $PID" return 1 - else - log_info "Process $PID terminated successfully" - return 0 fi + + log_info "Process $PID terminated successfully" + return 0 } is_process_running() { @@ -4426,20 +4494,25 @@ get_pid() { log_info "Usage: get_pid " return 1 fi - + process_name="$1" - - # Try multiple ps variants for compatibility - pid=$(ps -e | awk -v name="$process_name" '$NF == name { print $1 }') - [ -z "$pid" ] && pid=$(ps -A | awk -v name="$process_name" '$NF == name { print $1 }') - [ -z "$pid" ] && pid=$(ps -aux | awk -v name="$process_name" '$11 == name { print $2 }') - [ -z "$pid" ] && pid=$(ps -ef | awk -v name="$process_name" '$NF == name { print $2 }') - + pid="" + + # Prefer pgrep if available (fast + clean) + if command -v pgrep >/dev/null 2>&1; then + pid=$(pgrep -x "$process_name" 2>/dev/null | awk 'NR==1 {print; exit}') + fi + + # POSIX fallback: ps + if [ -z "$pid" ]; then + pid=$(ps -e 2>/dev/null | awk -v name="$process_name" '$NF == name { print $1; exit }') + fi + if [ -n "$pid" ]; then - echo "$pid" + printf '%s\n' "$pid" return 0 - else - log_info "Process '$process_name' not found." - return 1 fi + + log_info "Process '$process_name' not found." + return 1 }