#!/usr/bin/env bash # Self-test: curve logic, NVML read, API (dry-run). Full fan write needs sudo. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" STACK_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" cd "${STACK_DIR}" mkdir -p config cp -n curve.default.json config/curve.json 2>/dev/null || true export CURVE_PATH="${STACK_DIR}/config/curve.json" export DRY_RUN=true export GPU_FAN_PORT=18090 echo "=== 1. Curve logic ===" .venv/bin/python -c " from fan_controller import parse_curve, interpolate_speed pts = parse_curve({'30':50,'40':65,'50':80,'55':90,'60':100,'70':100}) assert interpolate_speed(45, pts) in (72, 73) assert interpolate_speed(70, pts) == 100 print('OK') " echo "=== 2. NVML read ===" .venv/bin/python -c " import pynvml pynvml.nvmlInit() h = pynvml.nvmlDeviceGetHandleByIndex(0) t = pynvml.nvmlDeviceGetTemperature(h, pynvml.NVML_TEMPERATURE_GPU) print(f'GPU temp: {t}C') pynvml.nvmlShutdown() print('OK') " echo "=== 3. API dry-run (background) ===" .venv/bin/python app.py & APP_PID=$! trap 'kill $APP_PID 2>/dev/null || true' EXIT sleep 2 STATUS=$(curl -sf "http://127.0.0.1:${GPU_FAN_PORT}/api/status") echo "$STATUS" | .venv/bin/python -m json.tool | head -20 TARGET=$(echo "$STATUS" | .venv/bin/python -c "import sys,json; print(json.load(sys.stdin)['target_speed_pct'])") TEMP=$(echo "$STATUS" | .venv/bin/python -c "import sys,json; print(json.load(sys.stdin)['temperature_c'])") echo "Temp=${TEMP}C target=${TARGET}%" curl -sf -X PUT "http://127.0.0.1:${GPU_FAN_PORT}/api/curve" \ -H 'Content-Type: application/json' \ -d '{"points":[{"temp":30,"speed":50},{"temp":40,"speed":65},{"temp":50,"speed":80},{"temp":55,"speed":90},{"temp":60,"speed":100},{"temp":70,"speed":100}]}' \ | .venv/bin/python -m json.tool >/dev/null echo "Curve PUT: OK" curl -sf -X POST "http://127.0.0.1:${GPU_FAN_PORT}/api/mode" \ -H 'Content-Type: application/json' \ -d '{"mode":"manual","speed":100}' >/dev/null echo "Mode manual 100%: OK" kill $APP_PID 2>/dev/null || true trap - EXIT echo "" if sudo -n true 2>/dev/null; then echo "=== 4. Fan write (root) ===" sudo -n env CURVE_PATH="$CURVE_PATH" .venv/bin/python -c " from pathlib import Path from fan_controller import FanController c = FanController(Path('$CURVE_PATH'), 0, 2.0) c.init_nvml() c.set_mode('manual', 50) m = c.update_once() print(f\"Applied: {m['temperature_c']}C -> {m['target_speed_pct']}%\") c.set_mode('auto') c.update_once() c.shutdown() print('OK') " else echo "=== 4. Fan write (root) — SKIP (sudo needs password) ===" echo " Run: sudo scripts/install.sh && sudo systemctl start gpu-fan" fi echo "" echo "All automated checks passed."