#!/bin/bash # ══════════════════════════════════════════════════════════════════════════════ # Volt Hybrid Integration Test Runner # # Runs all hybrid integration tests in sequence and reports a summary. # # Usage: # sudo ./run_tests.sh # Run all tests # sudo ./run_tests.sh lifecycle # Run only matching test(s) # sudo ./run_tests.sh --list # List available tests # # Environment variables: # VOLT=/path/to/volt — Override volt binary path # OP_TIMEOUT=60 — Timeout for workload operations (seconds) # BOOT_TIMEOUT=30 — Timeout for workload boot readiness (seconds) # # Exit codes: # 0 — All tests passed # 1 — One or more tests failed # 2 — Prerequisites not met # ══════════════════════════════════════════════════════════════════════════════ set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" VOLT="${VOLT:-$(cd "$SCRIPT_DIR/../.." && pwd)/volt}" # ── Color ───────────────────────────────────────────────────────────────────── if [[ -t 1 ]]; then GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[0;33m' BOLD='\033[1m' DIM='\033[0;90m' RESET='\033[0m' else GREEN='' RED='' YELLOW='' BOLD='' DIM='' RESET='' fi # ── Test Suite Registry ─────────────────────────────────────────────────────── # Order matters: lifecycle tests first, then more complex tests TEST_SUITES=( "test_container_lifecycle.sh:Container Mode Lifecycle" "test_hybrid_lifecycle.sh:Hybrid-Native Mode Lifecycle" "test_mode_toggle.sh:Mode Toggle (Container ↔ Hybrid)" "test_isolation.sh:Isolation Verification" "test_manifest.sh:Manifest Validation" ) # ── Command-Line Handling ───────────────────────────────────────────────────── if [[ "${1:-}" == "--list" || "${1:-}" == "-l" ]]; then echo "Available test suites:" for entry in "${TEST_SUITES[@]}"; do script="${entry%%:*}" desc="${entry#*:}" echo " $script — $desc" done exit 0 fi if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then echo "Usage: sudo $0 [filter]" echo "" echo "Options:" echo " --list, -l List available test suites" echo " --help, -h Show this help" echo " Run only tests matching this string" echo "" echo "Environment:" echo " VOLT=/path Override volt binary path (default: auto-detect)" echo " OP_TIMEOUT Workload operation timeout in seconds (default: 60)" echo " BOOT_TIMEOUT Boot readiness timeout in seconds (default: 30)" exit 0 fi FILTER="${1:-}" # ── Prerequisites ───────────────────────────────────────────────────────────── echo "" echo -e "${BOLD}⚡ Volt Hybrid Integration Test Suite${RESET}" echo "════════════════════════════════════════════════════════════════" echo "" # Root check if [[ $EUID -ne 0 ]]; then echo -e "${RED}ERROR: Integration tests require root.${RESET}" echo "Run with: sudo $0" exit 2 fi # Volt binary if [[ ! -x "$VOLT" ]]; then echo -e "${RED}ERROR: volt binary not found at $VOLT${RESET}" echo "Build with: cd $(dirname "$VOLT") && make build" exit 2 fi echo -e " Volt binary: ${DIM}$VOLT${RESET}" VOLT_VERSION=$("$VOLT" version --short 2>/dev/null || "$VOLT" --version 2>/dev/null | head -1 || echo "unknown") echo -e " Version: ${DIM}$VOLT_VERSION${RESET}" # systemd-nspawn if ! command -v systemd-nspawn &>/dev/null; then echo -e "${RED}ERROR: systemd-nspawn not found. Install systemd-container.${RESET}" exit 2 fi echo -e " systemd-nspawn: ${DIM}$(systemd-nspawn --version 2>/dev/null | head -1 || echo "installed")${RESET}" # Base image BASE_IMAGE="/var/lib/volt/images/ubuntu_24.04" if [[ -d "$BASE_IMAGE" ]]; then echo -e " Base image: ${DIM}$BASE_IMAGE${RESET}" else echo -e " Base image: ${YELLOW}NOT FOUND${RESET}" echo "" echo " The base image is required for most tests." echo " Create it with:" echo " sudo mkdir -p /var/lib/volt/images" echo " sudo debootstrap noble $BASE_IMAGE http://archive.ubuntu.com/ubuntu" echo "" echo " Continuing — tests that need it will be skipped." fi # Kernel and host info echo -e " Host kernel: ${DIM}$(uname -r)${RESET}" echo -e " cgroups v2: ${DIM}$(test -f /sys/fs/cgroup/cgroup.controllers && echo "yes ($(cat /sys/fs/cgroup/cgroup.controllers))" || echo "no")${RESET}" echo -e " Landlock: ${DIM}$(test -f /sys/kernel/security/landlock/abi_version && echo "yes (ABI v$(cat /sys/kernel/security/landlock/abi_version))" || echo "not detected")${RESET}" echo "" echo "────────────────────────────────────────────────────────────────" echo "" # ── Run Tests ───────────────────────────────────────────────────────────────── TOTAL_SUITES=0 PASSED_SUITES=0 FAILED_SUITES=0 SKIPPED_SUITES=0 FAILED_NAMES=() START_TIME=$(date +%s) for entry in "${TEST_SUITES[@]}"; do script="${entry%%:*}" desc="${entry#*:}" # Apply filter if [[ -n "$FILTER" ]] && ! echo "$script $desc" | grep -qi "$FILTER"; then continue fi TOTAL_SUITES=$((TOTAL_SUITES + 1)) script_path="$SCRIPT_DIR/$script" if [[ ! -x "$script_path" ]]; then echo -e "${YELLOW}⊘${RESET} $desc — ${DIM}$script not executable${RESET}" SKIPPED_SUITES=$((SKIPPED_SUITES + 1)) continue fi echo -e "${BOLD}▶ Running: $desc${RESET} ${DIM}($script)${RESET}" echo "" # Run the test suite, passing through environment if VOLT="$VOLT" bash "$script_path"; then PASSED_SUITES=$((PASSED_SUITES + 1)) echo "" else FAILED_SUITES=$((FAILED_SUITES + 1)) FAILED_NAMES+=("$desc") echo "" fi done END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) # ── Summary ─────────────────────────────────────────────────────────────────── echo "" echo "════════════════════════════════════════════════════════════════" echo -e "${BOLD}⚡ Volt Hybrid Integration Test Summary${RESET}" echo "────────────────────────────────────────────────────────────────" echo -e " Suites passed: ${GREEN}${PASSED_SUITES}${RESET}" echo -e " Suites failed: ${RED}${FAILED_SUITES}${RESET}" if [[ $SKIPPED_SUITES -gt 0 ]]; then echo -e " Suites skipped: ${YELLOW}${SKIPPED_SUITES}${RESET}" fi echo " Total suites: ${TOTAL_SUITES}" echo " Duration: ${DURATION}s" echo "════════════════════════════════════════════════════════════════" if [[ $FAILED_SUITES -gt 0 ]]; then echo "" echo -e "${RED}Failed suites:${RESET}" for name in "${FAILED_NAMES[@]}"; do echo -e " ${RED}✗${RESET} $name" done echo "" exit 1 fi echo "" echo -e "${GREEN}All test suites passed! ✅${RESET}" echo "" exit 0