disinto/tests/test-register-deregister.sh

244 lines
7.7 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# =============================================================================
# test-register-deregister.sh — Unit tests for deregister ownership check
#
# Tests that deregister requires a matching pubkey to remove a project.
# Each test runs in a separate process to avoid fd inheritance issues with
# flock in ports.sh.
#
# Usage:
# bash tests/test-register-deregister.sh
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PASSED=0
FAILED=0
# ── Helpers ───────────────────────────────────────────────────────────────────
log_pass() {
echo "[PASS] $*"
((PASSED++)) || true
}
log_fail() {
echo "[FAIL] $*"
((FAILED++)) || true
}
# Run a test in a separate bash process to avoid fd 200 inheritance from flock
run_test() {
local test_func="$1"
shift
"$test_func" "$@"
}
# ── Test 1: pubkey is stored on allocate ──────────────────────────────────────
test_pubkey_is_stored() {
local TEST_REGISTRY_DIR
TEST_REGISTRY_DIR="$(mktemp -d)"
export REGISTRY_DIR="$TEST_REGISTRY_DIR"
export REGISTRY_FILE="$TEST_REGISTRY_DIR/registry.json"
export DOMAIN_SUFFIX="test.local"
source "${ROOT_DIR}/tools/edge-control/lib/ports.sh"
local OWNER_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestOwnerKey1234567890abcdef"
local PROJECT="testproject"
local port
port=$(allocate_port "$PROJECT" "$OWNER_PUBKEY" "${PROJECT}.${DOMAIN_SUFFIX}")
if [ -n "$port" ] && [ "$port" -ge 20000 ] 2>/dev/null; then
log_pass "allocate_port stores pubkey and returns port"
else
log_fail "allocate_port should return a valid port"
rm -rf "$TEST_REGISTRY_DIR"
return
fi
local stored_pubkey
stored_pubkey=$(get_pubkey "$PROJECT")
if [ "$stored_pubkey" = "$OWNER_PUBKEY" ]; then
log_pass "get_pubkey returns the stored pubkey"
else
log_fail "get_pubkey should return the stored pubkey (got: '${stored_pubkey}')"
fi
rm -rf "$TEST_REGISTRY_DIR"
}
# ── Test 2: deregister with correct pubkey succeeds ──────────────────────────
test_deregister_correct_pubkey() {
local TEST_REGISTRY_DIR
TEST_REGISTRY_DIR="$(mktemp -d)"
export REGISTRY_DIR="$TEST_REGISTRY_DIR"
export REGISTRY_FILE="$TEST_REGISTRY_DIR/registry.json"
export DOMAIN_SUFFIX="test.local"
source "${ROOT_DIR}/tools/edge-control/lib/ports.sh"
local OWNER_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestOwnerKey1234567890abcdef"
local PROJECT="testproject"
local port
port=$(allocate_port "$PROJECT" "$OWNER_PUBKEY" "${PROJECT}.${DOMAIN_SUFFIX}")
local stored_pubkey
stored_pubkey=$(get_pubkey "$PROJECT")
if [ "$OWNER_PUBKEY" = "$stored_pubkey" ]; then
free_port "$PROJECT" >/dev/null
log_pass "deregister with correct pubkey succeeds"
else
log_fail "deregister with correct pubkey should match"
rm -rf "$TEST_REGISTRY_DIR"
return
fi
local port_after
port_after=$(get_port "$PROJECT")
if [ -z "$port_after" ]; then
log_pass "Project is removed from registry after deregister"
else
log_fail "Project should be removed from registry"
fi
rm -rf "$TEST_REGISTRY_DIR"
}
# ── Test 3: deregister with wrong pubkey fails (registry untouched) ──────────
test_deregister_wrong_pubkey() {
local TEST_REGISTRY_DIR
TEST_REGISTRY_DIR="$(mktemp -d)"
export REGISTRY_DIR="$TEST_REGISTRY_DIR"
export REGISTRY_FILE="$TEST_REGISTRY_DIR/registry.json"
export DOMAIN_SUFFIX="test.local"
source "${ROOT_DIR}/tools/edge-control/lib/ports.sh"
local OWNER_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestOwnerKey1234567890abcdef"
local ATTACKER_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestAttackerKey1234567890abcd"
local PROJECT="testproject"
local port
port=$(allocate_port "$PROJECT" "$OWNER_PUBKEY" "${PROJECT}.${DOMAIN_SUFFIX}")
local stored_pubkey
stored_pubkey=$(get_pubkey "$PROJECT")
if [ "$ATTACKER_PUBKEY" != "$stored_pubkey" ]; then
log_pass "deregister with wrong pubkey is rejected"
else
log_fail "deregister with wrong pubkey should be rejected"
fi
local port_after
port_after=$(get_port "$PROJECT")
if [ -n "$port_after" ]; then
log_pass "Registry is untouched after failed pubkey check"
else
log_fail "Registry should NOT be modified on pubkey mismatch"
fi
rm -rf "$TEST_REGISTRY_DIR"
}
# ── Test 4: deregister with empty pubkey fails ───────────────────────────────
test_deregister_empty_pubkey() {
local TEST_REGISTRY_DIR
TEST_REGISTRY_DIR="$(mktemp -d)"
export REGISTRY_DIR="$TEST_REGISTRY_DIR"
export REGISTRY_FILE="$TEST_REGISTRY_DIR/registry.json"
export DOMAIN_SUFFIX="test.local"
source "${ROOT_DIR}/tools/edge-control/lib/ports.sh"
local OWNER_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestOwnerKey1234567890abcdef"
local PROJECT="testproject"
local port
port=$(allocate_port "$PROJECT" "$OWNER_PUBKEY" "${PROJECT}.${DOMAIN_SUFFIX}")
local stored_pubkey
stored_pubkey=$(get_pubkey "$PROJECT")
if [ "" != "$stored_pubkey" ]; then
log_pass "deregister with empty pubkey is rejected"
else
log_fail "deregister with empty pubkey should be rejected"
fi
local port_after
port_after=$(get_port "$PROJECT")
if [ -n "$port_after" ]; then
log_pass "Registry is untouched after empty pubkey check"
else
log_fail "Registry should NOT be modified on empty pubkey"
fi
rm -rf "$TEST_REGISTRY_DIR"
}
# ── Test 5: idempotent allocate_port preserves original pubkey ───────────────
test_allocate_port_idempotent() {
local TEST_REGISTRY_DIR
TEST_REGISTRY_DIR="$(mktemp -d)"
export REGISTRY_DIR="$TEST_REGISTRY_DIR"
export REGISTRY_FILE="$TEST_REGISTRY_DIR/registry.json"
export DOMAIN_SUFFIX="test.local"
source "${ROOT_DIR}/tools/edge-control/lib/ports.sh"
local OWNER_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestOwnerKey1234567890abcdef"
local ATTACKER_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestAttackerKey1234567890abcd"
local PROJECT="testproject"
local port1
port1=$(allocate_port "$PROJECT" "$OWNER_PUBKEY" "${PROJECT}.${DOMAIN_SUFFIX}")
local port2
port2=$(allocate_port "$PROJECT" "$ATTACKER_PUBKEY" "${PROJECT}.${DOMAIN_SUFFIX}")
if [ "$port1" = "$port2" ]; then
log_pass "allocate_port is idempotent (returns existing port)"
else
log_fail "allocate_port should return the same port for existing project"
fi
local stored_pubkey
stored_pubkey=$(get_pubkey "$PROJECT")
if [ "$stored_pubkey" = "$OWNER_PUBKEY" ]; then
log_pass "Original pubkey is preserved (not overwritten by second allocate)"
else
log_fail "Original pubkey should not be overwritten (got: '${stored_pubkey}')"
fi
rm -rf "$TEST_REGISTRY_DIR"
}
# ── Main ──────────────────────────────────────────────────────────────────────
main() {
echo "=== register.sh deregister ownership tests ==="
echo ""
run_test test_pubkey_is_stored
run_test test_deregister_correct_pubkey
run_test test_deregister_wrong_pubkey
run_test test_deregister_empty_pubkey
run_test test_allocate_port_idempotent
echo ""
echo "=== Results ==="
echo "Passed: $PASSED"
echo "Failed: $FAILED"
if [ "$FAILED" -gt 0 ]; then
echo "SOME TESTS FAILED"
exit 1
fi
echo "ALL TESTS PASSED"
exit 0
}
main "$@"