Update test.sh
This commit is contained in:
663
test.sh
663
test.sh
@@ -1,583 +1,318 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
# Configuration
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
|
||||||
TEST_DIR="${SCRIPT_DIR}/test_tmp"
|
TEST_DIR="${SCRIPT_DIR}/test_tmp"
|
||||||
TEST_TOKEN="test-token-$(date +%s)"
|
TEST_TOKEN="test-token-$(date +%s)"
|
||||||
CONTAINER_NAME="sos-test-$(date +%s)"
|
CONTAINER_NAME="sos-test-$(date +%s)"
|
||||||
TEST_PORT="" # Will be set dynamically after container starts
|
IMAGE="gitea.jde.nz/public/simple-object-server:latest"
|
||||||
|
TEST_PORT=""
|
||||||
|
SOS_TEST_HOST=""
|
||||||
CLEANUP_NEEDED=false
|
CLEANUP_NEEDED=false
|
||||||
|
|
||||||
# Colors for output
|
# Colors
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m'
|
||||||
|
|
||||||
function log_info() {
|
# Logging functions
|
||||||
echo -e "${GREEN}[INFO]${NC} $1"
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }
|
||||||
|
log_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
die() { log_error "$@"; exit 1; }
|
||||||
|
|
||||||
|
# Cleanup on exit
|
||||||
|
cleanup() {
|
||||||
|
[[ "$CLEANUP_NEEDED" != true ]] && return
|
||||||
|
log_info "Cleaning up test environment..."
|
||||||
|
docker stop "${CONTAINER_NAME}" &>/dev/null || true
|
||||||
|
docker rm "${CONTAINER_NAME}" &>/dev/null || true
|
||||||
|
rm -rf "${TEST_DIR}"
|
||||||
|
log_info "Cleanup complete"
|
||||||
}
|
}
|
||||||
|
|
||||||
function log_error() {
|
|
||||||
echo -e "${RED}[ERROR]${NC} $1" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
function log_warning() {
|
|
||||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanup() {
|
|
||||||
if [ "$CLEANUP_NEEDED" = true ]; then
|
|
||||||
log_info "Cleaning up test environment..."
|
|
||||||
|
|
||||||
# Stop and remove container
|
|
||||||
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
||||||
docker stop "${CONTAINER_NAME}" >/dev/null 2>&1 || true
|
|
||||||
docker rm "${CONTAINER_NAME}" >/dev/null 2>&1 || true
|
|
||||||
log_info "Removed test container"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clean up test directory
|
|
||||||
if [ -d "${TEST_DIR}" ]; then
|
|
||||||
rm -rf "${TEST_DIR}"
|
|
||||||
log_info "Removed test directory"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
function die() {
|
# Check dependencies
|
||||||
log_error "$@"
|
check_dependencies() {
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_dependencies() {
|
|
||||||
log_info "Checking dependencies..."
|
log_info "Checking dependencies..."
|
||||||
|
for cmd in docker jq curl; do
|
||||||
# Check for Docker
|
command -v $cmd &>/dev/null || die "$cmd is required but not installed"
|
||||||
if ! command -v docker &> /dev/null; then
|
done
|
||||||
die "Docker is required but not installed"
|
docker info &>/dev/null || die "Docker daemon is not running"
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for jq
|
|
||||||
if ! command -v jq &> /dev/null; then
|
|
||||||
die "jq is required but not installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for curl
|
|
||||||
if ! command -v curl &> /dev/null; then
|
|
||||||
die "curl is required but not installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check Docker daemon is running
|
|
||||||
if ! docker info >/dev/null 2>&1; then
|
|
||||||
die "Docker daemon is not running"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "All dependencies satisfied"
|
log_info "All dependencies satisfied"
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup_test_environment() {
|
# Setup test environment
|
||||||
|
setup_test_environment() {
|
||||||
log_info "Setting up test environment..."
|
log_info "Setting up test environment..."
|
||||||
CLEANUP_NEEDED=true
|
CLEANUP_NEEDED=true
|
||||||
|
|
||||||
# Create test directory structure
|
# Create directories
|
||||||
rm -rf "${TEST_DIR}"
|
rm -rf "${TEST_DIR}"
|
||||||
mkdir -p "${TEST_DIR}/test_files"
|
mkdir -p "${TEST_DIR}"/{test_files,config}
|
||||||
mkdir -p "${TEST_DIR}/config"
|
|
||||||
|
|
||||||
# Generate hashed token
|
# Generate hashed token for authentication
|
||||||
log_info "Generating authentication token..."
|
log_info "Generating authentication token..."
|
||||||
HASHED_TOKEN=$(docker run --rm gitea.jde.nz/public/simple-object-server:latest /sos/hash_token "${TEST_TOKEN}" 2>/dev/null | grep '^\$2[aby]\$' | head -1)
|
local hashed_token=$(docker run --rm "$IMAGE" /sos/hash_token "${TEST_TOKEN}" 2>/dev/null | grep '^\$2[aby]\$' | head -1)
|
||||||
|
[[ -z "$hashed_token" ]] && die "Failed to generate hashed token"
|
||||||
|
|
||||||
if [ -z "${HASHED_TOKEN}" ]; then
|
# Create config
|
||||||
die "Failed to generate hashed token"
|
echo "{\"write_tokens\": [\"${hashed_token}\"]}" > "${TEST_DIR}/config/sos_config.json"
|
||||||
fi
|
|
||||||
|
|
||||||
# Create test configuration in config directory
|
|
||||||
cat > "${TEST_DIR}/config/sos_config.json" <<EOF
|
|
||||||
{
|
|
||||||
"write_tokens": ["${HASHED_TOKEN}"]
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
log_info "Created test configuration"
|
|
||||||
|
|
||||||
# Create test files
|
# Create test files
|
||||||
echo "This is test file 1" > "${TEST_DIR}/test_files/test1.txt"
|
echo "This is test file 1" > "${TEST_DIR}/test_files/test1.txt"
|
||||||
echo "This is test file 2 with more content" > "${TEST_DIR}/test_files/test2.txt"
|
echo "This is test file 2 with more content" > "${TEST_DIR}/test_files/test2.txt"
|
||||||
dd if=/dev/urandom of="${TEST_DIR}/test_files/binary_test.bin" bs=1024 count=10 2>/dev/null
|
dd if=/dev/urandom of="${TEST_DIR}/test_files/binary_test.bin" bs=1024 count=10 &>/dev/null
|
||||||
|
|
||||||
# Create the sos binary for testing
|
|
||||||
cp "${SCRIPT_DIR}/sos" "${TEST_DIR}/test_files/sos_binary"
|
cp "${SCRIPT_DIR}/sos" "${TEST_DIR}/test_files/sos_binary"
|
||||||
|
|
||||||
log_info "Created test files"
|
log_info "Test environment ready"
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_test_server() {
|
# Start and configure test server
|
||||||
|
start_test_server() {
|
||||||
log_info "Starting SOS test server..."
|
log_info "Starting SOS test server..."
|
||||||
|
|
||||||
# Pull the latest image
|
# Pull latest image
|
||||||
log_info "Pulling latest simple-object-server image..."
|
docker pull "$IMAGE" &>/dev/null || log_warning "Using cached image"
|
||||||
docker pull gitea.jde.nz/public/simple-object-server:latest
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
log_warning "Failed to pull latest image, using cached version if available"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure the config file exists and is readable
|
# Start container with dynamic port
|
||||||
if [ ! -f "${TEST_DIR}/config/sos_config.json" ]; then
|
local container_id=$(docker run -d --name "${CONTAINER_NAME}" -p 80 "$IMAGE" 2>&1)
|
||||||
die "Config file ${TEST_DIR}/config/sos_config.json does not exist"
|
[[ $? -ne 0 ]] && die "Failed to start container: ${container_id}"
|
||||||
fi
|
|
||||||
|
|
||||||
# Start the container without specifying host port (Docker will assign one)
|
log_info "Container started: ${container_id:0:12}"
|
||||||
# No volume mounts - will use docker cp/exec for file operations
|
|
||||||
local container_id=$(docker run -d \
|
|
||||||
--name "${CONTAINER_NAME}" \
|
|
||||||
-p 80 \
|
|
||||||
gitea.jde.nz/public/simple-object-server:latest 2>&1)
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
# Get assigned port
|
||||||
log_error "Failed to start container: ${container_id}"
|
|
||||||
die "Failed to start test server"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "Container started with ID: ${container_id:0:12}"
|
|
||||||
|
|
||||||
# Get the dynamically assigned port
|
|
||||||
TEST_PORT=$(docker port "${CONTAINER_NAME}" 80 | cut -d: -f2)
|
TEST_PORT=$(docker port "${CONTAINER_NAME}" 80 | cut -d: -f2)
|
||||||
if [ -z "${TEST_PORT}" ]; then
|
[[ -z "$TEST_PORT" ]] && die "Failed to get container port"
|
||||||
log_error "Failed to get container port"
|
log_info "Container port: ${TEST_PORT}"
|
||||||
die "Failed to get container port mapping"
|
|
||||||
fi
|
|
||||||
log_info "Container mapped to port: ${TEST_PORT}"
|
|
||||||
|
|
||||||
# Copy the config file into the container using docker cp
|
# Copy config and restart (for Docker-in-Docker compatibility)
|
||||||
log_info "Copying config file into container..."
|
docker cp "${TEST_DIR}/config/sos_config.json" "${CONTAINER_NAME}:/data/sos_config.json" || die "Failed to copy config"
|
||||||
docker cp "${TEST_DIR}/config/sos_config.json" "${CONTAINER_NAME}:/data/sos_config.json"
|
docker exec "${CONTAINER_NAME}" mkdir -p /data/storage 2>/dev/null || true
|
||||||
if [ $? -ne 0 ]; then
|
docker restart "${CONTAINER_NAME}" &>/dev/null || die "Failed to restart container"
|
||||||
log_error "Failed to copy config file into container"
|
|
||||||
docker logs "${CONTAINER_NAME}" 2>&1
|
|
||||||
die "Failed to copy config file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure storage directory exists in container
|
sleep 3 # Wait for restart
|
||||||
docker exec "${CONTAINER_NAME}" mkdir -p /data/storage
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
log_warning "Could not create storage directory (may already exist)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Restart the container to pick up the config file
|
# Update port if changed after restart
|
||||||
log_info "Restarting container to load config..."
|
|
||||||
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
log_error "Failed to restart container"
|
|
||||||
die "Failed to restart container"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Give container more time to initialize after restart
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# Verify port mapping after restart (it might change)
|
|
||||||
local new_port=$(docker port "${CONTAINER_NAME}" 80 | cut -d: -f2)
|
local new_port=$(docker port "${CONTAINER_NAME}" 80 | cut -d: -f2)
|
||||||
if [ -z "${new_port}" ]; then
|
[[ -z "$new_port" ]] && die "Lost port mapping after restart"
|
||||||
log_error "Lost port mapping after restart"
|
[[ "$new_port" != "$TEST_PORT" ]] && TEST_PORT="$new_port" && log_info "Port updated: ${TEST_PORT}"
|
||||||
docker logs "${CONTAINER_NAME}" 2>&1 | tail -20
|
|
||||||
die "Container port mapping lost after restart"
|
|
||||||
fi
|
|
||||||
if [ "${new_port}" != "${TEST_PORT}" ]; then
|
|
||||||
log_info "Port changed after restart: ${TEST_PORT} -> ${new_port}"
|
|
||||||
TEST_PORT="${new_port}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get container IP address for Docker-in-Docker environments
|
# Get network details for connectivity
|
||||||
CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${CONTAINER_NAME}")
|
local container_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${CONTAINER_NAME}")
|
||||||
if [ -z "${CONTAINER_IP}" ]; then
|
local host_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' "${CONTAINER_NAME}")
|
||||||
log_warning "Could not get container IP, will use localhost"
|
|
||||||
CONTAINER_IP="localhost"
|
|
||||||
else
|
|
||||||
log_info "Container IP address: ${CONTAINER_IP}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try to get the Docker host IP (gateway) for Docker-in-Docker
|
# Wait for server readiness and determine connection method
|
||||||
HOST_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' "${CONTAINER_NAME}")
|
wait_for_server "$container_ip" "$host_ip"
|
||||||
if [ -n "${HOST_IP}" ]; then
|
|
||||||
log_info "Docker host IP (gateway): ${HOST_IP}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if container is still running
|
|
||||||
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
||||||
log_error "Container stopped unexpectedly. Logs:"
|
|
||||||
docker logs "${CONTAINER_NAME}" 2>&1
|
|
||||||
|
|
||||||
# Additional debugging for CI environment
|
|
||||||
log_error "Debug: Checking /data directory in container:"
|
|
||||||
docker exec "${CONTAINER_NAME}" ls -la /data/ 2>&1 || true
|
|
||||||
log_error "Debug: Config file in container:"
|
|
||||||
docker exec "${CONTAINER_NAME}" cat /data/sos_config.json 2>&1 || true
|
|
||||||
|
|
||||||
die "Container failed to stay running"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wait for server to be ready
|
|
||||||
log_info "Waiting for server to be ready..."
|
|
||||||
local max_attempts=60
|
|
||||||
local attempt=0
|
|
||||||
|
|
||||||
while [ $attempt -lt $max_attempts ]; do
|
|
||||||
# Try multiple connection methods for different environments
|
|
||||||
local http_code="000"
|
|
||||||
local container_code="000"
|
|
||||||
local host_code="000"
|
|
||||||
local local_code="000"
|
|
||||||
|
|
||||||
# Try direct container IP on port 80 (might work in some Docker setups)
|
|
||||||
if [ "${CONTAINER_IP}" != "localhost" ]; then
|
|
||||||
container_code=$(curl -s --max-time 2 -o /dev/null -w "%{http_code}" "http://${CONTAINER_IP}:80/" 2>/dev/null || echo "000")
|
|
||||||
if [ "$container_code" != "000" ] && [ "$container_code" != "" ]; then
|
|
||||||
http_code="$container_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try host IP with mapped port (Docker-in-Docker)
|
|
||||||
if [ -n "${HOST_IP}" ]; then
|
|
||||||
host_code=$(curl -s --max-time 2 -o /dev/null -w "%{http_code}" "http://${HOST_IP}:${TEST_PORT}/" 2>/dev/null || echo "000")
|
|
||||||
if [ "$host_code" != "000" ] && [ "$host_code" != "" ]; then
|
|
||||||
http_code="$host_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try localhost with mapped port (local Docker)
|
|
||||||
local_code=$(curl -s --max-time 2 -o /dev/null -w "%{http_code}" "http://localhost:${TEST_PORT}/" 2>/dev/null || echo "000")
|
|
||||||
if [ "$local_code" != "000" ] && [ "$local_code" != "" ]; then
|
|
||||||
http_code="$local_code"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Debug: Show HTTP codes from all attempts on first few tries
|
|
||||||
if [ $attempt -lt 3 ]; then
|
|
||||||
log_info "Health check attempt $((attempt + 1)):"
|
|
||||||
log_info " Container IP (${CONTAINER_IP}:80): ${container_code}"
|
|
||||||
log_info " Host IP (${HOST_IP}:${TEST_PORT}): ${host_code}"
|
|
||||||
log_info " Localhost (localhost:${TEST_PORT}): ${local_code}"
|
|
||||||
# Check if container is actually running
|
|
||||||
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
||||||
log_info "Container is running, checking logs..."
|
|
||||||
docker logs "${CONTAINER_NAME}" 2>&1 | tail -5
|
|
||||||
else
|
|
||||||
log_error "Container is not running!"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if any method succeeded
|
|
||||||
if [ "$container_code" = "200" ] || [ "$container_code" = "204" ] || [ "$container_code" = "404" ]; then
|
|
||||||
export SOS_TEST_HOST="${CONTAINER_IP}:80"
|
|
||||||
log_info "Server is ready! Using container IP: ${SOS_TEST_HOST}"
|
|
||||||
return 0
|
|
||||||
elif [ "$host_code" = "200" ] || [ "$host_code" = "204" ] || [ "$host_code" = "404" ]; then
|
|
||||||
export SOS_TEST_HOST="${HOST_IP}:${TEST_PORT}"
|
|
||||||
log_info "Server is ready! Using host IP: ${SOS_TEST_HOST}"
|
|
||||||
return 0
|
|
||||||
elif [ "$local_code" = "200" ] || [ "$local_code" = "204" ] || [ "$local_code" = "404" ]; then
|
|
||||||
export SOS_TEST_HOST="localhost:${TEST_PORT}"
|
|
||||||
log_info "Server is ready! Using localhost: ${SOS_TEST_HOST}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check container is still running every 5 attempts
|
|
||||||
if [ $((attempt % 5)) -eq 0 ]; then
|
|
||||||
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
||||||
log_error "Container stopped while waiting. Logs:"
|
|
||||||
docker logs "${CONTAINER_NAME}" 2>&1 | tail -20
|
|
||||||
die "Container stopped unexpectedly"
|
|
||||||
fi
|
|
||||||
# Show progress every 5 seconds
|
|
||||||
if [ $attempt -gt 0 ]; then
|
|
||||||
log_info "Still waiting for server... (${attempt}/${max_attempts})"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
sleep 1
|
|
||||||
attempt=$((attempt + 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
log_error "Server did not become ready. Container logs:"
|
|
||||||
docker logs "${CONTAINER_NAME}" 2>&1 | tail -20
|
|
||||||
die "Server failed to start after ${max_attempts} seconds"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_upload() {
|
# Wait for server and determine connection method
|
||||||
|
wait_for_server() {
|
||||||
|
local container_ip="${1:-}"
|
||||||
|
local host_ip="${2:-}"
|
||||||
|
|
||||||
|
log_info "Waiting for server readiness..."
|
||||||
|
|
||||||
|
for attempt in {1..60}; do
|
||||||
|
# Try all connection methods
|
||||||
|
local container_code=$(curl -s --max-time 2 -o /dev/null -w "%{http_code}" "http://${container_ip}:80/" 2>/dev/null || echo "000")
|
||||||
|
local host_code=$(curl -s --max-time 2 -o /dev/null -w "%{http_code}" "http://${host_ip}:${TEST_PORT}/" 2>/dev/null || echo "000")
|
||||||
|
local local_code=$(curl -s --max-time 2 -o /dev/null -w "%{http_code}" "http://localhost:${TEST_PORT}/" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
# Debug first attempts
|
||||||
|
if [[ $attempt -le 3 ]]; then
|
||||||
|
log_info "Health check #${attempt}: container=${container_code}, host=${host_code}, localhost=${local_code}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check which method works
|
||||||
|
if [[ "$container_code" =~ ^(200|204|404)$ ]]; then
|
||||||
|
export SOS_TEST_HOST="${container_ip}:80"
|
||||||
|
log_info "Server ready! Using container IP: ${SOS_TEST_HOST}"
|
||||||
|
return 0
|
||||||
|
elif [[ "$host_code" =~ ^(200|204|404)$ ]]; then
|
||||||
|
export SOS_TEST_HOST="${host_ip}:${TEST_PORT}"
|
||||||
|
log_info "Server ready! Using host IP: ${SOS_TEST_HOST}"
|
||||||
|
return 0
|
||||||
|
elif [[ "$local_code" =~ ^(200|204|404)$ ]]; then
|
||||||
|
export SOS_TEST_HOST="localhost:${TEST_PORT}"
|
||||||
|
log_info "Server ready! Using localhost: ${SOS_TEST_HOST}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Progress indicator
|
||||||
|
[[ $((attempt % 10)) -eq 0 ]] && log_info "Still waiting... (${attempt}/60)"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
die "Server failed to become ready after 60 seconds"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute SOS upload command
|
||||||
|
run_sos_upload() {
|
||||||
|
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
||||||
|
export SOS_WRITE_TOKEN="${TEST_TOKEN}"
|
||||||
|
export SOS_TEST_MODE=1
|
||||||
|
"${SCRIPT_DIR}/sos" upload "$host" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test functions
|
||||||
|
test_upload() {
|
||||||
local file="$1"
|
local file="$1"
|
||||||
local label="$2"
|
local label="$2"
|
||||||
shift 2
|
shift 2
|
||||||
local extra_labels="$@"
|
|
||||||
|
|
||||||
log_info "Testing upload: ${file} with label ${label}"
|
log_info "Testing upload: ${file##*/} with label ${label}"
|
||||||
|
|
||||||
export SOS_WRITE_TOKEN="${TEST_TOKEN}"
|
if run_sos_upload "$file" "$label" "$@" 2>&1 | tee "${TEST_DIR}/upload_output.txt" | grep -q "Download URL:"; then
|
||||||
# Override to use HTTP for local testing
|
log_info "Upload successful"
|
||||||
export SOS_TEST_MODE=1
|
|
||||||
# Use the determined host (either container IP or localhost)
|
|
||||||
local test_host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
|
||||||
# For container IP, we use IP:80 directly, for localhost we use localhost:port
|
|
||||||
if [[ "${test_host}" == *":"* ]]; then
|
|
||||||
# Has port, use as is
|
|
||||||
"${SCRIPT_DIR}/sos" upload "${test_host}" "${file}" "${label}" ${extra_labels} 2>&1 | tee "${TEST_DIR}/upload_output.txt"
|
|
||||||
else
|
|
||||||
# No port, shouldn't happen but handle it
|
|
||||||
"${SCRIPT_DIR}/sos" upload "${test_host}:80" "${file}" "${label}" ${extra_labels} 2>&1 | tee "${TEST_DIR}/upload_output.txt"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ${PIPESTATUS[0]} -ne 0 ]; then
|
|
||||||
log_error "Upload failed for ${file}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Verify upload was successful
|
|
||||||
if grep -q "Download URL:" "${TEST_DIR}/upload_output.txt"; then
|
|
||||||
log_info "Upload successful for ${file}"
|
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
log_error "Upload verification failed for ${file}"
|
log_error "Upload failed"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_retrieval() {
|
test_retrieval() {
|
||||||
local identifier="$1"
|
local identifier="$1"
|
||||||
local expected_content="$2"
|
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
||||||
|
|
||||||
log_info "Testing retrieval by ${identifier}"
|
log_info "Testing retrieval: ${identifier}"
|
||||||
|
|
||||||
# Try to retrieve the file using the determined host
|
local response=$(curl -s "http://${host}/${identifier}")
|
||||||
local test_host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
[[ -z "$response" ]] && log_error "Retrieval failed" && return 1
|
||||||
local response=$(curl -s "http://${test_host}/${identifier}")
|
|
||||||
|
|
||||||
if [ -z "${response}" ]; then
|
# For hash identifiers, also test metadata endpoint
|
||||||
log_error "Failed to retrieve by ${identifier}"
|
if [[ "$identifier" =~ ^[a-f0-9]{64}$ ]]; then
|
||||||
return 1
|
curl -s "http://${host}/meta/${identifier}" | jq -e '.metadata' &>/dev/null || {
|
||||||
fi
|
log_error "Metadata retrieval failed"
|
||||||
|
|
||||||
# For hash retrieval, test the actual hash endpoint
|
|
||||||
if [[ "${identifier}" =~ ^[a-f0-9]{64}$ ]]; then
|
|
||||||
local meta_response=$(curl -s "http://${test_host}/meta/${identifier}")
|
|
||||||
if echo "${meta_response}" | jq -e '.metadata' >/dev/null 2>&1; then
|
|
||||||
log_info "Successfully retrieved metadata for hash ${identifier}"
|
|
||||||
else
|
|
||||||
log_error "Failed to retrieve metadata for hash ${identifier}"
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log_info "Retrieval successful for ${identifier}"
|
log_info "Retrieval successful"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_duplicate_upload() {
|
test_deduplication() {
|
||||||
log_info "Testing duplicate file upload (deduplication)..."
|
log_info "Testing deduplication..."
|
||||||
|
|
||||||
# Create a duplicate file with different name
|
# Create duplicate file
|
||||||
cp "${TEST_DIR}/test_files/test1.txt" "${TEST_DIR}/test_files/test1_dup.txt"
|
cp "${TEST_DIR}/test_files/test1.txt" "${TEST_DIR}/test_files/test1_dup.txt"
|
||||||
|
|
||||||
export SOS_WRITE_TOKEN="${TEST_TOKEN}"
|
# Upload original and duplicate
|
||||||
export SOS_TEST_MODE=1
|
run_sos_upload "${TEST_DIR}/test_files/test1.txt" "dup:original" &>/dev/null
|
||||||
|
local output=$(run_sos_upload "${TEST_DIR}/test_files/test1_dup.txt" "dup:copy" 2>&1)
|
||||||
|
|
||||||
# Use the determined host
|
if echo "$output" | grep -q "File already exists, skipping upload"; then
|
||||||
local test_host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
log_info "Deduplication working"
|
||||||
|
|
||||||
# Upload original
|
|
||||||
"${SCRIPT_DIR}/sos" upload "${test_host}" "${TEST_DIR}/test_files/test1.txt" "dup:original" >/dev/null 2>&1
|
|
||||||
|
|
||||||
# Upload duplicate (should detect existing file)
|
|
||||||
local output=$("${SCRIPT_DIR}/sos" upload "${test_host}" "${TEST_DIR}/test_files/test1_dup.txt" "dup:copy" 2>&1)
|
|
||||||
|
|
||||||
if echo "${output}" | grep -q "File already exists, skipping upload"; then
|
|
||||||
log_info "Deduplication working correctly"
|
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
log_error "Deduplication test failed"
|
log_error "Deduplication failed"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_metadata_update() {
|
test_metadata_update() {
|
||||||
log_info "Testing metadata update..."
|
log_info "Testing metadata update..."
|
||||||
|
|
||||||
export SOS_WRITE_TOKEN="${TEST_TOKEN}"
|
run_sos_upload "${TEST_DIR}/test_files/test2.txt" "meta:v1" &>/dev/null
|
||||||
export SOS_TEST_MODE=1
|
local output=$(run_sos_upload "${TEST_DIR}/test_files/test2.txt" "meta:v2" "meta:updated" 2>&1)
|
||||||
|
|
||||||
# Use the determined host
|
if echo "$output" | grep -q "File already exists"; then
|
||||||
local test_host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
log_info "Metadata update working"
|
||||||
|
|
||||||
# Upload a file
|
|
||||||
"${SCRIPT_DIR}/sos" upload "${test_host}" "${TEST_DIR}/test_files/test2.txt" "meta:v1" >/dev/null 2>&1
|
|
||||||
|
|
||||||
# Upload same file with different metadata
|
|
||||||
local output=$("${SCRIPT_DIR}/sos" upload "${test_host}" "${TEST_DIR}/test_files/test2.txt" "meta:v2" "meta:updated" 2>&1)
|
|
||||||
|
|
||||||
if echo "${output}" | grep -q "File already exists"; then
|
|
||||||
log_info "Metadata update successful"
|
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
log_error "Metadata update test failed"
|
log_error "Metadata update failed"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_exists_endpoint() {
|
test_api_endpoints() {
|
||||||
log_info "Testing exists endpoint..."
|
log_info "Testing API endpoints..."
|
||||||
|
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
||||||
|
|
||||||
# Use the determined host
|
# Test hash endpoint
|
||||||
local test_host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
local hash=$(curl -s "http://${host}/hash/test:file1" | jq -r '.hash')
|
||||||
|
[[ -z "$hash" || "$hash" == "null" ]] && log_error "Hash endpoint failed" && return 1
|
||||||
# Get hash of an uploaded file
|
|
||||||
local hash=$(curl -s "http://${test_host}/hash/test:file1" | jq -r '.hash')
|
|
||||||
|
|
||||||
if [ -z "${hash}" ] || [ "${hash}" = "null" ]; then
|
|
||||||
log_error "Failed to get hash for exists test"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test exists endpoint
|
# Test exists endpoint
|
||||||
local exists=$(curl -s "http://${test_host}/exists/${hash}" | jq -r '.exists')
|
local exists=$(curl -s "http://${host}/exists/${hash}" | jq -r '.exists')
|
||||||
|
[[ "$exists" != "true" ]] && log_error "Exists endpoint failed" && return 1
|
||||||
|
|
||||||
if [ "${exists}" = "true" ]; then
|
log_info "API endpoints working"
|
||||||
log_info "Exists endpoint working correctly"
|
return 0
|
||||||
return 0
|
|
||||||
else
|
|
||||||
log_error "Exists endpoint test failed"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_invalid_auth() {
|
test_invalid_auth() {
|
||||||
log_info "Testing invalid authentication..."
|
log_info "Testing invalid authentication..."
|
||||||
|
|
||||||
# Create a unique test file for this test
|
echo "auth test" > "${TEST_DIR}/test_files/auth_test.txt"
|
||||||
echo "auth test content" > "${TEST_DIR}/test_files/auth_test.txt"
|
|
||||||
|
|
||||||
export SOS_WRITE_TOKEN="invalid-token"
|
export SOS_WRITE_TOKEN="invalid-token"
|
||||||
export SOS_TEST_MODE=1
|
export SOS_TEST_MODE=1
|
||||||
|
|
||||||
# Use the determined host
|
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
||||||
local test_host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
|
|
||||||
|
|
||||||
# Run upload with invalid token and capture output + exit code
|
# Run upload with invalid token and properly capture exit code
|
||||||
set +e # Temporarily disable exit on error
|
set +e
|
||||||
"${SCRIPT_DIR}/sos" upload "${test_host}" "${TEST_DIR}/test_files/auth_test.txt" "auth:test" 2>&1 | tee "${TEST_DIR}/auth_test_output.txt"
|
"${SCRIPT_DIR}/sos" upload "$host" "${TEST_DIR}/test_files/auth_test.txt" "auth:test" >"${TEST_DIR}/auth_output.txt" 2>&1
|
||||||
local exit_code=${PIPESTATUS[0]}
|
local exit_code=$?
|
||||||
set -e # Re-enable exit on error
|
set -e
|
||||||
|
|
||||||
local output=$(cat "${TEST_DIR}/auth_test_output.txt")
|
local output=$(cat "${TEST_DIR}/auth_output.txt")
|
||||||
|
|
||||||
# Check if it failed with non-zero exit code and error message
|
# The sos script should fail with non-zero exit code and show error message
|
||||||
if [ ${exit_code} -ne 0 ] && (echo "${output}" | grep -q "Failed to upload" || echo "${output}" | grep -q "Invalid write token"); then
|
if [[ $exit_code -ne 0 ]] && echo "$output" | grep -qE "(FATAL:|Invalid write token|HTTP 403|HTTP 401)"; then
|
||||||
log_info "Invalid auth correctly rejected"
|
log_info "Invalid auth correctly rejected (exit code: $exit_code)"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
log_error "Invalid auth test failed - upload should have been rejected (exit code: ${exit_code})"
|
log_error "Invalid auth not rejected properly (exit code: $exit_code)"
|
||||||
echo "Output was: ${output}"
|
echo "Output:" && echo "$output" | head -5
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_tests() {
|
# Run all tests
|
||||||
local total_tests=0
|
run_tests() {
|
||||||
local passed_tests=0
|
local tests=(
|
||||||
|
"test_upload ${TEST_DIR}/test_files/test1.txt test:file1"
|
||||||
|
"test_upload ${TEST_DIR}/test_files/test2.txt test:file2 version:1.0 env:test"
|
||||||
|
"test_upload ${TEST_DIR}/test_files/binary_test.bin binary:test"
|
||||||
|
"test_upload ${TEST_DIR}/test_files/sos_binary sos:test sos:latest"
|
||||||
|
"test_retrieval test:file1"
|
||||||
|
"test_deduplication"
|
||||||
|
"test_metadata_update"
|
||||||
|
"test_api_endpoints"
|
||||||
|
"test_invalid_auth"
|
||||||
|
)
|
||||||
|
|
||||||
# Disable exit on error for test functions
|
local total=${#tests[@]}
|
||||||
set +e
|
local passed=0
|
||||||
|
|
||||||
log_info "Starting test suite..."
|
log_info "Running ${total} tests..."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Test 1: Basic upload
|
set +e # Don't exit on test failures
|
||||||
((total_tests++))
|
for test in "${tests[@]}"; do
|
||||||
test_upload "${TEST_DIR}/test_files/test1.txt" "test:file1"
|
eval "$test" && ((passed++)) || true
|
||||||
if [ $? -eq 0 ]; then
|
echo ""
|
||||||
((passed_tests++))
|
done
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 2: Upload with multiple labels
|
|
||||||
((total_tests++))
|
|
||||||
test_upload "${TEST_DIR}/test_files/test2.txt" "test:file2" "version:1.0" "env:test"
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 3: Binary file upload
|
|
||||||
((total_tests++))
|
|
||||||
test_upload "${TEST_DIR}/test_files/binary_test.bin" "binary:test"
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 4: Upload sos binary itself
|
|
||||||
((total_tests++))
|
|
||||||
test_upload "${TEST_DIR}/test_files/sos_binary" "sos:test" "sos:latest"
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 5: Retrieval by label
|
|
||||||
((total_tests++))
|
|
||||||
test_retrieval "test:file1" "This is test file 1"
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 6: Deduplication
|
|
||||||
((total_tests++))
|
|
||||||
test_duplicate_upload
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 7: Metadata update
|
|
||||||
((total_tests++))
|
|
||||||
test_metadata_update
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 8: Exists endpoint
|
|
||||||
((total_tests++))
|
|
||||||
test_exists_endpoint
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test 9: Invalid authentication
|
|
||||||
((total_tests++))
|
|
||||||
test_invalid_auth
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
((passed_tests++))
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Re-enable exit on error
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Summary
|
# Summary
|
||||||
echo "=================================="
|
echo "=================================="
|
||||||
if [ ${passed_tests} -eq ${total_tests} ]; then
|
if [[ $passed -eq $total ]]; then
|
||||||
echo -e "${GREEN}All tests passed!${NC} (${passed_tests}/${total_tests})"
|
echo -e "${GREEN}All tests passed!${NC} (${passed}/${total})"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo -e "${RED}Some tests failed!${NC} (${passed_tests}/${total_tests})"
|
echo -e "${RED}Some tests failed!${NC} (${passed}/${total})"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
# Main execution
|
||||||
|
main() {
|
||||||
echo "SOS Test Suite"
|
echo "SOS Test Suite"
|
||||||
echo "=============="
|
echo "=============="
|
||||||
echo ""
|
echo ""
|
||||||
@@ -587,19 +322,15 @@ function main() {
|
|||||||
start_test_server
|
start_test_server
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
run_tests
|
local result=0
|
||||||
local test_result=$?
|
run_tests || result=$?
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
log_info "Test suite completed"
|
log_info "Test suite completed"
|
||||||
|
|
||||||
# Show container logs if tests failed
|
[[ $result -ne 0 ]] && log_warning "Server logs:" && docker logs "${CONTAINER_NAME}" 2>&1 | tail -10
|
||||||
if [ ${test_result} -ne 0 ]; then
|
|
||||||
log_warning "Showing server logs for debugging:"
|
|
||||||
docker logs "${CONTAINER_NAME}" 2>&1 | tail -20
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit ${test_result}
|
exit $result
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
Reference in New Issue
Block a user