From 384bb463d3a4729868e8ec5e9aadf30bc91847b5 Mon Sep 17 00:00:00 2001 From: Luke McCrone Date: Sat, 26 Apr 2025 13:07:52 -0300 Subject: [PATCH] test: copy object tests (copy source, payload) --- tests/commands/put_object.sh | 29 +++++++ tests/drivers/copy_object/copy_object_rest.sh | 76 +++++++++++++++++++ tests/rest_scripts/copy_object.sh | 29 ++++--- tests/test_rest.sh | 26 +++++++ tests/test_s3api_object.sh | 1 + tests/util/util_object.sh | 48 ------------ 6 files changed, 146 insertions(+), 63 deletions(-) create mode 100644 tests/drivers/copy_object/copy_object_rest.sh diff --git a/tests/commands/put_object.sh b/tests/commands/put_object.sh index 82bc1c4..45760ef 100644 --- a/tests/commands/put_object.sh +++ b/tests/commands/put_object.sh @@ -141,3 +141,32 @@ put_object_rest_user_bad_signature() { fi return 0 } + +put_object_multiple() { + if [ $# -ne 3 ]; then + log 2 "put object command requires command type, source, destination" + return 1 + fi + local exit_code=0 + local error + if [[ $1 == 's3api' ]] || [[ $1 == 's3' ]]; then + # shellcheck disable=SC2086 + error=$(aws --no-verify-ssl s3 cp "$(dirname "$2")" s3://"$3" --recursive --exclude="*" --include="$2" 2>&1) || exit_code=$? + elif [[ $1 == 's3cmd' ]]; then + # shellcheck disable=SC2086 + error=$(s3cmd "${S3CMD_OPTS[@]}" --no-check-certificate put $2 "s3://$3/" 2>&1) || exit_code=$? + elif [[ $1 == 'mc' ]]; then + # shellcheck disable=SC2086 + error=$(mc --insecure cp $2 "$MC_ALIAS"/"$3" 2>&1) || exit_code=$? + else + log 2 "invalid command type $1" + return 1 + fi + if [ $exit_code -ne 0 ]; then + log 2 "error copying object to bucket: $error" + return 1 + else + log 5 "$error" + fi + return 0 +} diff --git a/tests/drivers/copy_object/copy_object_rest.sh b/tests/drivers/copy_object/copy_object_rest.sh new file mode 100644 index 0000000..0db4e56 --- /dev/null +++ b/tests/drivers/copy_object/copy_object_rest.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# Copyright 2024 Versity Software +# This file is licensed under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +attempt_copy_object_to_directory_with_same_name() { + if [ $# -ne 3 ]; then + log 2 "'attempt_copy_object_to_directory_with_same_name' requires bucket name, key name, copy source" + return 1 + fi + if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OBJECT_KEY="$2/" COPY_SOURCE="$3" OUTPUT_FILE="$TEST_FILE_FOLDER/result.txt" ./tests/rest_scripts/copy_object.sh); then + log 2 "error copying object: $result" + return 1 + fi + if [ "$result" != "409" ]; then + log 2 "expected '409', was '$result'" + return 1 + fi + if ! check_xml_error_contains "$TEST_FILE_FOLDER/result.txt" "ObjectParentIsFile" "Object parent already exists as a file"; then + log 2 "error checking XML" + return 1 + fi + return 0 +} + +copy_object_invalid_copy_source() { + if [ $# -ne 1 ]; then + log 2 "'copy_object_invalid_copy_source' requires bucket name" + return 1 + fi + if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$BUCKET_ONE_NAME" OBJECT_KEY="dummy-copy" COPY_SOURCE="dummy" OUTPUT_FILE="$TEST_FILE_FOLDER/result.txt" ./tests/rest_scripts/copy_object.sh); then + log 2 "error copying object: $result" + return 1 + fi + if [ "$result" != "400" ]; then + log 2 "expected '400', was '$result' $(cat "$TEST_FILE_FOLDER/result.txt")" + return 1 + fi + if ! check_xml_element_contains "$TEST_FILE_FOLDER/result.txt" "InvalidArgument" "Error" "Code"; then + log 2 "error checking XML error code" + return 1 + fi + return 0 +} + +copy_object_copy_source_and_payload() { + if [ $# -ne 3 ]; then + log 2 "'copy_object_copy_source_and_payload' requires bucket name, source key, and local data file" + return 1 + fi + if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OBJECT_KEY="${2}-copy" COPY_SOURCE="$1/$2" DATA_FILE="$3" OUTPUT_FILE="$TEST_FILE_FOLDER/result.txt" ./tests/rest_scripts/copy_object.sh); then + log 2 "error copying object: $result" + return 1 + fi + if [ "$result" != "400" ]; then + log 2 "expected '400', was '$result' $(cat "$TEST_FILE_FOLDER/result.txt")" + return 1 + fi + log 5 "result: $(cat "$TEST_FILE_FOLDER/result.txt")" + if ! check_xml_element_contains "$TEST_FILE_FOLDER/result.txt" "InvalidRequest" "Error" "Code"; then + log 2 "error checking XML error code" + return 1 + fi + return 0 +} diff --git a/tests/rest_scripts/copy_object.sh b/tests/rest_scripts/copy_object.sh index afc5780..ad06ef0 100755 --- a/tests/rest_scripts/copy_object.sh +++ b/tests/rest_scripts/copy_object.sh @@ -24,28 +24,27 @@ bucket_name="$BUCKET_NAME" key="$OBJECT_KEY" # shellcheck disable=SC2153 copy_source="$COPY_SOURCE" +# for testing only +# shellcheck disable=SC2153 +data_file="$DATA_FILE" current_date_time=$(date -u +"%Y%m%dT%H%M%SZ") -canonical_request="PUT -/$bucket_name/$key - -host:$host -x-amz-content-sha256:UNSIGNED-PAYLOAD -x-amz-copy-source:$copy_source -x-amz-date:$current_date_time - -host;x-amz-content-sha256;x-amz-copy-source;x-amz-date -UNSIGNED-PAYLOAD" +cr_data=("PUT" "/$bucket_name/$key" "") +cr_data+=("host:$host" "x-amz-content-sha256:UNSIGNED-PAYLOAD") +cr_data+=("x-amz-copy-source:$copy_source") +cr_data+=("x-amz-date:$current_date_time") +build_canonical_request "${cr_data[@]}" # shellcheck disable=SC2119 create_canonical_hash_sts_and_signature curl_command+=(curl -ks -w "\"%{http_code}\"" -X PUT "$AWS_ENDPOINT_URL/$bucket_name/$key") -curl_command+=(-H "\"Authorization: AWS4-HMAC-SHA256 Credential=$aws_access_key_id/$year_month_day/$aws_region/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-copy-source;x-amz-date,Signature=$signature\"") -curl_command+=(-H "\"x-amz-content-sha256: UNSIGNED-PAYLOAD\"" --H "\"x-amz-copy-source: $copy_source\"" --H "\"x-amz-date: $current_date_time\"") +curl_command+=(-H "\"Authorization: AWS4-HMAC-SHA256 Credential=$aws_access_key_id/$year_month_day/$aws_region/s3/aws4_request,SignedHeaders=$param_list,Signature=$signature\"") +curl_command+=("${header_fields[@]}") curl_command+=(-o "$OUTPUT_FILE") +if [ "$data_file" != "" ]; then + curl_command+=(-T "$data_file") +fi # shellcheck disable=SC2154 -eval "${curl_command[*]}" 2>&1 \ No newline at end of file +eval "${curl_command[*]}" 2>&1 diff --git a/tests/test_rest.sh b/tests/test_rest.sh index da7b3c0..296c157 100755 --- a/tests/test_rest.sh +++ b/tests/test_rest.sh @@ -29,6 +29,7 @@ source ./tests/commands/put_bucket_versioning.sh source ./tests/commands/put_object.sh source ./tests/commands/put_object_retention.sh source ./tests/commands/put_object_tagging.sh +source ./tests/drivers/copy_object/copy_object_rest.sh source ./tests/logger.sh source ./tests/setup.sh source ./tests/util/util_acl.sh @@ -603,3 +604,28 @@ test_file="test_file" run upload_part_without_upload_id "$BUCKET_ONE_NAME" "$test_file" assert_success } + +@test "REST - copy object w/invalid copy source" { + run setup_bucket_and_file "$BUCKET_ONE_NAME" "$test_file" + assert_success + + run put_object "rest" "$TEST_FILE_FOLDER/$test_file" "$BUCKET_ONE_NAME" "$test_file" + assert_success + + run copy_object_invalid_copy_source "$BUCKET_ONE_NAME" + assert_success +} + +@test "REST - copy object w/copy source and payload" { + if [ "$DIRECT" != "true" ]; then + skip "https://github.com/versity/versitygw/issues/1242" + fi + run setup_bucket_and_file "$BUCKET_ONE_NAME" "$test_file" + assert_success + + run put_object "rest" "$TEST_FILE_FOLDER/$test_file" "$BUCKET_ONE_NAME" "$test_file" + assert_success + + run copy_object_copy_source_and_payload "$BUCKET_ONE_NAME" "$test_file" "$TEST_FILE_FOLDER/$test_file" + assert_success +} diff --git a/tests/test_s3api_object.sh b/tests/test_s3api_object.sh index bfd7a25..a4ce7cc 100755 --- a/tests/test_s3api_object.sh +++ b/tests/test_s3api_object.sh @@ -50,6 +50,7 @@ source ./tests/commands/put_object_lock_configuration.sh source ./tests/commands/put_object_retention.sh source ./tests/commands/put_public_access_block.sh source ./tests/commands/select_object_content.sh +source ./tests/drivers/copy_object/copy_object_rest.sh export RUN_USERS=true diff --git a/tests/util/util_object.sh b/tests/util/util_object.sh index 7fde80d..02a1fba 100644 --- a/tests/util/util_object.sh +++ b/tests/util/util_object.sh @@ -175,35 +175,6 @@ get_object_metadata() { return 0 } -put_object_multiple() { - if [ $# -ne 3 ]; then - log 2 "put object command requires command type, source, destination" - return 1 - fi - local exit_code=0 - local error - if [[ $1 == 's3api' ]] || [[ $1 == 's3' ]]; then - # shellcheck disable=SC2086 - error=$(aws --no-verify-ssl s3 cp "$(dirname "$2")" s3://"$3" --recursive --exclude="*" --include="$2" 2>&1) || exit_code=$? - elif [[ $1 == 's3cmd' ]]; then - # shellcheck disable=SC2086 - error=$(s3cmd "${S3CMD_OPTS[@]}" --no-check-certificate put $2 "s3://$3/" 2>&1) || exit_code=$? - elif [[ $1 == 'mc' ]]; then - # shellcheck disable=SC2086 - error=$(mc --insecure cp $2 "$MC_ALIAS"/"$3" 2>&1) || exit_code=$? - else - log 2 "invalid command type $1" - return 1 - fi - if [ $exit_code -ne 0 ]; then - log 2 "error copying object to bucket: $error" - return 1 - else - log 5 "$error" - fi - return 0 -} - # add object to versitygw if it doesn't exist # params: source file, destination copy location # return 0 for success or already exists, 1 for failure @@ -484,22 +455,3 @@ put_object_rest_check_expires_header() { fi return 0 } - -attempt_copy_object_to_directory_with_same_name() { - if [ $# -ne 3 ]; then - log 2 "'attempt_copy_object_to_directory_with_same_name' requires bucket name, key name, copy source" - return 1 - fi - if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OBJECT_KEY="$2/" COPY_SOURCE="$3" OUTPUT_FILE="$TEST_FILE_FOLDER/result.txt" ./tests/rest_scripts/copy_object.sh); then - log 2 "error copying object: $result" - return 1 - fi - if [ "$result" != "409" ]; then - log 2 "expected '409', was '$result'" - return 1 - fi - if ! check_xml_error_contains "$TEST_FILE_FOLDER/result.txt" "ObjectParentIsFile" "Object parent already exists as a file"; then - log 2 "error checking XML" - return 1 - fi -}