#!/bin/bash set -euo pipefail # TEST-202: Dependency chain test. # Tests that apps with dependencies properly enforce install order. # # Test chains: # 1. electrs → requires bitcoin-knots # 2. btcpay-server → requires lnd # 3. mempool → requires bitcoin-knots + electrs # 4. fedimint-gateway → requires fedimint + lnd SSH_KEY="${ARCHIPELAGO_SSH_KEY:-$HOME/.ssh/archipelago-deploy}" TARGET="archipelago@192.168.1.228" SSH_CMD="ssh -i $SSH_KEY -o StrictHostKeyChecking=no $TARGET" PASSWORD="password123" PASS=0 FAIL=0 RESULTS=() log() { echo -e "\033[1;34m[TEST]\033[0m $*"; } pass() { echo -e "\033[1;32m[PASS]\033[0m $*"; PASS=$((PASS + 1)); RESULTS+=("PASS: $*"); } fail() { echo -e "\033[1;31m[FAIL]\033[0m $*"; FAIL=$((FAIL + 1)); RESULTS+=("FAIL: $*"); } get_session() { $SSH_CMD "curl -s -c - http://localhost:5678/rpc/v1 \ -X POST -H 'Content-Type: application/json' \ -d '{\"method\":\"auth.login\",\"params\":{\"password\":\"$PASSWORD\"}}' 2>/dev/null \ | grep session | awk '{print \$NF}'" } rpc_call() { local session="$1" method="$2" params="${3:-{}}" $SSH_CMD "curl -s http://localhost:5678/rpc/v1 \ -X POST -H 'Content-Type: application/json' \ -H 'Cookie: session=$session' \ -d '{\"method\":\"$method\",\"params\":$params}' 2>/dev/null" } # Test that installing an app without its dependency fails with a dependency error test_dep_blocked() { local session="$1" local app_id="$2" local dep_name="$3" log "Testing: $app_id should require $dep_name" local result result=$(rpc_call "$session" "package.install" "{\"id\":\"$app_id\"}") if echo "$result" | grep -qi "dependency\|requires\|must be\|needs"; then pass "$app_id correctly blocked — requires $dep_name" elif echo "$result" | grep -q '"error"'; then # Got an error, might still be dependency-related local msg msg=$(echo "$result" | grep -o '"message":"[^"]*"' | head -1 | sed 's/"message":"//;s/"$//') if echo "$msg" | grep -qi "$dep_name\|depend\|running\|install"; then pass "$app_id correctly blocked: $msg" else fail "$app_id — got error but not dependency-related: $msg" fi else # Install succeeded when it shouldn't have — clean up rpc_call "$session" "package.uninstall" "{\"id\":\"$app_id\"}" > /dev/null 2>&1 || true fail "$app_id — installed without $dep_name (should have been blocked)" fi } container_running() { local session="$1" app_id="$2" local result result=$(rpc_call "$session" "container-list") echo "$result" | grep -q "\"$app_id\"" && return 0 || return 1 } main() { log "=== Dependency Chain Test ===" echo "" log "Authenticating..." local session session=$(get_session) if [ -z "$session" ]; then echo "Failed to authenticate. Exiting." exit 1 fi log "Session: ${session:0:8}..." echo "" # Check current state — which deps are already running local bitcoin_running=false lnd_running=false electrs_running=false fedimint_running=false if container_running "$session" "bitcoin-knots"; then bitcoin_running=true log "bitcoin-knots is already running" fi if container_running "$session" "lnd"; then lnd_running=true log "lnd is already running" fi if container_running "$session" "electrs"; then electrs_running=true log "electrs is already running" fi if container_running "$session" "fedimint"; then fedimint_running=true log "fedimint is already running" fi echo "" # Test 1: electrs requires bitcoin-knots if [ "$bitcoin_running" = false ]; then test_dep_blocked "$session" "electrs" "bitcoin" else log "SKIP: electrs dep test — bitcoin-knots already running" fi # Test 2: btcpay-server requires lnd if [ "$lnd_running" = false ]; then test_dep_blocked "$session" "btcpay-server" "lnd" else log "SKIP: btcpay dep test — lnd already running" fi # Test 3: mempool requires bitcoin-knots + electrs if [ "$bitcoin_running" = false ] || [ "$electrs_running" = false ]; then test_dep_blocked "$session" "mempool" "bitcoin" else log "SKIP: mempool dep test — deps already running" fi echo "" log "=== RESULTS ===" for r in "${RESULTS[@]:-}"; do [ -n "$r" ] && echo " $r" done echo "" log "Pass: $PASS | Fail: $FAIL" [ $FAIL -gt 0 ] && exit 1 exit 0 } main "$@"