#! /bin/bash set -euo pipefail HOSTURL="${1:-http://127.0.0.1:7703}" #------------------------------------------------------------------------------------------------ SCRIPT_DIR=$(dirname "$0") SCRIPT_NAME=$(basename "$0") # FUNCTIONS function title() { echo "----------------------------------------" # Center the text local text="$1" local line_length=40 local text_length=${#text} local padding=$(( (line_length - text_length) / 2 )) printf "%*s%s%*s\n" $padding "" "$text" $padding "" echo "----------------------------------------" } function die() { title "error: $1" exit 1 } #------------------------------------------------------------------------------------------------ cat << EOF EOF title "TESTING ${HOSTURL}" cat << EOF EOF function test0() { # Test 0: Verify the script is running title "0: Verify the server is running" # test jq is installed if ! command -v jq &> /dev/null; then echo "jq could not be found" echo "sudo apt-get install jq" exit 1 fi # read sos_config.json CONFIG_PATH="${SCRIPT_DIR}/sos_config.json" if [ ! -f "${CONFIG_PATH}" ]; then echo "config file not found at ${CONFIG_PATH}" exit 1 fi CONFIG=$(cat "${CONFIG_PATH}") # Use plaintext tokens from environment (set by generate_test_config.sh or manually) # The config file should only contain hashed tokens if [ -n "${TEST_TOKEN1:-}" ] && [ -n "${TEST_TOKEN2:-}" ] && [ -n "${TEST_TOKEN3:-}" ]; then # Use environment tokens (plaintext) TOKENS=("$TEST_TOKEN1" "$TEST_TOKEN2" "$TEST_TOKEN3") TOKEN_COUNT=${#TOKENS[@]} RANDOM_INDEX=$((RANDOM % TOKEN_COUNT)) WRITE_TOKEN="${TOKENS[$RANDOM_INDEX]}" echo "Using plaintext token index $RANDOM_INDEX from environment" else # For static test configs, use hardcoded plaintext tokens # These correspond to the hashes in the static sos_config.json TOKENS=("t570H7DmK2VBfCwUmtFaUXyzVklL90E1" "U3x9V39Y7rjXdRK0oxZsCz5lD6jFFDtm" "UhtchhGDEGXlJ37GumimFtPe0imjAvak") TOKEN_COUNT=${#TOKENS[@]} RANDOM_INDEX=$((RANDOM % TOKEN_COUNT)) WRITE_TOKEN="${TOKENS[$RANDOM_INDEX]}" echo "Using hardcoded plaintext token index $RANDOM_INDEX (for static config)" fi BASE_TAG="autotest" if ! command -v wget &> /dev/null; then echo "wget could not be found" exit 1 fi # test if server is running if ! wget -qO- "${HOSTURL}/status" | jq -r '.result' | grep -q 'success'; then wget -O - "${HOSTURL}/status" die "server is not running on ${HOSTURL}" fi echo "Simple Object Storage server is running at ${HOSTURL}" } function test1() { # test every action in the README.md file, leaving the system in the same state it was found # and print the output of each action # Construct metadata JSON METADATA_JSON=$(cat </dev/null 2>&1; then die "Invalid JSON response from upload: ${UPLOAD_RESPONSE}" fi OBJECT_HASH=$(echo "${UPLOAD_RESPONSE}" | jq -r '.hash') echo "Received hash: ${OBJECT_HASH}" # Verify the object exists echo "Verifying object exists..." EXISTS_RESPONSE=$(curl -s "${HOSTURL}/exists/${BASE_TAG}:test2") echo "Exists response: ${EXISTS_RESPONSE}" # Get metadata and verify extra fields are preserved echo "Retrieving metadata for ${BASE_TAG}:test2" METADATA_RESPONSE=$(curl -s "${HOSTURL}/meta/${BASE_TAG}:test2") CURL_EXIT_CODE=$? echo "Curl exit code: ${CURL_EXIT_CODE}" echo "Full metadata response: ${METADATA_RESPONSE}" if [ ${CURL_EXIT_CODE} -ne 0 ]; then die "Failed to retrieve metadata: curl returned ${CURL_EXIT_CODE}" fi if ! echo "${METADATA_RESPONSE}" | jq -e . >/dev/null 2>&1; then die "Invalid JSON response: ${METADATA_RESPONSE}" fi if ! echo "${METADATA_RESPONSE}" | jq -r '.metadata.extra_field1' | grep -q 'value1'; then die "extra_field1 not preserved in metadata" fi if ! echo "${METADATA_RESPONSE}" | jq -r '.metadata.extra_field2' | grep -q 'value2'; then die "extra_field2 not preserved in metadata" fi } function test6() { #------------------------------------------------------------------------------------------------ title "6: Test tag versioning behavior" # Clean up curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${OBJECT_HASH}" > /dev/null # Upload first version with tag 'latest' FIRST_METADATA_JSON=$(cat < /dev/null curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${SECOND_HASH}" > /dev/null # Use a known invalid token INVALID_TOKEN="invalid_token" # Make 5 requests with an invalid token for i in {1..5}; do echo "Attempt $i with invalid token" RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${INVALID_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${HOSTURL}/upload") echo "Response: ${RESPONSE}" done # Now try a request with a valid token - should be rate limited echo "Attempting request with valid token (should be rate limited)" RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${WRITE_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${HOSTURL}/upload") if ! echo "${RESPONSE}" | jq -r '.error' | grep -q "Too many authentication attempts"; then die "Expected rate limit error, got: ${RESPONSE}" fi echo "Sleeping for 3 seconds to allow rate limit to reset" echo "(Normally 5 mins, but we set to 2s for this test!)" sleep 3 # Now try a request with a valid token - should be rate limited echo "Attempting request with valid token (should NOT be rate limited)" RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${WRITE_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${HOSTURL}/upload") } function test8() { #------------------------------------------------------------------------------------------------ title "8: Test update endpoint" # First upload a test file UPLOAD_RESPONSE=$(curl -s -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" \ -F "metadata={\"labeltags\":[\"test:update\"]}" \ "${HOSTURL}/upload") HASH=$(echo "${UPLOAD_RESPONSE}" | jq -r '.hash') if [ -z "${HASH}" ] || [ "${HASH}" = "null" ]; then die "Failed to upload test file for update test" fi # Test 8.1: Update metadata using JSON UPDATED_METADATA='{"labeltags":["test:updated", "version:1.0"], "new_field":"test_value"}' UPDATE_RESPONSE=$(curl -s -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"hash\":\"${HASH}\", \"metadata\":${UPDATED_METADATA}}" \ "${HOSTURL}/update") echo "Update response: ${UPDATE_RESPONSE}" if [ "$(echo "${UPDATE_RESPONSE}" | jq -r '.result')" != "success" ]; then die "Failed to update metadata via JSON" fi # Verify the update UPDATED_METADATA_RESPONSE=$(curl -s "${HOSTURL}/meta/${HASH}") if ! echo "${UPDATED_METADATA_RESPONSE}" | jq -e '.metadata.new_field == "test_value"' | grep -q true; then die "Metadata was not updated correctly via JSON" fi # Test 8.2: Update metadata using form data # Update with form data using raw JSON string UPDATE_FORM_RESPONSE=$(curl -s -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -F "hash=${HASH}" \ -F 'metadata={"labeltags":["test:form_updated"], "form_field":"form_value"}' \ "${HOSTURL}/update") echo "Form update response: ${UPDATE_FORM_RESPONSE}" if [ "$(echo "${UPDATE_FORM_RESPONSE}" | jq -r '.result')" != "success" ]; then die "Failed to update metadata via form data" fi # Verify the form update UPDATED_FORM_METADATA_RESPONSE=$(curl -s "${HOSTURL}/meta/${HASH}") if ! echo "${UPDATED_FORM_METADATA_RESPONSE}" | jq -e '.metadata.form_field == "form_value"' | grep -q true; then die "Metadata was not updated correctly via form data" fi # Test 8.3: Test error cases # Missing hash MISSING_HASH_RESPONSE=$(curl -s -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -d '{"metadata":{}}' \ "${HOSTURL}/update") if [ "$(echo "${MISSING_HASH_RESPONSE}" | jq -r '.error')" != "Missing 'hash' or 'metadata' field in request body" ]; then die "Expected error for missing hash, got: ${MISSING_HASH_RESPONSE}" fi # Missing metadata MISSING_METADATA_RESPONSE=$(curl -s -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -d "{\"hash\":\"${HASH}\"}" \ "${HOSTURL}/update") if [ "$(echo "${MISSING_METADATA_RESPONSE}" | jq -r '.error')" != "Missing 'hash' or 'metadata' field in request body" ]; then die "Expected error for missing metadata, got: ${MISSING_METADATA_RESPONSE}" fi # Verify that labeltags were actually updated echo "Checking if test:updated tag exists..." UPDATED_HASH=$(curl -s "${HOSTURL}/hash/test:updated" | jq -r '.hash') if [ "${UPDATED_HASH}" = "${HASH}" ]; then echo "✓ test:updated tag correctly points to hash ${HASH}" else echo "✗ test:updated tag not found or points to wrong hash: ${UPDATED_HASH}" exit 1 fi echo "Checking if test:form_updated tag exists..." FORM_UPDATED_HASH=$(curl -s "${HOSTURL}/hash/test:form_updated" | jq -r '.hash') if [ "${FORM_UPDATED_HASH}" = "${HASH}" ]; then echo "✓ test:form_updated tag correctly points to hash ${HASH}" else echo "✗ test:form_updated tag not found or points to wrong hash: ${FORM_UPDATED_HASH}" exit 1 fi # Clean up using the correct current labeltag echo "Cleaning up test object with hash: ${HASH}" RESPONSE=$(curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${HASH}") echo "Delete response: ${RESPONSE}" if echo "${RESPONSE}" | jq -r '.result' | grep -q 'success'; then echo "Successfully deleted test object" else echo "Failed to delete test object: ${RESPONSE}" exit 1 fi } #------------------------------------------------------------------------------------------------ function test9() { title "9: Testing 1GB File upload" source test_1GB_file_upload.sh } #------------------------------------------------------------------------------------------------ function test10() { title "10: Testing Input Validation" # Use the simpler validation test that works in Docker local test_script="test_input_validation_simple.sh" # Fall back to full test if simple doesn't exist if [ ! -f "$test_script" ]; then test_script="test_input_validation.sh" fi # Check if validation test script exists if [ ! -f "$test_script" ]; then echo "Warning: No input validation test script found, skipping" return 0 fi # Run the input validation tests # Use the same token that's already set export TEST_TOKEN1="${WRITE_TOKEN}" echo "Running input validation tests..." if bash "${SCRIPT_DIR}/$test_script" "${HOSTURL}"; then echo "✓ Input validation tests passed" else die "Input validation tests failed" fi } #------------------------------------------------------------------------------------------------ test0 test1 test2 test3 test3b test4 test5 test6 test7 test8 test9 test10 title "ALL TESTS PASSED"