diff --git a/sos b/sos index fb4d461..26c630f 100755 --- a/sos +++ b/sos @@ -84,16 +84,16 @@ function upload() { server=$1 file=$2 - first_label=$3 - LABELTAGS=("$first_label") - [[ "$first_label" =~ : ]] || die "Label $first_label does not contain a tag!" - - shift 3 + shift 2 - # Arrays to store custom metadata + # Arrays to store labels and custom metadata + LABELTAGS=() declare -A CUSTOM_METADATA # Parse remaining arguments for labels and metadata + # Need at least one label:tag + local found_first_label=false + while [ "$#" -gt 0 ]; do if [ "$1" == "--metadata" ]; then shift @@ -114,9 +114,18 @@ function upload() { label="$1" [[ "$label" =~ : ]] || die "Label $label does not contain a tag!" LABELTAGS+=("$label") + found_first_label=true shift fi done + + # Ensure we have at least one label + if [ "$found_first_label" != true ]; then + die "At least one label:tag is required" + fi + + # Store the first label for later use + first_label="${LABELTAGS[0]}" # check if file contains : [[ ! "$file" =~ : ]] || die "File contains : - this is not allowed!" diff --git a/test.sh b/test.sh index ca5f2ee..c11d447 100755 --- a/test.sh +++ b/test.sh @@ -489,6 +489,228 @@ test_metadata_invalid_format() { 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=( @@ -507,6 +729,8 @@ run_tests() { "test_metadata_mixed_labels" "test_metadata_empty_value" "test_metadata_invalid_format" + "test_metadata_no_labels" + "test_metadata_ordering_comprehensive" ) local total=${#tests[@]}