#!/usr/bin/env bats # Tests for lib/detect.sh — hardware and config detection load test_helper.sh setup() { source_lib common.sh source_lib format.sh source_lib detect.sh setup_mock_sysfs # Override GPU_SYSFS AFTER sourcing detect.sh (which sets it at load time) export GPU_SYSFS="$MOCK_SYSFS/class/drm/card0/device" } teardown() { teardown_mock_sysfs } # ── GPU sysfs reads ────────────────────────────────────── @test "detect_vram_total: reads mocked value" { echo "34359738368" > "$GPU_SYSFS/mem_info_vram_total" run detect_vram_total assert_output "34359738368" } @test "detect_vram_total: returns 0 when sysfs file missing" { rm -f "$GPU_SYSFS/mem_info_vram_total" run detect_vram_total assert_output "0" } @test "detect_gtt_total: reads mocked value" { echo "64424509440" > "$GPU_SYSFS/mem_info_gtt_total" run detect_gtt_total assert_output "64424509440" } @test "detect_gpu_busy: reads percentage" { echo "42" > "$GPU_SYSFS/gpu_busy_percent" run detect_gpu_busy assert_output "42" } @test "detect_gpu_busy: returns 0 when sysfs file missing" { rm -f "$GPU_SYSFS/gpu_busy_percent" run detect_gpu_busy assert_output "0" } @test "detect_gpu_temp: reads millidegrees" { echo "55000" > "$GPU_SYSFS/hwmon/hwmon0/temp1_input" run detect_gpu_temp assert_output "55000" } @test "detect_gpu_temp: returns 0 when hwmon missing" { rm -f "$GPU_SYSFS/hwmon/hwmon0/temp1_input" run detect_gpu_temp assert_output "0" } @test "detect_gpu_power: reads microwatts" { echo "30000000" > "$GPU_SYSFS/hwmon/hwmon0/power1_average" run detect_gpu_power assert_output "30000000" } @test "detect_gpu_power: returns 0 when hwmon missing" { rm -f "$GPU_SYSFS/hwmon/hwmon0/power1_average" run detect_gpu_power assert_output "0" } @test "detect_gpu_device_id: reads and strips 0x prefix" { echo "0x1586" > "$GPU_SYSFS/device" run detect_gpu_device_id assert_output "1586" } @test "detect_gpu_device_id: handles device ID without 0x prefix" { echo "1586" > "$GPU_SYSFS/device" run detect_gpu_device_id assert_output "1586" } # ── Kernel param detection (tests the REAL detect_kernel_param logic) ──── # Helper: create a mock /proc/cmdline and call detect_kernel_param against it _test_kernel_param() { local param="$1" cmdline="$2" # Temporarily replace /proc/cmdline reading by overriding the function # to use a variable instead of reading /proc/cmdline eval 'detect_kernel_param() { local param="$1" local cmdline="'"${cmdline}"'" local pattern="${param//./\\.}" if [[ "$cmdline" =~ (^|[[:space:]])${pattern}=([^ ]+) ]]; then echo "${BASH_REMATCH[2]}" elif [[ "$cmdline" =~ (^|[[:space:]])${pattern}([[:space:]]|$) ]]; then echo "present" fi }' detect_kernel_param "$param" } @test "kernel_param: extracts iommu=pt" { run _test_kernel_param 'iommu' "BOOT_IMAGE=/boot/vmlinuz root=UUID=abc ro iommu=pt quiet" assert_output "pt" } @test "kernel_param: extracts amdgpu.gttsize value" { run _test_kernel_param 'amdgpu.gttsize' "BOOT_IMAGE=/boot/vmlinuz iommu=pt amdgpu.gttsize=61440 quiet" assert_output "61440" } @test "kernel_param: returns empty when param missing" { run _test_kernel_param 'iommu' "BOOT_IMAGE=/boot/vmlinuz root=UUID=abc ro quiet" assert_output "" } @test "kernel_param: iommu does NOT match amd_iommu (word boundary)" { run _test_kernel_param 'iommu' "BOOT_IMAGE=/boot/vmlinuz amd_iommu=off quiet" assert_output "" } @test "kernel_param: amdgpu.gttsize does NOT match xamdgpu.gttsize" { run _test_kernel_param 'amdgpu.gttsize' "BOOT_IMAGE=/boot/vmlinuz xamdgpu.gttsize=99999 quiet" assert_output "" } @test "kernel_param: dot is literal not regex wildcard" { run _test_kernel_param 'amdgpu.gttsize' "BOOT_IMAGE=/boot/vmlinuz amdgpuXgttsize=99999 quiet" assert_output "" } @test "kernel_param: param at start of cmdline" { run _test_kernel_param 'iommu' "iommu=pt root=UUID=abc ro quiet" assert_output "pt" } @test "kernel_param: param at end of cmdline" { run _test_kernel_param 'iommu' "BOOT_IMAGE=/boot/vmlinuz iommu=pt" assert_output "pt" } @test "kernel_param: boolean param without value" { run _test_kernel_param 'quiet' "BOOT_IMAGE=/boot/vmlinuz iommu=pt quiet" assert_output "present" } @test "kernel_param: param with equals in value (UUID)" { run _test_kernel_param 'root' "BOOT_IMAGE=/boot/vmlinuz root=UUID=abc-def-123" assert_output "UUID=abc-def-123" } @test "kernel_param: ttm.pages_limit extracted correctly" { run _test_kernel_param 'ttm.pages_limit' "iommu=pt amdgpu.gttsize=61440 ttm.pages_limit=15728640" assert_output "15728640" } # ── Recommended values ─────────────────────────────────── @test "recommended_gttsize_mib: 64 GiB system" { # 32 GiB visible RAM (in KB) + 32 GiB VRAM (in bytes) detect_system_ram_kb() { echo "33554432"; } detect_vram_total() { echo "34359738368"; } run recommended_gttsize_mib # total_kb = 33554432 + (34359738368/1024) = 33554432 + 33554432 = 67108864 KB # total_gib = 67108864 / 1024 / 1024 = 64, gtt = 64 - 4 = 60, result = 61440 MiB assert_output "61440" } @test "recommended_gttsize_mib: 128 GiB system with 0.5 GiB VRAM" { detect_system_ram_kb() { echo "130023424"; } # ~124 GiB visible detect_vram_total() { echo "536870912"; } # 0.5 GiB = 524288 KB run recommended_gttsize_mib # total_kb = 130023424 + 524288 = 130547712 → 124 GiB → 120 GiB GTT → 122880 MiB assert_output "122880" } @test "recommended_gttsize_mib: tiny system (2 GiB) floors at 1 GiB" { detect_system_ram_kb() { echo "2097152"; } detect_vram_total() { echo "0"; } run recommended_gttsize_mib # 2 GiB - 4 = -2 → floored to 1 → 1024 MiB assert_output "1024" } @test "recommended_gttsize_mib: zero RAM floors at 1 GiB" { detect_system_ram_kb() { echo "0"; } detect_vram_total() { echo "0"; } run recommended_gttsize_mib assert_output "1024" } @test "recommended_gttsize_mib: exactly 4 GiB (reserve equals total) floors at 1 GiB" { detect_system_ram_kb() { echo "4194304"; } detect_vram_total() { echo "0"; } run recommended_gttsize_mib # 4 - 4 = 0 → floored to 1 → 1024 assert_output "1024" } @test "recommended_gttsize_mib: 5 GiB system → 1 GiB GTT" { detect_system_ram_kb() { echo "5242880"; } detect_vram_total() { echo "0"; } run recommended_gttsize_mib assert_output "1024" } @test "recommended_gttsize_mib: non-GiB-aligned RAM (65535 MiB)" { # 65535 MiB = 67107840 KB. Integer division: 67107840/1024/1024 = 63 GiB detect_system_ram_kb() { echo "67107840"; } detect_vram_total() { echo "0"; } run recommended_gttsize_mib # 63 - 4 = 59 → 59 * 1024 = 60416 MiB assert_output "60416" } @test "recommended_pages_limit: matches gttsize * 256" { detect_system_ram_kb() { echo "33554432"; } detect_vram_total() { echo "34359738368"; } local gttsize gttsize="$(recommended_gttsize_mib)" run recommended_pages_limit assert_output "$(( gttsize * 256 ))" } # ── Firmware detection ─────────────────────────────────── @test "detect_firmware_bad: true for known bad version" { detect_firmware_version() { echo "20251125-1"; } run detect_firmware_bad assert_success } @test "detect_firmware_bad: false for good version" { detect_firmware_version() { echo "20260309-1"; } run detect_firmware_bad assert_failure } @test "detect_firmware_bad: false for 'unknown' string" { detect_firmware_version() { echo "unknown"; } run detect_firmware_bad assert_failure } @test "detect_firmware_bad: false for empty string" { detect_firmware_version() { echo ""; } run detect_firmware_bad assert_failure } # ── Stack detection ────────────────────────────────────── @test "detect_stack_ollama: missing when not installed" { is_cmd() { return 1; } run detect_stack_ollama assert_output "missing" } @test "detect_stack_ollama: installed when available" { is_cmd() { [[ "$1" == "ollama" ]] && return 0 || return 1; } run detect_stack_ollama assert_output "installed" } @test "detect_stack_llamacpp: installed when llama-cli exists" { is_cmd() { [[ "$1" == "llama-cli" ]] && return 0 || return 1; } run detect_stack_llamacpp assert_output "installed" } @test "detect_stack_llamacpp: installed when llama-bench exists" { is_cmd() { [[ "$1" == "llama-bench" ]] && return 0 || return 1; } run detect_stack_llamacpp assert_output "installed" } # ── detect_total_physical_ram_kb ───────────────────────── @test "detect_total_physical_ram_kb: adds visible RAM and VRAM" { detect_system_ram_kb() { echo "33554432"; } # 32 GiB in KB detect_vram_total() { echo "34359738368"; } # 32 GiB in bytes = 33554432 KB run detect_total_physical_ram_kb # 33554432 + 33554432 = 67108864 assert_output "67108864" } @test "detect_total_physical_ram_kb: handles zero VRAM" { detect_system_ram_kb() { echo "33554432"; } detect_vram_total() { echo "0"; } run detect_total_physical_ram_kb assert_output "33554432" }