Files
sos/test.sh
Your Name 944cc63502
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 31s
Build-Test-Publish / build (linux/arm64) (push) Successful in 31s
test: Update 2 files
2025-09-02 15:17:50 +12:00

784 lines
28 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
TEST_DIR="${SCRIPT_DIR}/test_tmp"
TEST_TOKEN="test-token-$(date +%s)"
CONTAINER_NAME="sos-test-$(date +%s)"
IMAGE="gitea.jde.nz/public/simple-object-server:latest"
TEST_PORT=""
SOS_TEST_HOST=""
CLEANUP_NEEDED=false
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Logging functions
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"
}
trap cleanup EXIT
# Check dependencies
check_dependencies() {
log_info "Checking dependencies..."
for cmd in docker jq curl; do
command -v $cmd &>/dev/null || die "$cmd is required but not installed"
done
docker info &>/dev/null || die "Docker daemon is not running"
log_info "All dependencies satisfied"
}
# Setup test environment
setup_test_environment() {
log_info "Setting up test environment..."
CLEANUP_NEEDED=true
# Create directories
rm -rf "${TEST_DIR}"
mkdir -p "${TEST_DIR}"/{test_files,config}
# Generate hashed token for authentication
log_info "Generating authentication token..."
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"
# Create config
echo "{\"write_tokens\": [\"${hashed_token}\"]}" > "${TEST_DIR}/config/sos_config.json"
# Create test files
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"
dd if=/dev/urandom of="${TEST_DIR}/test_files/binary_test.bin" bs=1024 count=10 &>/dev/null
cp "${SCRIPT_DIR}/sos" "${TEST_DIR}/test_files/sos_binary"
log_info "Test environment ready"
}
# Start and configure test server
start_test_server() {
log_info "Starting SOS test server..."
# Pull latest image
docker pull "$IMAGE" &>/dev/null || log_warning "Using cached image"
# Start container with dynamic port
local container_id=$(docker run -d --name "${CONTAINER_NAME}" -p 80 "$IMAGE" 2>&1)
[[ $? -ne 0 ]] && die "Failed to start container: ${container_id}"
log_info "Container started: ${container_id:0:12}"
# Get assigned port
TEST_PORT=$(docker port "${CONTAINER_NAME}" 80 | cut -d: -f2)
[[ -z "$TEST_PORT" ]] && die "Failed to get container port"
log_info "Container port: ${TEST_PORT}"
# Copy config and restart (for Docker-in-Docker compatibility)
docker cp "${TEST_DIR}/config/sos_config.json" "${CONTAINER_NAME}:/data/sos_config.json" || die "Failed to copy config"
docker exec "${CONTAINER_NAME}" mkdir -p /data/storage 2>/dev/null || true
docker restart "${CONTAINER_NAME}" &>/dev/null || die "Failed to restart container"
# ARM64 systems may need more time to restart
sleep 5 # Wait for restart
# Update port if changed after restart
local new_port=$(docker port "${CONTAINER_NAME}" 80 | cut -d: -f2)
[[ -z "$new_port" ]] && die "Lost port mapping after restart"
[[ "$new_port" != "$TEST_PORT" ]] && TEST_PORT="$new_port" && log_info "Port updated: ${TEST_PORT}"
# Get network details for connectivity
local container_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${CONTAINER_NAME}")
local host_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' "${CONTAINER_NAME}")
# Wait for server readiness and determine connection method
wait_for_server "$container_ip" "$host_ip"
}
# 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 label="$2"
shift 2
log_info "Testing upload: ${file##*/} with label ${label}"
local output=$(run_sos_upload "$file" "$label" "$@" 2>&1 | tee "${TEST_DIR}/upload_output.txt")
if echo "$output" | grep -q "Download URL:"; then
log_info "Upload successful"
return 0
else
log_error "Upload failed"
# Show error details for debugging ARM64 issues
echo "Error output:" >&2
echo "$output" | grep -E "(FATAL:|ERROR:|Failed|curl)" | head -5 >&2
return 1
fi
}
test_retrieval() {
local identifier="$1"
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
log_info "Testing retrieval: ${identifier}"
local response=$(curl -s "http://${host}/${identifier}")
[[ -z "$response" ]] && log_error "Retrieval failed" && return 1
# For hash identifiers, also test metadata endpoint
if [[ "$identifier" =~ ^[a-f0-9]{64}$ ]]; then
curl -s "http://${host}/meta/${identifier}" | jq -e '.metadata' &>/dev/null || {
log_error "Metadata retrieval failed"
return 1
}
fi
log_info "Retrieval successful"
return 0
}
test_deduplication() {
log_info "Testing deduplication..."
# Create duplicate file
cp "${TEST_DIR}/test_files/test1.txt" "${TEST_DIR}/test_files/test1_dup.txt"
# Upload original and duplicate
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)
if echo "$output" | grep -q "File already exists, skipping upload"; then
log_info "Deduplication working"
return 0
else
log_error "Deduplication failed"
return 1
fi
}
test_metadata_update() {
log_info "Testing metadata update..."
run_sos_upload "${TEST_DIR}/test_files/test2.txt" "meta:v1" &>/dev/null
local output=$(run_sos_upload "${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 working"
return 0
else
log_error "Metadata update failed"
return 1
fi
}
test_api_endpoints() {
log_info "Testing API endpoints..."
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
# Test hash endpoint
local hash=$(curl -s "http://${host}/hash/test:file1" | jq -r '.hash')
[[ -z "$hash" || "$hash" == "null" ]] && log_error "Hash endpoint failed" && return 1
# Test exists endpoint
local exists=$(curl -s "http://${host}/exists/${hash}" | jq -r '.exists')
[[ "$exists" != "true" ]] && log_error "Exists endpoint failed" && return 1
log_info "API endpoints working"
return 0
}
test_invalid_auth() {
log_info "Testing invalid authentication..."
echo "auth test" > "${TEST_DIR}/test_files/auth_test.txt"
export SOS_WRITE_TOKEN="invalid-token"
export SOS_TEST_MODE=1
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
# Run upload with invalid token and properly capture exit code
set +e
"${SCRIPT_DIR}/sos" upload "$host" "${TEST_DIR}/test_files/auth_test.txt" "auth:test" >"${TEST_DIR}/auth_output.txt" 2>&1
local exit_code=$?
set -e
local output=$(cat "${TEST_DIR}/auth_output.txt")
# The sos script should fail with non-zero exit code and show error message
if [[ $exit_code -ne 0 ]] && echo "$output" | grep -qE "(FATAL:|Invalid write token|HTTP 403|HTTP 401)"; then
log_info "Invalid auth correctly rejected (exit code: $exit_code)"
return 0
else
log_error "Invalid auth not rejected properly (exit code: $exit_code)"
echo "Output:" && echo "$output" | head -5
return 1
fi
}
test_metadata_single() {
log_info "Testing single metadata field..."
echo "metadata test single" > "${TEST_DIR}/test_files/meta_single.txt"
local output=$(run_sos_upload "${TEST_DIR}/test_files/meta_single.txt" "meta:single" --metadata "customField=testValue" 2>&1)
# Check if upload succeeded
if ! echo "$output" | grep -q "Download URL:"; then
log_error "Upload with metadata failed"
echo "$output" | head -5
return 1
fi
# Verify metadata was included
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
local hash=$(curl -s "http://${host}/hash/meta:single" | jq -r '.hash')
local meta=$(curl -s "http://${host}/meta/${hash}" | jq -r '.metadata.customField')
if [[ "$meta" == "testValue" ]]; then
log_info "Single metadata field working"
return 0
else
log_error "Metadata not found or incorrect (got: $meta)"
return 1
fi
}
test_metadata_multiple() {
log_info "Testing multiple metadata fields..."
echo "metadata test multiple" > "${TEST_DIR}/test_files/meta_multiple.txt"
local output=$(run_sos_upload "${TEST_DIR}/test_files/meta_multiple.txt" "meta:multiple" \
--metadata "field1=value1" \
--metadata "field2=value2" \
--metadata "templateXXHash64=abc123def456" 2>&1)
# Check if upload succeeded
if ! echo "$output" | grep -q "Download URL:"; then
log_error "Upload with multiple metadata failed"
echo "$output" | head -5
return 1
fi
# Verify all metadata fields were included
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
local hash=$(curl -s "http://${host}/hash/meta:multiple" | jq -r '.hash')
local metadata=$(curl -s "http://${host}/meta/${hash}")
local field1=$(echo "$metadata" | jq -r '.metadata.field1')
local field2=$(echo "$metadata" | jq -r '.metadata.field2')
local xxhash=$(echo "$metadata" | jq -r '.metadata.templateXXHash64')
if [[ "$field1" == "value1" && "$field2" == "value2" && "$xxhash" == "abc123def456" ]]; then
log_info "Multiple metadata fields working"
return 0
else
log_error "Metadata fields incorrect"
echo "field1=$field1, field2=$field2, templateXXHash64=$xxhash"
return 1
fi
}
test_metadata_special_chars() {
log_info "Testing metadata with special characters..."
echo "metadata test special" > "${TEST_DIR}/test_files/meta_special.txt"
local output=$(run_sos_upload "${TEST_DIR}/test_files/meta_special.txt" "meta:special" \
--metadata "description=This is a test with spaces" \
--metadata "formula=a=b+c" \
--metadata "path=/usr/local/bin" \
--metadata "quote=He said \"hello\"" 2>&1)
# Check if upload succeeded
if ! echo "$output" | grep -q "Download URL:"; then
log_error "Upload with special chars metadata failed"
echo "$output" | head -5
return 1
fi
# Verify metadata with special characters
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
local hash=$(curl -s "http://${host}/hash/meta:special" | jq -r '.hash')
local metadata=$(curl -s "http://${host}/meta/${hash}")
local desc=$(echo "$metadata" | jq -r '.metadata.description')
local formula=$(echo "$metadata" | jq -r '.metadata.formula')
local path=$(echo "$metadata" | jq -r '.metadata.path')
local quote=$(echo "$metadata" | jq -r '.metadata.quote')
if [[ "$desc" == "This is a test with spaces" && \
"$formula" == "a=b+c" && \
"$path" == "/usr/local/bin" && \
"$quote" == 'He said "hello"' ]]; then
log_info "Metadata with special characters working"
return 0
else
log_error "Special character metadata incorrect"
echo "description='$desc'"
echo "formula='$formula'"
echo "path='$path'"
echo "quote='$quote'"
return 1
fi
}
test_metadata_mixed_labels() {
log_info "Testing metadata mixed with multiple labels..."
echo "metadata test mixed" > "${TEST_DIR}/test_files/meta_mixed.txt"
local output=$(run_sos_upload "${TEST_DIR}/test_files/meta_mixed.txt" \
"meta:mixed1" \
--metadata "author=test-user" \
"meta:mixed2" \
--metadata "version=1.2.3" \
"meta:mixed3" 2>&1)
# Check if upload succeeded
if ! echo "$output" | grep -q "Download URL:"; then
log_error "Upload with mixed labels and metadata failed"
echo "$output" | head -5
return 1
fi
# Verify metadata and labels
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
local hash=$(curl -s "http://${host}/hash/meta:mixed1" | jq -r '.hash')
local metadata=$(curl -s "http://${host}/meta/${hash}")
local author=$(echo "$metadata" | jq -r '.metadata.author')
local version=$(echo "$metadata" | jq -r '.metadata.version')
local labels=$(echo "$metadata" | jq -r '.metadata.labeltags | length')
# Check all three labels exist
local has_mixed1=$(echo "$metadata" | jq -r '.metadata.labeltags | map(select(. == "meta:mixed1")) | length')
local has_mixed2=$(echo "$metadata" | jq -r '.metadata.labeltags | map(select(. == "meta:mixed2")) | length')
local has_mixed3=$(echo "$metadata" | jq -r '.metadata.labeltags | map(select(. == "meta:mixed3")) | length')
if [[ "$author" == "test-user" && "$version" == "1.2.3" && \
"$has_mixed1" == "1" && "$has_mixed2" == "1" && "$has_mixed3" == "1" ]]; then
log_info "Mixed labels and metadata working"
return 0
else
log_error "Mixed metadata/labels incorrect"
echo "author=$author, version=$version"
echo "Labels: mixed1=$has_mixed1, mixed2=$has_mixed2, mixed3=$has_mixed3"
return 1
fi
}
test_metadata_empty_value() {
log_info "Testing metadata with empty value..."
echo "metadata test empty" > "${TEST_DIR}/test_files/meta_empty.txt"
local output=$(run_sos_upload "${TEST_DIR}/test_files/meta_empty.txt" "meta:empty" \
--metadata "emptyField=" \
--metadata "normalField=hasValue" 2>&1)
# Check if upload succeeded
if ! echo "$output" | grep -q "Download URL:"; then
log_error "Upload with empty metadata value failed"
echo "$output" | head -5
return 1
fi
# Verify metadata
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
local hash=$(curl -s "http://${host}/hash/meta:empty" | jq -r '.hash')
local metadata=$(curl -s "http://${host}/meta/${hash}")
local empty=$(echo "$metadata" | jq -r '.metadata.emptyField')
local normal=$(echo "$metadata" | jq -r '.metadata.normalField')
if [[ "$empty" == "" && "$normal" == "hasValue" ]]; then
log_info "Empty metadata value handled correctly"
return 0
else
log_error "Empty metadata value not handled correctly"
echo "emptyField='$empty', normalField='$normal'"
return 1
fi
}
test_metadata_invalid_format() {
log_info "Testing invalid metadata format rejection..."
echo "metadata test invalid" > "${TEST_DIR}/test_files/meta_invalid.txt"
# Test invalid format (no equals sign) - directly call sos to capture exit code
export SOS_WRITE_TOKEN="${TEST_TOKEN}"
export SOS_TEST_MODE=1
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
set +e
"${SCRIPT_DIR}/sos" upload "$host" "${TEST_DIR}/test_files/meta_invalid.txt" "meta:invalid" --metadata "noequals" >"${TEST_DIR}/invalid_meta_output.txt" 2>&1
local exit_code=$?
set -e
local output=$(cat "${TEST_DIR}/invalid_meta_output.txt")
if [[ $exit_code -ne 0 ]] && echo "$output" | grep -q "Metadata must be in \"key=value\" format"; then
log_info "Invalid metadata format correctly rejected (exit code: $exit_code)"
return 0
else
log_error "Invalid metadata format not rejected properly"
echo "Exit code: $exit_code"
echo "$output" | head -5
return 1
fi
}
test_metadata_no_labels() {
log_info "Testing metadata without any labels (should fail)..."
echo "metadata no labels" > "${TEST_DIR}/test_files/meta_no_labels.txt"
# Test with only metadata, no labels - should fail
export SOS_WRITE_TOKEN="${TEST_TOKEN}"
export SOS_TEST_MODE=1
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
set +e
"${SCRIPT_DIR}/sos" upload "$host" "${TEST_DIR}/test_files/meta_no_labels.txt" \
--metadata "field1=value1" \
--metadata "field2=value2" >"${TEST_DIR}/no_labels_output.txt" 2>&1
local exit_code=$?
set -e
local output=$(cat "${TEST_DIR}/no_labels_output.txt")
if [[ $exit_code -ne 0 ]] && echo "$output" | grep -q "At least one label:tag is required"; then
log_info "Metadata without labels correctly rejected (exit code: $exit_code)"
return 0
else
log_error "Metadata without labels not rejected properly"
echo "Exit code: $exit_code"
echo "$output" | head -5
return 1
fi
}
test_metadata_ordering_comprehensive() {
log_info "Testing comprehensive metadata and label ordering combinations..."
local all_passed=true
local host="${SOS_TEST_HOST:-localhost:${TEST_PORT}}"
# Test 1: Metadata before all labels
echo "order test 1" > "${TEST_DIR}/test_files/order1.txt"
local output=$(run_sos_upload "${TEST_DIR}/test_files/order1.txt" \
--metadata "position=before" \
--metadata "test=1" \
"order:test1a" \
"order:test1b" 2>&1)
if echo "$output" | grep -q "Download URL:"; then
local hash=$(curl -s "http://${host}/hash/order:test1a" | jq -r '.hash')
local metadata=$(curl -s "http://${host}/meta/${hash}")
local position=$(echo "$metadata" | jq -r '.metadata.position')
local test=$(echo "$metadata" | jq -r '.metadata.test')
local labels=$(echo "$metadata" | jq -r '.metadata.labeltags | length')
if [[ "$position" == "before" && "$test" == "1" && "$labels" == "2" ]]; then
log_info " ✓ Metadata before all labels: PASSED"
else
log_error " ✗ Metadata before all labels: FAILED"
echo " Got: position=$position, test=$test, labels=$labels"
all_passed=false
fi
else
log_error " ✗ Metadata before all labels: Upload failed"
all_passed=false
fi
# Test 2: Metadata after all labels
echo "order test 2" > "${TEST_DIR}/test_files/order2.txt"
output=$(run_sos_upload "${TEST_DIR}/test_files/order2.txt" \
"order:test2a" \
"order:test2b" \
--metadata "position=after" \
--metadata "test=2" 2>&1)
if echo "$output" | grep -q "Download URL:"; then
hash=$(curl -s "http://${host}/hash/order:test2a" | jq -r '.hash')
metadata=$(curl -s "http://${host}/meta/${hash}")
position=$(echo "$metadata" | jq -r '.metadata.position')
test=$(echo "$metadata" | jq -r '.metadata.test')
labels=$(echo "$metadata" | jq -r '.metadata.labeltags | length')
if [[ "$position" == "after" && "$test" == "2" && "$labels" == "2" ]]; then
log_info " ✓ Metadata after all labels: PASSED"
else
log_error " ✗ Metadata after all labels: FAILED"
echo " Got: position=$position, test=$test, labels=$labels"
all_passed=false
fi
else
log_error " ✗ Metadata after all labels: Upload failed"
all_passed=false
fi
# Test 3: Alternating pattern - label, metadata, label, metadata
echo "order test 3" > "${TEST_DIR}/test_files/order3.txt"
output=$(run_sos_upload "${TEST_DIR}/test_files/order3.txt" \
"order:test3a" \
--metadata "first=1" \
"order:test3b" \
--metadata "second=2" 2>&1)
if echo "$output" | grep -q "Download URL:"; then
hash=$(curl -s "http://${host}/hash/order:test3a" | jq -r '.hash')
metadata=$(curl -s "http://${host}/meta/${hash}")
first=$(echo "$metadata" | jq -r '.metadata.first')
second=$(echo "$metadata" | jq -r '.metadata.second')
labels=$(echo "$metadata" | jq -r '.metadata.labeltags | length')
if [[ "$first" == "1" && "$second" == "2" && "$labels" == "2" ]]; then
log_info " ✓ Alternating label-metadata pattern: PASSED"
else
log_error " ✗ Alternating label-metadata pattern: FAILED"
echo " Got: first=$first, second=$second, labels=$labels"
all_passed=false
fi
else
log_error " ✗ Alternating label-metadata pattern: Upload failed"
all_passed=false
fi
# Test 4: Alternating pattern - metadata, label, metadata, label
echo "order test 4" > "${TEST_DIR}/test_files/order4.txt"
output=$(run_sos_upload "${TEST_DIR}/test_files/order4.txt" \
--metadata "alpha=a" \
"order:test4a" \
--metadata "beta=b" \
"order:test4b" 2>&1)
if echo "$output" | grep -q "Download URL:"; then
hash=$(curl -s "http://${host}/hash/order:test4a" | jq -r '.hash')
metadata=$(curl -s "http://${host}/meta/${hash}")
alpha=$(echo "$metadata" | jq -r '.metadata.alpha')
beta=$(echo "$metadata" | jq -r '.metadata.beta')
labels=$(echo "$metadata" | jq -r '.metadata.labeltags | length')
if [[ "$alpha" == "a" && "$beta" == "b" && "$labels" == "2" ]]; then
log_info " ✓ Alternating metadata-label pattern: PASSED"
else
log_error " ✗ Alternating metadata-label pattern: FAILED"
echo " Got: alpha=$alpha, beta=$beta, labels=$labels"
all_passed=false
fi
else
log_error " ✗ Alternating metadata-label pattern: Upload failed"
all_passed=false
fi
# Test 5: Complex mixed pattern
echo "order test 5" > "${TEST_DIR}/test_files/order5.txt"
output=$(run_sos_upload "${TEST_DIR}/test_files/order5.txt" \
--metadata "start=yes" \
"order:test5a" \
"order:test5b" \
--metadata "middle=true" \
"order:test5c" \
--metadata "end=done" \
--metadata "extra=value" 2>&1)
if echo "$output" | grep -q "Download URL:"; then
hash=$(curl -s "http://${host}/hash/order:test5a" | jq -r '.hash')
metadata=$(curl -s "http://${host}/meta/${hash}")
start=$(echo "$metadata" | jq -r '.metadata.start')
middle=$(echo "$metadata" | jq -r '.metadata.middle')
end=$(echo "$metadata" | jq -r '.metadata.end')
extra=$(echo "$metadata" | jq -r '.metadata.extra')
labels=$(echo "$metadata" | jq -r '.metadata.labeltags | length')
if [[ "$start" == "yes" && "$middle" == "true" && "$end" == "done" && \
"$extra" == "value" && "$labels" == "3" ]]; then
log_info " ✓ Complex mixed pattern: PASSED"
else
log_error " ✗ Complex mixed pattern: FAILED"
echo " Got: start=$start, middle=$middle, end=$end, extra=$extra, labels=$labels"
all_passed=false
fi
else
log_error " ✗ Complex mixed pattern: Upload failed"
all_passed=false
fi
# Test 6: Multiple consecutive metadata flags at different positions
echo "order test 6" > "${TEST_DIR}/test_files/order6.txt"
output=$(run_sos_upload "${TEST_DIR}/test_files/order6.txt" \
--metadata "group1a=1" \
--metadata "group1b=2" \
"order:test6a" \
--metadata "group2a=3" \
--metadata "group2b=4" \
"order:test6b" \
--metadata "group3a=5" \
--metadata "group3b=6" 2>&1)
if echo "$output" | grep -q "Download URL:"; then
hash=$(curl -s "http://${host}/hash/order:test6a" | jq -r '.hash')
metadata=$(curl -s "http://${host}/meta/${hash}")
g1a=$(echo "$metadata" | jq -r '.metadata.group1a')
g1b=$(echo "$metadata" | jq -r '.metadata.group1b')
g2a=$(echo "$metadata" | jq -r '.metadata.group2a')
g2b=$(echo "$metadata" | jq -r '.metadata.group2b')
g3a=$(echo "$metadata" | jq -r '.metadata.group3a')
g3b=$(echo "$metadata" | jq -r '.metadata.group3b')
labels=$(echo "$metadata" | jq -r '.metadata.labeltags | length')
if [[ "$g1a" == "1" && "$g1b" == "2" && "$g2a" == "3" && \
"$g2b" == "4" && "$g3a" == "5" && "$g3b" == "6" && "$labels" == "2" ]]; then
log_info " ✓ Multiple consecutive metadata groups: PASSED"
else
log_error " ✗ Multiple consecutive metadata groups: FAILED"
echo " Got: g1a=$g1a, g1b=$g1b, g2a=$g2a, g2b=$g2b, g3a=$g3a, g3b=$g3b, labels=$labels"
all_passed=false
fi
else
log_error " ✗ Multiple consecutive metadata groups: Upload failed"
all_passed=false
fi
if [[ "$all_passed" == true ]]; then
log_info "All ordering tests passed!"
return 0
else
log_error "Some ordering tests failed"
return 1
fi
}
# Run all tests
run_tests() {
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"
"test_metadata_single"
"test_metadata_multiple"
"test_metadata_special_chars"
"test_metadata_mixed_labels"
"test_metadata_empty_value"
"test_metadata_invalid_format"
"test_metadata_no_labels"
"test_metadata_ordering_comprehensive"
)
local total=${#tests[@]}
local passed=0
log_info "Running ${total} tests..."
echo ""
set +e # Don't exit on test failures
for test in "${tests[@]}"; do
eval "$test" && ((passed++)) || true
echo ""
# Small delay between tests for ARM64 stability
sleep 0.5
done
set -e
# Summary
echo "=================================="
if [[ $passed -eq $total ]]; then
echo -e "${GREEN}All tests passed!${NC} (${passed}/${total})"
return 0
else
echo -e "${RED}Some tests failed!${NC} (${passed}/${total})"
return 1
fi
}
# Main execution
main() {
echo "SOS Test Suite"
echo "=============="
echo ""
check_dependencies
setup_test_environment
start_test_server
echo ""
local result=0
run_tests || result=$?
echo ""
log_info "Test suite completed"
[[ $result -ne 0 ]] && log_warning "Server logs:" && docker logs "${CONTAINER_NAME}" 2>&1 | tail -10
exit $result
}
main "$@"