Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 67 additions & 20 deletions Runner/suites/Multimedia/Graphics/KMSCube/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause-Clear

# KMSCube Validator Script (Yocto-Compatible)
# KMSCube Validator Script (Yocto-Compatible, POSIX sh)

# --- Robustly find and source init_env ---------------------------------------
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
INIT_ENV=""
SEARCH="$SCRIPT_DIR"
Expand All @@ -19,56 +21,101 @@ if [ -z "$INIT_ENV" ]; then
exit 1
fi

# Only source once (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"

# --- Test metadata -----------------------------------------------------------
TESTNAME="KMSCube"
FRAME_COUNT=999
EXPECTED_FRAMES=$((FRAME_COUNT - 1))
test_path=$(find_test_case_by_name "$TESTNAME")
FRAME_COUNT="${FRAME_COUNT:-999}" # allow override via env
EXPECTED_MIN=$((FRAME_COUNT - 1)) # tolerate off-by-one under-reporting

# Ensure we run from the testcase directory so .res/logs land next to run.sh
test_path="$(find_test_case_by_name "$TESTNAME")"
cd "$test_path" || exit 1

RES_FILE="./$TESTNAME.res"
LOG_FILE="./${TESTNAME}_run.log"
rm -f "$RES_FILE" "$LOG_FILE"

log_info "-------------------------------------------------------------------"
log_info "------------------- Starting $TESTNAME Testcase -------------------"

if check_dependencies "$TESTNAME"; then
log_fail "$TESTNAME : kmscube binary not found"
echo "$TESTNAME SKIP" > "$RES_FILE"
exit 1
# --- Dependencies ------------------------------------------------------------
# Note: check_dependencies returns 0 when present, non-zero if missing.
check_dependencies kmscube || {
log_skip "$TESTNAME SKIP: missing dependencies: kmscube"
echo "$TESTNAME SKIP" >"$RES_FILE"
exit 0
}
KMSCUBE_BIN="$(command -v kmscube 2>/dev/null || true)"
log_info "Using kmscube: ${KMSCUBE_BIN:-<not found>}"

# --- Basic DRM availability guard -------------------------------------------
set -- /dev/dri/card* 2>/dev/null
if [ ! -e "$1" ]; then
log_skip "$TESTNAME SKIP: no /dev/dri/card* nodes"
echo "$TESTNAME SKIP" >"$RES_FILE"
exit 0
fi

# --- If Weston is running, stop it so KMS has control ------------------------
weston_was_running=0
if weston_is_running; then
weston_stop
weston_was_running=1
fi

log_info "Running kmscube test with --count=$FRAME_COUNT..."
if kmscube --count="$FRAME_COUNT" > "$LOG_FILE" 2>&1; then
if grep -q "Rendered $EXPECTED_FRAMES frames" "$LOG_FILE"; then
log_pass "$TESTNAME : Test Passed"
echo "$TESTNAME PASS" > "$RES_FILE"
else
log_fail "$TESTNAME : Expected output not found (Rendered $EXPECTED_FRAMES frames)"
echo "$TESTNAME FAIL" > "$RES_FILE"
exit 1
# --- Execute kmscube ---------------------------------------------------------
log_info "Running kmscube with --count=${FRAME_COUNT} ..."
if kmscube --count="${FRAME_COUNT}" >"$LOG_FILE" 2>&1; then :; else
rc=$?
log_fail "$TESTNAME : Execution failed (rc=$rc) — see $LOG_FILE"
echo "$TESTNAME FAIL" >"$RES_FILE"
if [ "$weston_was_running" -eq 1 ]; then
log_info "Restarting Weston after failure"
weston_start
fi
exit 1
fi

# --- Parse 'Rendered N frames' (case-insensitive), use the last N -----------
FRAMES_RENDERED="$(
awk 'BEGIN{IGNORECASE=1}
/Rendered[[:space:]][0-9]+[[:space:]]+frames/{
# capture the numeric token on that line; remember the last match
for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+$/) n=$i
last=n
}
END{if (last!="") print last}' "$LOG_FILE"
)"
[ -n "$FRAMES_RENDERED" ] || FRAMES_RENDERED=0
[ "$EXPECTED_MIN" -lt 0 ] && EXPECTED_MIN=0
log_info "kmscube reported: Rendered ${FRAMES_RENDERED} frames (requested ${FRAME_COUNT}, min acceptable ${EXPECTED_MIN})"

# --- Verdict -----------------------------------------------------------------
if [ "$FRAMES_RENDERED" -ge "$EXPECTED_MIN" ]; then
log_pass "$TESTNAME : PASS"
echo "$TESTNAME PASS" >"$RES_FILE"
else
log_fail "$TESTNAME : Execution failed (non-zero exit code)"
echo "$TESTNAME FAIL" > "$RES_FILE"
log_fail "$TESTNAME : FAIL (rendered ${FRAMES_RENDERED} < ${EXPECTED_MIN})"
echo "$TESTNAME FAIL" >"$RES_FILE"
if [ "$weston_was_running" -eq 1 ]; then
log_info "Restarting Weston after failure"
weston_start
fi
exit 1
fi

# --- Restore Weston if we stopped it -----------------------------------------
if [ "$weston_was_running" -eq 1 ]; then
log_info "weston realuching after $TESTNAME completion"
log_info "Restarting Weston after $TESTNAME completion"
weston_start
fi

Expand Down
208 changes: 163 additions & 45 deletions Runner/suites/Multimedia/Graphics/weston-simple-egl/run.sh
Original file line number Diff line number Diff line change
@@ -1,80 +1,198 @@
#!/bin/sh
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause-Clear
# Description: Script to test the 'weston-simple-egl' Wayland client for 30 seconds and log the result.
# Validate weston-simple-egl runs under a working Wayland session.
# - Robust Wayland env resolution (adopts socket & fixes XDG_RUNTIME_DIR perms)
# - CI-friendly logs and PASS/FAIL semantics
# - Optional FPS parsing if build prints it (lenient if not present)

# Robustly find and source init_env
# ---------- Source init_env and functestlib ----------
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
INIT_ENV=""
SEARCH="$SCRIPT_DIR"
while [ "$SEARCH" != "/" ]; do
if [ -f "$SEARCH/init_env" ]; then
INIT_ENV="$SEARCH/init_env"
break
fi
SEARCH=$(dirname "$SEARCH")
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
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"
# shellcheck disable=SC1090
. "$INIT_ENV"
fi

# Always source functestlib.sh, using $TOOLS exported by init_env
# shellcheck disable=SC1090,SC1091
. "$TOOLS/functestlib.sh"

TESTNAME="weston-simple-egl"
# Tunables (env override)
DURATION="${DURATION:-30s}" # how long to run the client
STOP_GRACE="${STOP_GRACE:-3s}" # grace period on stop
EXPECT_FPS="${EXPECT_FPS:-60}" # nominal refresh (used for logging)
FPS_TOL_PCT="${FPS_TOL_PCT:-10}" # +/- tolerance %
REQUIRE_FPS="${REQUIRE_FPS:-0}" # 1=require FPS lines & threshold; 0=best effort

test_path=$(find_test_case_by_name "$TESTNAME")
test_path="$(find_test_case_by_name "$TESTNAME" 2>/dev/null || echo "$SCRIPT_DIR")"
cd "$test_path" || exit 1
RES_FILE="./$TESTNAME.res"
LOG_FILE="./${TESTNAME}_run.log"
rm -f "$RES_FILE" "$LOG_FILE"

log_info "--------------------------------------------------------------------------"
log_info "------------------- Starting $TESTNAME Testcase --------------------------"
# FIX #1: Use ASCII '+/-' and keep it in a normal string
log_info "Config: DURATION=$DURATION STOP_GRACE=$STOP_GRACE EXPECT_FPS=${EXPECT_FPS}+/-${FPS_TOL_PCT}% REQUIRE_FPS=$REQUIRE_FPS"

# Dependencies
check_dependencies weston-simple-egl || {
log_fail "$TESTNAME : weston-simple-egl binary not found in PATH"
echo "$TESTNAME SKIP" > "$RES_FILE"
exit 0
}
BIN="$(command -v weston-simple-egl 2>/dev/null || true)"
log_info "Using weston-simple-egl: ${BIN:-<none>}"

# Resolve Wayland socket:
# 1) If current env points to a real socket, use it.
sock=""
if [ -n "$XDG_RUNTIME_DIR" ] && [ -n "$WAYLAND_DISPLAY" ] && [ -e "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; then
sock="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY"
fi

# Only start if not already running
if ! weston_is_running; then
# 2) Otherwise, scan common locations.
if [ -z "$sock" ]; then
for s in $(find_wayland_sockets); do
if [ -e "$s" ]; then sock="$s"; break; fi
done
fi

# 3) If still no socket, try to start Weston and wait a bit.
if [ -z "$sock" ]; then
if weston_is_running; then
log_warn "Weston running but no Wayland socket visible; attempting to continue."
else
log_info "Weston not running. Attempting to start..."
weston_start
fi
# Wait for socket to appear (up to ~5s)
n=0
while [ $n -lt 5 ] && [ -z "$sock" ]; do
for s in $(find_wayland_sockets); do
if [ -e "$s" ]; then sock="$s"; break; fi
done
[ -n "$sock" ] && break
sleep 1
n=$((n+1))
done
fi

if check_dependencies weston-simple-egl; then
log_fail "$TESTNAME : weston-simple-egl binary not found"
echo "$TESTNAME SKIP" > "$RES_FILE"
exit 1
if [ -z "$sock" ]; then
log_fail "$TESTNAME : FAIL (no Wayland socket found after attempting to start Weston)"
echo "$TESTNAME FAIL" > "$RES_FILE"
exit 1
fi

# Adopt env and fix runtime dir perms (done inside helper(s))
adopt_wayland_env_from_socket "$sock"

# FIX #2: Avoid duplicate prints — helpers can log the chosen socket/env once.
# If your helpers are quiet instead, uncomment the two lines below:
# log_info "Selected Wayland socket: $sock"
# log_info "Wayland env: XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR WAYLAND_DISPLAY=$WAYLAND_DISPLAY"

if wayland_connection_ok; then
log_info "Wayland connection test: OK (wayland-info/env)"
else
log_fail "$TESTNAME : FAIL (Wayland connection test failed)"
print_path_meta "$XDG_RUNTIME_DIR" | sed 's/^/[DBG] /'
stat "$XDG_RUNTIME_DIR" 2>/dev/null | sed 's/^/[DBG] /' || true
echo "$TESTNAME FAIL" > "$RES_FILE"
exit 1
fi

XDG_RUNTIME_DIR="/dev/socket/weston"
WAYLAND_DISPLAY="wayland-1"
export XDG_RUNTIME_DIR WAYLAND_DISPLAY

mkdir -p "$XDG_RUNTIME_DIR"
chmod 0700 "$XDG_RUNTIME_DIR"
log_info "Running weston-simple-egl for 30 seconds..."
script -q -c "weston-simple-egl" "$LOG_FILE" 2>/dev/null &
EGL_PID=$!
sleep 30
kill "$EGL_PID" 2>/dev/null
wait "$EGL_PID" 2>/dev/null

count=$(grep -i -o "5 seconds" "$LOG_FILE" | wc -l)
if [ "$count" -ge 5 ]; then
log_pass "$TESTNAME : Test Passed"
# Try to enable FPS prints if supported by the client build (best effort).
export SIMPLE_EGL_FPS=1
export WESTON_SIMPLE_EGL_FPS=1

# Run the client for DURATION with a stopwatch for CI logs.
log_info "Running weston-simple-egl for $DURATION ..."
start_ts="$(date +%s 2>/dev/null || echo 0)"
if command -v run_with_timeout >/dev/null 2>&1; then
run_with_timeout "$DURATION" weston-simple-egl >"$LOG_FILE" 2>&1
rc=$?
else
if command -v timeout >/dev/null 2>&1; then
timeout "$DURATION" weston-simple-egl >"$LOG_FILE" 2>&1
rc=$?
else
# Last resort: background and sleep.
sh -c 'weston-simple-egl' >"$LOG_FILE" 2>&1 &
pid=$!
# DURATION like "30s" → "30"
dur_s="$(printf '%s' "$DURATION" | sed -n 's/^\([0-9][0-9]*\)s$/\1/p')"
[ -z "$dur_s" ] && dur_s="$DURATION"
sleep "$dur_s"
kill "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
rc=143
fi
fi
end_ts="$(date +%s 2>/dev/null || echo 0)"
elapsed=$(( end_ts - start_ts ))
[ "$elapsed" -lt 0 ] && elapsed=0

# FPS parsing (best effort)
fps="-"
fps_line="$(grep -E '([Ff][Pp][Ss]|frames per second|^fps:)' "$LOG_FILE" 2>/dev/null | tail -n 1)"
if [ -n "$fps_line" ]; then
# Extract last numeric token (integer or float)
fps="$(printf '%s\n' "$fps_line" | awk '{
for (i=NF;i>=1;i--) if ($i ~ /^[0-9]+(\.[0-9]+)?$/) {print $i; exit}
}')"
[ -z "$fps" ] && fps="-"
fi

# CI debugging summary
log_info "Result summary: rc=$rc elapsed=${elapsed}s fps=${fps} (expected ~${EXPECT_FPS}+/-${FPS_TOL_PCT}%)"
# Quick duration gate: must have run at least (DURATION-1) seconds to be considered OK.
dur_s="$(printf '%s' "$DURATION" | sed -n 's/^\([0-9][0-9]*\)s$/\1/p')"
[ -z "$dur_s" ] && dur_s="$DURATION"
min_ok=$(( dur_s - 1 ))
[ "$min_ok" -lt 0 ] && min_ok=0

final="PASS"

if [ "$elapsed" -lt "$min_ok" ]; then
final="FAIL"
log_fail "$TESTNAME : FAIL (exited after ${elapsed}s; expected ~${dur_s}s) — rc=$rc"
fi

# Optional FPS gate
if [ "$final" = "PASS" ] && [ "$REQUIRE_FPS" -eq 1 ]; then
if [ "$fps" = "-" ]; then
final="FAIL"
log_fail "$TESTNAME : FAIL (no FPS lines found but REQUIRE_FPS=1)"
else
# Integer-only tolerance check (portable)
lo=$(( (EXPECT_FPS * (100 - FPS_TOL_PCT)) / 100 ))
hi=$(( (EXPECT_FPS * (100 + FPS_TOL_PCT)) / 100 ))
fps_int="$(printf '%s' "$fps" | cut -d. -f1)"
if [ "$fps_int" -lt "$lo" ] || [ "$fps_int" -gt "$hi" ]; then
final="FAIL"
log_fail "$TESTNAME : FAIL (fps=$fps outside ${lo}-${hi})"
fi
fi
fi

case "$final" in
PASS)
log_pass "$TESTNAME : PASS"
echo "$TESTNAME PASS" > "$RES_FILE"
exit 0
else
log_fail "$TESTNAME : Test Failed"
;;
*)
echo "$TESTNAME FAIL" > "$RES_FILE"
exit 1
fi

log_info "------------------- Completed $TESTNAME Testcase ------------------------"
exit 0
;;
esac
Loading
Loading