fix: migrate PaperMC to v3 API, fix NeoForge beta fallback, add test suite
- Migrate Paper loader from sunset v2 API to v3 (fill.papermc.io) - Fix NeoForge: fall back to beta versions when no stable exists (set -e + grep) - Fix setEula/setperms ordering (was writing eula.txt before /data was writable) - Fix setEula/serverInfoWrite to use absolute paths (/data/server/) - Add VOLUME directive removal (was shadowing bind mounts) - Add comprehensive API test suite (110 tests across 6 suites) - Move test.sh to tests/integration.sh, switch to named volumes - Add Docker build cache to CI workflows - Add .editorconfig, expand .gitignore, improve README docs
This commit is contained in:
Executable
+252
@@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tests for Bedrock Dedicated Server download API
|
||||
# Covers: Primary API, fallback API, version parsing
|
||||
# Usage: ./tests/test_bedrock.sh
|
||||
|
||||
source "$(dirname "$0")/test_utils.sh"
|
||||
|
||||
echo -e "\n${BOLD}Bedrock API Tests${NC}"
|
||||
echo ""
|
||||
|
||||
BEDROCK_API_URL="https://net.web.minecraft-services.net/api/v1.0/download/links"
|
||||
BEDROCK_FALLBACK_URL="https://raw.githubusercontent.com/kittizz/bedrock-server-downloads/refs/heads/main/bedrock-server-downloads.json"
|
||||
|
||||
# ---------- Primary API (minecraft-services.net) ---------------------------
|
||||
|
||||
test_bedrock_primary_api_reachable() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
assert_not_empty "$body" "Bedrock primary API body should not be empty"
|
||||
}
|
||||
|
||||
test_bedrock_primary_api_is_json() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
assert_json_valid "$body" "Primary API response should be valid JSON"
|
||||
}
|
||||
|
||||
test_bedrock_primary_api_has_result() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
assert_json_field "$body" '.result' "Should have .result field"
|
||||
}
|
||||
|
||||
test_bedrock_primary_api_has_links() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
assert_json_field "$body" '.result.links' "Should have .result.links array"
|
||||
}
|
||||
|
||||
test_bedrock_primary_api_links_is_array() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
local type
|
||||
type=$(echo "$body" | jq -r '.result.links | type')
|
||||
assert_equals "$type" "array" ".result.links should be an array"
|
||||
}
|
||||
|
||||
test_bedrock_primary_has_linux_entry() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
local found
|
||||
found=$(echo "$body" | jq -r '.result.links[] | select(.downloadType == "serverBedrockLinux") | .downloadUrl // empty')
|
||||
|
||||
if [[ -n "$found" && "$found" != "null" ]]; then
|
||||
return 0
|
||||
else
|
||||
echo "ASSERT FAILED: No serverBedrockLinux entry found"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_bedrock_primary_linux_url_format() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
local url
|
||||
url=$(echo "$body" | jq -r '.result.links[] | select(.downloadType == "serverBedrockLinux") | .downloadUrl // empty')
|
||||
|
||||
assert_matches "$url" "bedrock-server-.*\.zip$" \
|
||||
"Linux download URL should end with bedrock-server-{version}.zip"
|
||||
}
|
||||
|
||||
test_bedrock_primary_linux_url_reachable() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
local url
|
||||
url=$(echo "$body" | jq -r '.result.links[] | select(.downloadType == "serverBedrockLinux") | .downloadUrl // empty')
|
||||
|
||||
if [[ -z "$url" ]]; then
|
||||
echo "No Linux download URL found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Just check HTTP HEAD to avoid downloading the full zip
|
||||
local http_code
|
||||
http_code=$(curl -sL -o /dev/null -w "%{http_code}" --connect-timeout 10 --max-time 30 \
|
||||
-A "Mozilla/5.0 (X11; Linux x86_64)" -I "$url") || true
|
||||
assert_equals "$http_code" "200" "Bedrock download URL should return HTTP 200"
|
||||
}
|
||||
|
||||
test_bedrock_primary_has_windows_entry() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
local found
|
||||
found=$(echo "$body" | jq -r '.result.links[] | select(.downloadType == "serverBedrockWin") | .downloadUrl // empty')
|
||||
|
||||
if [[ -n "$found" && "$found" != "null" ]]; then
|
||||
return 0
|
||||
else
|
||||
echo "No serverBedrockWin entry found (may be expected on some API versions)"
|
||||
return 77 # skip
|
||||
fi
|
||||
}
|
||||
|
||||
test_bedrock_primary_download_type_values() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
local types
|
||||
types=$(echo "$body" | jq -r '.result.links[].downloadType' | sort -u)
|
||||
|
||||
assert_not_empty "$types" "Should have at least one download type"
|
||||
}
|
||||
|
||||
# ---------- Version parsing from URL ---------------------------------------
|
||||
|
||||
test_bedrock_version_from_url() {
|
||||
local body
|
||||
body=$(api_get_ua "$BEDROCK_API_URL")
|
||||
local url
|
||||
url=$(echo "$body" | jq -r '.result.links[] | select(.downloadType == "serverBedrockLinux") | .downloadUrl // empty')
|
||||
|
||||
if [[ -z "$url" ]]; then
|
||||
echo "No Linux download URL found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Extract version from URL (same regex as bedrock.sh)
|
||||
local ver
|
||||
ver=$(echo "$url" | grep -oP 'bedrock-server-\K[\d.]+(?=\.zip)')
|
||||
assert_not_empty "$ver" "Should extract version from URL"
|
||||
assert_matches "$ver" "^[0-9]+\.[0-9]+\.[0-9]+" \
|
||||
"Version '${ver}' should look like x.y.z"
|
||||
}
|
||||
|
||||
# ---------- Fallback API (GitHub) ------------------------------------------
|
||||
|
||||
test_bedrock_fallback_api_reachable() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
assert_not_empty "$body" "Bedrock fallback API body should not be empty"
|
||||
}
|
||||
|
||||
test_bedrock_fallback_api_is_json() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
assert_json_valid "$body" "Fallback API response should be valid JSON"
|
||||
}
|
||||
|
||||
test_bedrock_fallback_has_release() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
assert_json_field "$body" '.release' "Should have .release field"
|
||||
}
|
||||
|
||||
test_bedrock_fallback_release_is_object() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
local type
|
||||
type=$(echo "$body" | jq -r '.release | type')
|
||||
assert_equals "$type" "object" ".release should be a JSON object"
|
||||
}
|
||||
|
||||
test_bedrock_fallback_release_has_entries() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
local count
|
||||
count=$(echo "$body" | jq '.release | length')
|
||||
if [[ "$count" -gt 0 ]]; then
|
||||
return 0
|
||||
else
|
||||
echo "ASSERT FAILED: .release should have entries, got ${count}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_bedrock_fallback_entry_has_linux_url() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
local first_key
|
||||
first_key=$(echo "$body" | jq -r '.release | keys | .[0]')
|
||||
local url
|
||||
url=$(echo "$body" | jq -r ".release[\"${first_key}\"].linux.url // empty")
|
||||
|
||||
assert_not_empty "$url" "First release entry should have .linux.url"
|
||||
}
|
||||
|
||||
test_bedrock_fallback_linux_url_format() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
local first_key
|
||||
first_key=$(echo "$body" | jq -r '.release | keys | .[0]')
|
||||
local url
|
||||
url=$(echo "$body" | jq -r ".release[\"${first_key}\"].linux.url // empty")
|
||||
|
||||
assert_matches "$url" "bedrock-server-.*\.zip$" \
|
||||
"Fallback URL should end with bedrock-server-{version}.zip"
|
||||
}
|
||||
|
||||
test_bedrock_fallback_highest_version() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
# The script sorts by version and takes the last (highest) entry
|
||||
local highest
|
||||
highest=$(echo "$body" | jq -r '
|
||||
.release | to_entries | sort_by(.key | split(".") | map(tonumber)) | last | .key
|
||||
')
|
||||
|
||||
assert_not_empty "$highest" "Should find a highest version"
|
||||
assert_matches "$highest" "^[0-9]+\.[0-9]+\.[0-9]+" \
|
||||
"Highest version '${highest}' should look like x.y.z"
|
||||
}
|
||||
|
||||
# ---------- Preview entry --------------------------------------------------
|
||||
|
||||
test_bedrock_fallback_has_preview() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
assert_json_field "$body" '.preview' "Should have .preview field"
|
||||
}
|
||||
|
||||
test_bedrock_fallback_preview_is_object() {
|
||||
local body
|
||||
body=$(api_get "$BEDROCK_FALLBACK_URL")
|
||||
local type
|
||||
type=$(echo "$body" | jq -r '.preview | type')
|
||||
assert_equals "$type" "object" ".preview should be a JSON object"
|
||||
}
|
||||
|
||||
# ---------- Run all tests --------------------------------------------------
|
||||
|
||||
run_test "Primary API is reachable" test_bedrock_primary_api_reachable
|
||||
run_test "Primary API response is valid JSON" test_bedrock_primary_api_is_json
|
||||
run_test "Primary API has .result field" test_bedrock_primary_api_has_result
|
||||
run_test "Primary API has .result.links" test_bedrock_primary_api_has_links
|
||||
run_test ".result.links is an array" test_bedrock_primary_api_links_is_array
|
||||
run_test "Has serverBedrockLinux entry" test_bedrock_primary_has_linux_entry
|
||||
run_test "Linux download URL has correct format" test_bedrock_primary_linux_url_format
|
||||
run_test "Linux download URL returns HTTP 200" test_bedrock_primary_linux_url_reachable
|
||||
run_test "Has serverBedrockWin entry" test_bedrock_primary_has_windows_entry
|
||||
run_test "Download types are present" test_bedrock_primary_download_type_values
|
||||
run_test "Version can be parsed from download URL" test_bedrock_version_from_url
|
||||
run_test "Fallback API (GitHub) is reachable" test_bedrock_fallback_api_reachable
|
||||
run_test "Fallback API response is valid JSON" test_bedrock_fallback_api_is_json
|
||||
run_test "Fallback has .release field" test_bedrock_fallback_has_release
|
||||
run_test ".release is a JSON object" test_bedrock_fallback_release_is_object
|
||||
run_test ".release has entries" test_bedrock_fallback_release_has_entries
|
||||
run_test "First release entry has .linux.url" test_bedrock_fallback_entry_has_linux_url
|
||||
run_test "Fallback URL has correct format" test_bedrock_fallback_linux_url_format
|
||||
run_test "Fallback has a highest version" test_bedrock_fallback_highest_version
|
||||
run_test "Fallback has .preview field" test_bedrock_fallback_has_preview
|
||||
run_test ".preview is a JSON object" test_bedrock_fallback_preview_is_object
|
||||
|
||||
print_summary
|
||||
Reference in New Issue
Block a user