2025-12-29 12:29:46 +01:00
|
|
|
#!/usr/bin/env bats
|
|
|
|
|
#
|
|
|
|
|
# Tests unitaires pour les fonctions de health check
|
2025-12-29 13:06:49 +01:00
|
|
|
# Tests simplifiés pour environnement sans ZFS (container Docker)
|
2025-12-29 12:29:46 +01:00
|
|
|
#
|
|
|
|
|
|
|
|
|
|
load test_helper
|
|
|
|
|
|
|
|
|
|
# Charger uniquement les fonctions du script (pas le code principal)
|
|
|
|
|
setup() {
|
|
|
|
|
# Setup environnement
|
|
|
|
|
setup_script_env
|
|
|
|
|
|
|
|
|
|
# Sourcer le script en mode test (le BATS_TEST_MODE évite l'exécution du main)
|
|
|
|
|
export BATS_TEST_MODE=true
|
|
|
|
|
source "${BATS_TEST_DIRNAME}/../zfs-nfs-replica.sh"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
teardown() {
|
|
|
|
|
cleanup_script_env
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
2025-12-29 13:06:49 +01:00
|
|
|
# Tests: Fonctions existent et sont appelables
|
2025-12-29 12:29:46 +01:00
|
|
|
# ============================================================================
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "get_pool_disk_uuids: fonction existe" {
|
|
|
|
|
declare -F get_pool_disk_uuids
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "init_disk_tracking: fonction existe" {
|
|
|
|
|
declare -F init_disk_tracking
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "verify_disk_presence: fonction existe" {
|
|
|
|
|
declare -F verify_disk_presence
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "check_pool_health_status: fonction existe" {
|
|
|
|
|
declare -F check_pool_health_status
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "triple_health_check: fonction existe" {
|
|
|
|
|
declare -F triple_health_check
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "check_recent_critical_error: fonction existe" {
|
|
|
|
|
declare -F check_recent_critical_error
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "record_critical_error: fonction existe" {
|
|
|
|
|
declare -F record_critical_error
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "handle_health_failure: fonction existe" {
|
|
|
|
|
declare -F handle_health_failure
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "verify_pool_health: fonction existe" {
|
|
|
|
|
declare -F verify_pool_health
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
2025-12-29 13:06:49 +01:00
|
|
|
# Tests: check_recent_critical_error (ne nécessite pas ZFS)
|
2025-12-29 12:29:46 +01:00
|
|
|
# ============================================================================
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "check_recent_critical_error: retourne 0 si erreur récente (<1h)" {
|
|
|
|
|
# Erreur il y a 30 minutes (1800 secondes)
|
|
|
|
|
local current_epoch=1735481400
|
|
|
|
|
local error_epoch=$((current_epoch - 1800))
|
|
|
|
|
|
|
|
|
|
export TEST_CURRENT_EPOCH=$current_epoch
|
|
|
|
|
create_critical_error_file "zpool1" "$error_epoch"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
run check_recent_critical_error "zpool1"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
|
|
|
|
[ "$status" -eq 0 ]
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "check_recent_critical_error: retourne 1 si erreur ancienne (>1h)" {
|
|
|
|
|
# Erreur il y a 2 heures (7200 secondes)
|
|
|
|
|
local current_epoch=1735481400
|
|
|
|
|
local error_epoch=$((current_epoch - 7200))
|
|
|
|
|
|
|
|
|
|
export TEST_CURRENT_EPOCH=$current_epoch
|
|
|
|
|
create_critical_error_file "zpool1" "$error_epoch"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
run check_recent_critical_error "zpool1"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
|
|
|
|
[ "$status" -eq 1 ]
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "check_recent_critical_error: retourne 1 si pas de fichier d'erreur" {
|
|
|
|
|
rm -f "${STATE_DIR}/critical-errors-zpool1.txt"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
run check_recent_critical_error "zpool1"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
|
|
|
|
[ "$status" -eq 1 ]
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "check_recent_critical_error: cooldown de 1h est respecté" {
|
|
|
|
|
local current_epoch=1735481400
|
|
|
|
|
local error_epoch=$((current_epoch - 3599)) # 1 seconde avant le cooldown
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
export TEST_CURRENT_EPOCH=$current_epoch
|
|
|
|
|
create_critical_error_file "zpool1" "$error_epoch"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
run check_recent_critical_error "zpool1"
|
|
|
|
|
|
|
|
|
|
[ "$status" -eq 0 ] # Encore dans la période de cooldown
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
2025-12-29 13:06:49 +01:00
|
|
|
# Tests: Configuration CLUSTER_NODES
|
2025-12-29 12:29:46 +01:00
|
|
|
# ============================================================================
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "CLUSTER_NODES: contient acemagician et elitedesk" {
|
|
|
|
|
[ -n "${CLUSTER_NODES[acemagician]}" ]
|
|
|
|
|
[ -n "${CLUSTER_NODES[elitedesk]}" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "CLUSTER_NODES: IPs correctes pour chaque nœud" {
|
|
|
|
|
[ "${CLUSTER_NODES[acemagician]}" = "192.168.100.10" ]
|
|
|
|
|
[ "${CLUSTER_NODES[elitedesk]}" = "192.168.100.20" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Nœud distant: elitedesk détecte acemagician" {
|
|
|
|
|
export TEST_HOSTNAME="elitedesk"
|
|
|
|
|
LOCAL_NODE=$(hostname)
|
|
|
|
|
|
|
|
|
|
# Trouver le nœud distant
|
|
|
|
|
REMOTE_NODE_NAME=""
|
|
|
|
|
REMOTE_NODE_IP=""
|
|
|
|
|
for node in "${!CLUSTER_NODES[@]}"; do
|
|
|
|
|
if [[ "$node" != "$LOCAL_NODE" ]]; then
|
|
|
|
|
REMOTE_NODE_NAME="$node"
|
|
|
|
|
REMOTE_NODE_IP="${CLUSTER_NODES[$node]}"
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
done
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
[ "$REMOTE_NODE_NAME" = "acemagician" ]
|
|
|
|
|
[ "$REMOTE_NODE_IP" = "192.168.100.10" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Nœud distant: acemagician détecte elitedesk" {
|
|
|
|
|
export TEST_HOSTNAME="acemagician"
|
|
|
|
|
LOCAL_NODE=$(hostname)
|
|
|
|
|
|
|
|
|
|
# Trouver le nœud distant
|
|
|
|
|
REMOTE_NODE_NAME=""
|
|
|
|
|
REMOTE_NODE_IP=""
|
|
|
|
|
for node in "${!CLUSTER_NODES[@]}"; do
|
|
|
|
|
if [[ "$node" != "$LOCAL_NODE" ]]; then
|
|
|
|
|
REMOTE_NODE_NAME="$node"
|
|
|
|
|
REMOTE_NODE_IP="${CLUSTER_NODES[$node]}"
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
done
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
[ "$REMOTE_NODE_NAME" = "elitedesk" ]
|
|
|
|
|
[ "$REMOTE_NODE_IP" = "192.168.100.20" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Nœud distant: erreur si nœud local inconnu" {
|
|
|
|
|
export TEST_HOSTNAME="unknown-node"
|
|
|
|
|
LOCAL_NODE=$(hostname)
|
|
|
|
|
|
|
|
|
|
# Vérifier que le nœud local n'est pas dans la config
|
|
|
|
|
if [[ ! -v "CLUSTER_NODES[$LOCAL_NODE]" ]]; then
|
|
|
|
|
# Comportement attendu : erreur
|
|
|
|
|
run echo "Node not found"
|
|
|
|
|
[ "$status" -eq 0 ]
|
|
|
|
|
else
|
|
|
|
|
# Ne devrait pas arriver ici
|
|
|
|
|
false
|
|
|
|
|
fi
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Nœud distant: erreur si cluster à 1 seul nœud" {
|
|
|
|
|
# Créer un cluster avec un seul nœud
|
|
|
|
|
declare -A TEST_CLUSTER=(
|
|
|
|
|
["lonely-node"]="192.168.100.99"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
export TEST_HOSTNAME="lonely-node"
|
|
|
|
|
LOCAL_NODE=$(hostname)
|
|
|
|
|
|
|
|
|
|
# Chercher nœud distant
|
|
|
|
|
REMOTE_NODE_NAME=""
|
|
|
|
|
REMOTE_NODE_IP=""
|
|
|
|
|
for node in "${!TEST_CLUSTER[@]}"; do
|
|
|
|
|
if [[ "$node" != "$LOCAL_NODE" ]]; then
|
|
|
|
|
REMOTE_NODE_NAME="$node"
|
|
|
|
|
REMOTE_NODE_IP="${TEST_CLUSTER[$node]}"
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
done
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
# Aucun nœud distant trouvé
|
|
|
|
|
[ -z "$REMOTE_NODE_NAME" ]
|
|
|
|
|
[ -z "$REMOTE_NODE_IP" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Cluster 3 nœuds: détecte le premier nœud distant disponible" {
|
|
|
|
|
# Créer un cluster avec 3 nœuds
|
|
|
|
|
declare -A EXTENDED_CLUSTER=(
|
|
|
|
|
["node1"]="192.168.100.10"
|
|
|
|
|
["node2"]="192.168.100.20"
|
|
|
|
|
["node3"]="192.168.100.30"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
export TEST_HOSTNAME="node1"
|
|
|
|
|
LOCAL_NODE=$(hostname)
|
|
|
|
|
|
|
|
|
|
# Trouver le premier nœud distant
|
|
|
|
|
REMOTE_NODE_NAME=""
|
|
|
|
|
REMOTE_NODE_IP=""
|
|
|
|
|
for node in "${!EXTENDED_CLUSTER[@]}"; do
|
|
|
|
|
if [[ "$node" != "$LOCAL_NODE" ]]; then
|
|
|
|
|
REMOTE_NODE_NAME="$node"
|
|
|
|
|
REMOTE_NODE_IP="${EXTENDED_CLUSTER[$node]}"
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
done
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
# Un nœud distant doit être trouvé (node2 ou node3)
|
|
|
|
|
[ -n "$REMOTE_NODE_NAME" ]
|
|
|
|
|
[ -n "$REMOTE_NODE_IP" ]
|
|
|
|
|
[[ "$REMOTE_NODE_NAME" != "node1" ]]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
2025-12-29 13:06:49 +01:00
|
|
|
# Tests: Validation des variables de configuration
|
2025-12-29 12:29:46 +01:00
|
|
|
# ============================================================================
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Variables de config: ZPOOLS est un tableau non vide" {
|
|
|
|
|
[ "${#ZPOOLS[@]}" -gt 0 ]
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Variables de config: CTID est défini" {
|
|
|
|
|
[ -n "$CTID" ]
|
|
|
|
|
[ "$CTID" -eq "$CTID" ] 2>/dev/null # Vérifier que c'est un nombre
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Variables de config: CONTAINER_NAME est défini" {
|
|
|
|
|
[ -n "$CONTAINER_NAME" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Variables de config: HEALTH_CHECK_MIN_FREE_SPACE valide" {
|
|
|
|
|
[ "$HEALTH_CHECK_MIN_FREE_SPACE" -ge 0 ]
|
|
|
|
|
[ "$HEALTH_CHECK_MIN_FREE_SPACE" -le 100 ]
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Variables de config: HEALTH_CHECK_ERROR_COOLDOWN valide" {
|
|
|
|
|
[ "$HEALTH_CHECK_ERROR_COOLDOWN" -gt 0 ]
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Variables de config: STATE_DIR est défini" {
|
|
|
|
|
[ -n "$STATE_DIR" ]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@test "Variables de config: LOG_DIR est défini" {
|
|
|
|
|
[ -n "$LOG_DIR" ]
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Variables de config: SSH_KEY est défini" {
|
|
|
|
|
[ -n "$SSH_KEY" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
2025-12-29 13:06:49 +01:00
|
|
|
# Tests: Fichiers d'état (sans ZFS)
|
2025-12-29 12:29:46 +01:00
|
|
|
# ============================================================================
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "create_disk_uuid_file: crée fichier avec format correct" {
|
|
|
|
|
create_disk_uuid_file "zpool1" "wwn-0x5000cca2dfe2e414"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
[ -f "${STATE_DIR}/disk-uuids-zpool1.txt" ]
|
|
|
|
|
grep -q "initialized=true" "${STATE_DIR}/disk-uuids-zpool1.txt"
|
|
|
|
|
grep -q "pool=zpool1" "${STATE_DIR}/disk-uuids-zpool1.txt"
|
|
|
|
|
grep -q "wwn-0x5000cca2dfe2e414" "${STATE_DIR}/disk-uuids-zpool1.txt"
|
|
|
|
|
}
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "create_critical_error_file: crée fichier avec format correct" {
|
|
|
|
|
create_critical_error_file "zpool1" "1735481400"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
|
|
|
|
[ -f "${STATE_DIR}/critical-errors-zpool1.txt" ]
|
2025-12-29 13:06:49 +01:00
|
|
|
grep -q "epoch=1735481400" "${STATE_DIR}/critical-errors-zpool1.txt"
|
|
|
|
|
grep -q "reason=Test error" "${STATE_DIR}/critical-errors-zpool1.txt"
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
@test "Fichiers d'état: isolation par pool" {
|
|
|
|
|
create_disk_uuid_file "zpool1"
|
|
|
|
|
create_disk_uuid_file "zpool2"
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
[ -f "${STATE_DIR}/disk-uuids-zpool1.txt" ]
|
|
|
|
|
[ -f "${STATE_DIR}/disk-uuids-zpool2.txt" ]
|
2025-12-29 12:29:46 +01:00
|
|
|
|
2025-12-29 13:06:49 +01:00
|
|
|
# Les fichiers doivent être différents
|
|
|
|
|
! diff "${STATE_DIR}/disk-uuids-zpool1.txt" "${STATE_DIR}/disk-uuids-zpool2.txt"
|
2025-12-29 12:29:46 +01:00
|
|
|
}
|