#!/usr/bin/env bash set -euo pipefail usage() { cat < Minecraft version (default: auto-detect latest) -l, --loader Loader to test (default: all) -v, --loader-version Loader version (default: auto-detect latest) -t, --timeout Max wait for server jar (default: 180) -h, --help Show this help Examples: $(basename "$0") Test all loaders (latest MC) $(basename "$0") -m 1.21.1 Test all loaders on MC 1.21.1 $(basename "$0") -m 1.21.1 -l fabric Test Fabric on MC 1.21.1 $(basename "$0") -m 1.21.1 -l fabric -v 0.19.3 Test Fabric 0.19.3 on MC 1.21.1 Loaders: vanilla paper fabric forge neoforge bedrock EOF exit 0 } detect_mc_version() { curl -sf --connect-timeout 10 --max-time 30 \ "https://launchermeta.mojang.com/mc/game/version_manifest.json" | jq -r '.latest.release' } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" IMAGE="dockercraft-test:latest" MC_VERSION="" LOADER="" LOADER_VERSION="" TIMEOUT=180 PASS=0 FAIL=0 while [[ $# -gt 0 ]]; do case "$1" in -h|--help) usage ;; -m|--mc-version) MC_VERSION="$2"; shift 2 ;; -l|--loader) LOADER="$2"; shift 2 ;; -v|--loader-version) LOADER_VERSION="$2"; shift 2 ;; -t|--timeout) TIMEOUT="$2"; shift 2 ;; *) echo "Unknown option: $1"; usage ;; esac done if [[ -z "$MC_VERSION" ]]; then echo "Detecting latest Minecraft version..." MC_VERSION=$(detect_mc_version) echo " -> ${MC_VERSION}" fi if [[ -z "$LOADER" ]]; then tests=("vanilla" "paper" "fabric" "forge" "neoforge" "bedrock") else tests=("$LOADER") fi cleanup() { local name="$1" docker kill "dc-test-${name}" 2>/dev/null || true docker rm "dc-test-${name}" 2>/dev/null || true docker volume rm "dc-test-vol-${name}" 2>/dev/null || true } run_test() { local name="$1" shift echo "=== Testing: ${name} ===" cleanup "$name" # Use a named volume instead of a bind mount (avoids host filesystem quirks) docker volume create "dc-test-vol-${name}" >/dev/null local CONTAINER_ID if CONTAINER_ID=$(docker run -d --name "dc-test-${name}" \ -e EULA=true \ -e MC_VERSION="${MC_VERSION}" \ "$@" \ -v "dc-test-vol-${name}:/data" \ "${IMAGE}" 2>&1); then local waited=0 local jar_found=false while [[ $waited -lt $TIMEOUT ]]; do # Check inside the container for the server binary if docker exec "dc-test-${name}" test -f /data/server/server.jar 2>/dev/null || \ docker exec "dc-test-${name}" find /data/server -name 'forge-*-server.jar' 2>/dev/null | grep -q . || \ docker exec "dc-test-${name}" test -f /data/server/bedrock_server 2>/dev/null; then jar_found=true break fi sleep 3 waited=$((waited + 3)) echo -n "." done echo "" if $jar_found; then if docker exec "dc-test-${name}" test -f /data/server/bedrock_server 2>/dev/null; then echo " PASS (bedrock_server found in ~${waited}s)" else echo " PASS (server jar found in ~${waited}s)" fi PASS=$((PASS + 1)) else echo "" echo " FAIL: server binary not found after ${TIMEOUT}s" echo " --- container logs ---" docker logs "dc-test-${name}" 2>&1 | tail -50 || true echo " ---------------------" FAIL=$((FAIL + 1)) fi else echo "" echo " FAIL: container failed to start" echo " ${CONTAINER_ID}" FAIL=$((FAIL + 1)) fi cleanup "$name" } echo "Building image..." DOCKER_BUILDKIT=0 docker build -t "${IMAGE}" "${PROJECT_ROOT}" for t in "${tests[@]}"; do case $t in vanilla) run_test "vanilla" -e MC_LOADER=vanilla ;; paper) run_test "paper" -e MC_LOADER=paper ;; fabric) run_test "fabric" \ -e MC_LOADER=fabric \ -e FABRIC_LOADER_VERSION="${LOADER_VERSION}" ;; forge) run_test "forge" \ -e MC_LOADER=forge \ -e FORGE_VERSION="${LOADER_VERSION}" ;; neoforge) run_test "neoforge" \ -e MC_LOADER=neoforge \ -e NEOFORGE_VERSION="${LOADER_VERSION}" ;; bedrock) run_test "bedrock" \ -e MC_LOADER=bedrock \ -e MC_VERSION= ;; *) echo "Unknown loader: ${t}" echo "Valid: vanilla paper fabric forge neoforge bedrock" exit 1 ;; esac done echo "" echo "Results: ${PASS} passed, ${FAIL} failed" [[ $FAIL -eq 0 ]]