diff --git a/tests/commands/create_presigned_url.sh b/tests/commands/create_presigned_url.sh index 3ebab08d..56ea7b32 100644 --- a/tests/commands/create_presigned_url.sh +++ b/tests/commands/create_presigned_url.sh @@ -1,27 +1,32 @@ #!/usr/bin/env bash create_presigned_url() { - if [[ $# -ne 3 ]]; then - log 2 "create presigned url function requires command type, bucket, and filename" + if ! check_param_count_v2 "client, bucket, key" 3 $#; then return 1 fi + local response presign_result=0 presigned_url local presign_result=0 if [[ $1 == 's3api' ]]; then - presigned_url=$(send_command aws s3 presign "s3://$2/$3" --expires-in 900) || presign_result=$? + response=$(send_command aws s3 presign "s3://$2/$3" --expires-in 900 2>&1) || presign_result=$? elif [[ $1 == 's3cmd' ]]; then - presigned_url=$(send_command s3cmd --no-check-certificate "${S3CMD_OPTS[@]}" signurl "s3://$2/$3" "$(echo "$(date +%s)" + 900 | bc)") || presign_result=$? + response=$(send_command s3cmd --no-check-certificate "${S3CMD_OPTS[@]}" signurl "s3://$2/$3" "$(echo "$(date +%s)" + 900 | bc)" 2>&1) || presign_result=$? elif [[ $1 == 'mc' ]]; then - presigned_url_data=$(send_command mc --insecure share download --recursive "$MC_ALIAS/$2/$3") || presign_result=$? - presigned_url="${presigned_url_data#*Share: }" + response=$(send_command mc --insecure share download --recursive "$MC_ALIAS/$2/$3" 2>&1) || presign_result=$? else - log 2 "unrecognized command type $1" + log 2 "unrecognized client type $1" return 1 fi if [[ $presign_result -ne 0 ]]; then - log 2 "error generating presigned url: $presigned_url" + log 2 "error generating presigned url: $response" return 1 fi - export presigned_url + if [ "$1" == 'mc' ]; then + presigned_url=$(echo "$response" | grep "Share: " | sed 's/.*Share: //') + presigned_url="${presigned_url//$'\r'/}" + else + presigned_url="$response" + fi + echo "$presigned_url" return 0 } diff --git a/tests/commands/get_object_lock_configuration.sh b/tests/commands/get_object_lock_configuration.sh index d4394412..81a6f7b1 100644 --- a/tests/commands/get_object_lock_configuration.sh +++ b/tests/commands/get_object_lock_configuration.sh @@ -20,21 +20,27 @@ get_object_lock_configuration() { if ! check_param_count "get_object_lock_configuration" "client, bucket name" 2 $#; then return 1 fi + local response response_code response_data lock_config + if [ "$1" == 'rest' ]; then - if ! get_object_lock_configuration_rest "$2"; then - log 2 "error getting REST object lock configuration" - get_object_lock_config_err=$(cat "$TEST_FILE_FOLDER/object-lock-config.txt") + if ! response=$(get_object_lock_configuration_rest "$2" 2>&1); then + log 2 "error getting REST object lock configuration: $response" return 1 fi + read -r response_code response_data <<< "$response" + if [ "$response_code" != "200" ]; then + log 2 "get_object_lock_config returned error: $(cat "$response_data")" + return 1 + fi + lock_config="$(cat "$response_data")" else - if ! lock_config=$(send_command aws --no-verify-ssl s3api get-object-lock-configuration --bucket "$2" 2>&1); then - log 2 "error obtaining lock config: $lock_config" - # shellcheck disable=SC2034 - get_object_lock_config_err=$lock_config + if ! response=$(send_command aws --no-verify-ssl s3api get-object-lock-configuration --bucket "$2" 2>&1); then + log 2 "error obtaining lock config: $response" return 1 fi + lock_config=$(echo "$response" | grep -v "InsecureRequestWarning") + echo "$lock_config" fi - lock_config=$(echo "$lock_config" | grep -v "InsecureRequestWarning") return 0 } @@ -43,15 +49,20 @@ get_object_lock_configuration_rest() { if ! check_param_count "get_object_lock_configuration_rest" "bucket name" 1 $#; then return 1 fi - if ! result=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OUTPUT_FILE="$TEST_FILE_FOLDER/object-lock-config.txt" ./tests/rest_scripts/get_object_lock_config.sh); then - log 2 "error getting lock configuration: $result" + local response output_file response_code return_code=0 + + if ! response=$(get_file_name 2>&1); then + log 2 "error getting file name: $response" return 1 fi - if [[ "$result" != "200" ]]; then - log 2 "expected '200', returned '$result': $(cat "$TEST_FILE_FOLDER/object-lock-config.txt")" + output_file="$response" + + if ! response=$(COMMAND_LOG="$COMMAND_LOG" BUCKET_NAME="$1" OUTPUT_FILE="$TEST_FILE_FOLDER/$output_file" ./tests/rest_scripts/get_object_lock_config.sh 2>&1); then + log 2 "error getting lock configuration: $response" return 1 fi - lock_config="$(cat "$TEST_FILE_FOLDER/object-lock-config.txt")" - log 5 "lock config: $lock_config" - return 0 + response_code="$response" + + echo "$response_code" "$TEST_FILE_FOLDER/$output_file" + return $return_code } \ No newline at end of file diff --git a/tests/drivers/create_bucket/create_bucket.sh b/tests/drivers/create_bucket/create_bucket.sh index 1e850d74..ca572295 100644 --- a/tests/drivers/create_bucket/create_bucket.sh +++ b/tests/drivers/create_bucket/create_bucket.sh @@ -14,7 +14,7 @@ # specific language governing permissions and limitations # under the License. -source ./tests/util/util_mc.sh +source ./tests/drivers/delete_bucket/delete_bucket_mc.sh source ./tests/logger.sh create_and_check_bucket_invalid_name() { diff --git a/tests/drivers/create_presigned_url/create_presigned_url.sh b/tests/drivers/create_presigned_url/create_presigned_url.sh new file mode 100644 index 00000000..a95803cb --- /dev/null +++ b/tests/drivers/create_presigned_url/create_presigned_url.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Copyright 2026 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. + +source ./tests/commands/create_presigned_url.sh + +create_check_presigned_url() { + if ! check_param_count_v2 "client, bucket, key, save location" 4 $#; then + return 1 + fi + local response presigned_url + + if ! response=$(create_presigned_url "$1" "$2" "$3" 2>&1); then + log 2 "error creating presigned URL: $response" + return 1 + fi + presigned_url="$response" + + if ! response=$(curl -k -v "$presigned_url" -o "$4"); then + log 2 "error downloading file with curl: $response" + return 1 + fi + return 0 +} \ No newline at end of file diff --git a/tests/util/util_mc.sh b/tests/drivers/delete_bucket/delete_bucket_mc.sh similarity index 97% rename from tests/util/util_mc.sh rename to tests/drivers/delete_bucket/delete_bucket_mc.sh index 3f4334c6..d9ae1dcb 100644 --- a/tests/util/util_mc.sh +++ b/tests/drivers/delete_bucket/delete_bucket_mc.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2024 Versity Software +# Copyright 2026 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 diff --git a/tests/drivers/get_object_lock_config/get_object_lock_config_rest.sh b/tests/drivers/get_object_lock_config/get_object_lock_config_rest.sh index baf43f27..3e4e4453 100644 --- a/tests/drivers/get_object_lock_config/get_object_lock_config_rest.sh +++ b/tests/drivers/get_object_lock_config/get_object_lock_config_rest.sh @@ -15,21 +15,51 @@ # under the License. check_object_lock_config() { - log 6 "check_object_lock_config" - if ! check_param_count "check_object_lock_config" "bucket" 1 $#; then + if ! check_param_count_v2 "bucket" 1 $#; then return 1 fi - lock_config_exists=true - if ! get_object_lock_configuration "rest" "$1"; then - # shellcheck disable=SC2154 - log 5 "lock config error: $get_object_lock_config_err" - if [[ "$get_object_lock_config_err" == *"does not exist"* ]]; then - # shellcheck disable=SC2034 - lock_config_exists=false + local exists="true" response response_code output_file + + if ! response=$(get_object_lock_configuration_rest "$1" 2>&1); then + log 2 "error checking object lock configuration: $response" + return 1 + fi + read -r response_code output_file <<< "$response" + + if [ "$response_code" != "200" ]; then + if grep "ObjectLockConfigurationNotFoundError" "$output_file" >/dev/null; then + exists="false" else - log 2 "error getting object lock config" + log 2 "unexpected GetObjectLockConfiguration error: '$(cat "$output_file")'" return 1 fi fi + log 5 "check object lock config response: $response" + echo "$exists" return 0 -} \ No newline at end of file +} + +check_object_lock_config_enabled_rest() { + if ! check_param_count "check_object_lock_config_enabled_rest" "bucket" 1 $#; then + return 1 + fi + local response response_code response_file enabled_value + + if ! response=$(get_object_lock_configuration_rest "$1" 2>&1); then + log 2 "error getting object lock config: $response" + return 1 + fi + read -r response_code response_file <<< "$response" + + if ! response=$(xmllint --xpath '//*[local-name()="ObjectLockEnabled"]/text()' "$response_file" 2>&1); then + log 2 "error getting object lock config enabled value: $response" + return 1 + fi + enabled_value="$response" + + if [[ "$enabled_value" != "Enabled" ]]; then + log 2 "expected 'Enabled', is '$enabled_value'" + return 1 + fi + return 0 +} diff --git a/tests/util/util_lock_config.sh b/tests/drivers/get_object_lock_config/get_object_lock_config_s3api.sh similarity index 61% rename from tests/util/util_lock_config.sh rename to tests/drivers/get_object_lock_config/get_object_lock_config_s3api.sh index 317345f8..23d809fb 100644 --- a/tests/util/util_lock_config.sh +++ b/tests/drivers/get_object_lock_config/get_object_lock_config_s3api.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2024 Versity Software +# Copyright 2026 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 @@ -20,10 +20,14 @@ get_and_check_object_lock_config() { if ! check_param_count "get_and_check_object_lock_config" "bucket, expected enabled value, expected governance mode, expected days" 4 $#; then return 1 fi - if ! get_object_lock_configuration "s3api" "$1"; then - log 2 "error getting object lock config" + local response lock_config + + if ! response=$(get_object_lock_configuration "s3api" "$1" 2>&1); then + log 2 "error getting object lock config: $response" return 1 fi + lock_config="$response" + # shellcheck disable=SC2154 log 5 "LOCK CONFIG: $lock_config" if ! object_lock_configuration=$(echo "$lock_config" | grep -v "InsecureRequestWarning" | jq -r ".ObjectLockConfiguration" 2>&1); then @@ -65,10 +69,14 @@ get_check_object_lock_config_enabled() { if ! check_param_count "get_check_object_lock_config_enabled" "bucket" 1 $#; then return 1 fi - if ! get_object_lock_configuration "s3api" "$1"; then - log 2 "error getting lock configuration" + local response lock_config + + if ! response=$(get_object_lock_configuration "s3api" "$1" 2>&1); then + log 2 "error getting lock configuration: $response" return 1 fi + lock_config="$response" + # shellcheck disable=SC2154 log 5 "Lock config: $lock_config" if ! enabled=$(echo "$lock_config" | jq -r ".ObjectLockConfiguration.ObjectLockEnabled" 2>&1); then @@ -81,48 +89,3 @@ get_check_object_lock_config_enabled() { fi return 0 } - -check_no_object_lock_config_rest() { - if ! check_param_count "check_no_object_lock_config_rest" "bucket" 1 $#; then - return 1 - fi - if get_object_lock_configuration_rest "$1"; then - log 2 "object lock config should be missing" - return 1 - fi - log 5 "object lock config: $(cat "$TEST_FILE_FOLDER/object-lock-config.txt")" - # shellcheck disable=SC2154 - if [[ "$result" != "404" ]]; then - log 2 "incorrect response code: $reply" - return 1 - fi - if ! error=$(xmllint --xpath '//*[local-name()="Code"]/text()' "$TEST_FILE_FOLDER/object-lock-config.txt" 2>&1); then - log 2 "error getting object lock config error: $error" - return 1 - fi - if [[ "$error" != "ObjectLockConfigurationNotFoundError" ]]; then - log 2 "unexpected error: $error" - return 1 - fi - return 0 -} - -check_object_lock_config_enabled_rest() { - if ! check_param_count "check_object_lock_config_enabled_rest" "bucket" 1 $#; then - return 1 - fi - if ! get_object_lock_configuration_rest "$1"; then - log 2 "error getting object lock config" - return 1 - fi - log 5 "object lock config: $(cat "$TEST_FILE_FOLDER/object-lock-config.txt")" - if ! enabled=$(xmllint --xpath '//*[local-name()="ObjectLockEnabled"]/text()' "$TEST_FILE_FOLDER/object-lock-config.txt" 2>&1); then - log 2 "error getting object lock config enabled value: $enabled" - return 1 - fi - if [[ "$enabled" != "Enabled" ]]; then - log 2 "expected 'Enabled', is $enabled" - return 1 - fi - return 0 -} diff --git a/tests/drivers/list_parts/list_parts_rest.sh b/tests/drivers/list_parts/list_parts_rest.sh index 918ed8c0..95c07412 100644 --- a/tests/drivers/list_parts/list_parts_rest.sh +++ b/tests/drivers/list_parts/list_parts_rest.sh @@ -129,3 +129,115 @@ upload_check_part() { echo "$payload_part" return 0 } + +check_part_elements() { + if ! check_param_count_v2 "part, part number, etag, size" 4 $#; then + return 1 + fi + local part="$1" part_number="$2" etag="$3" size="$4" + + if ! response=$(check_xml_element_inside_string "$part" "$part_number" "PartNumber" 2>&1); then + log 2 "error checking PartNumber: $response" + return 1 + fi + if ! response=$(check_xml_element_inside_string "$part" "$etag" "ETag" 2>&1); then + log 2 "error checking ETag for part '$part_number' in array: $response" + return 1 + fi + if ! response=$(check_xml_element_inside_string "$part" "$size" "Size" 2>&1); then + log 2 "error checking Size for part '$part_number' in array: $response" + return 1 + fi + return 0 +} + +check_list_parts_parts() { + if ! check_param_count_gt "data string, part number marker, next part number, etag/size pairs" 3 $#; then + return 1 + fi + local data_string="$1" part_number_marker="$2" next_part_number_marker="$3" + local -a etag_size_pairs=("${@:4}") + local response part_number + local -a parts=() + + if ! response=$(get_elements_inside_string "$data_string" "Part" 2>&1); then + log 2 "error getting Part elements: $response" + return 1 + fi + log 5 "parts: $response" + if [ "$response" != "" ]; then + mapfile -t parts <<< "$response" + fi + + local part_count=$((next_part_number_marker-part_number_marker)) + if [ $part_count -lt 0 ]; then + part_count=0 + fi + if [ ${#parts[@]} -ne "$part_count" ]; then + log 2 "part count mismatch, expected '$part_count', actual '${#parts[@]}'" + return 1 + fi + if [ $((part_count*2)) -ne "${#etag_size_pairs[@]}" ]; then + log 2 "part count and etag/size mismatch, expected '$((part_count*2))' fields, actual is '${#etag_size_pairs[@]}'" + return 1 + fi + + for ((i=0; i&1); then + log 2 "error getting response: $response" + return 1 + fi + list_parts_result="$response" + + element_names=("Bucket" "Key" "UploadId" "MaxParts" "PartNumberMarker" "NextPartNumberMarker") + expected_values=("$bucket" "$key" "$upload_id" "$max_parts" "$part_number_marker" "$next_part_number_marker") + for ((i=0; i<${#element_names[@]}; i++))do + if ! response=$(check_xml_element_inside_string "$list_parts_result" "${expected_values[$i]}" "${element_names[$i]}" 2>&1); then + log 2 "error checking element with name '${element_names[$i]}': $response" + return 1 + fi + done + + if ! check_list_parts_parts "$list_parts_result" "$part_number_marker" "$next_part_number_marker" "${etag_size_pairs[@]}"; then + log 2 "error checking parts in parts list" + return 1 + fi + return 0 +} + +list_parts_check_with_marker_and_max_parts() { + if ! check_param_count_gt "bucket name, key, upload ID, max parts, part number marker, expected next part number marker, etag/size pairs" 6 $#; then + return 1 + fi + if ! send_rest_go_command_callback "200" "check_list_with_marker_and_max_parts" "-bucketName" "$1" "-objectKey" "$2" "-query" "part-number-marker=$5&max-parts=$4&uploadId=$3" "--" "$@"; then + log 2 "error sending ListParts command and checking callback" + return 1 + fi + return 0 +} diff --git a/tests/drivers/upload_part/upload_part_rest.sh b/tests/drivers/upload_part/upload_part_rest.sh index e7d05cb7..ff8f0411 100644 --- a/tests/drivers/upload_part/upload_part_rest.sh +++ b/tests/drivers/upload_part/upload_part_rest.sh @@ -111,4 +111,4 @@ perform_full_multipart_upload_with_checksum_before_completion() { echo "$upload_id" echo "$response" return 0 -} \ No newline at end of file +} diff --git a/tests/drivers/user.sh b/tests/drivers/user.sh index 7f6e4c2a..aa9ed113 100644 --- a/tests/drivers/user.sh +++ b/tests/drivers/user.sh @@ -124,15 +124,17 @@ reset_bucket() { return 1 fi log 6 "reset bucket '$1'" + local response lock_config_exists if [[ $LOG_LEVEL_INT -ge 5 ]] && ! log_bucket_policy "$1"; then log 3 "error logging bucket policy" fi - if ! check_object_lock_config "$1"; then - log 2 "error checking object lock config" + if ! response=$(check_object_lock_config "$1" 2>&1); then + log 2 "error checking object lock config: $response" return 1 fi + lock_config_exists="$response" if [[ "$DIRECT" != "true" ]] && ! add_governance_bypass_policy "$1"; then log 2 "error adding governance bypass policy" @@ -169,6 +171,7 @@ reset_bucket() { log 2 "error changing bucket owner back to root" return 1 fi + return 0 } get_user_id() { diff --git a/tests/drivers/xml.sh b/tests/drivers/xml.sh index 3d42c076..854eee0b 100644 --- a/tests/drivers/xml.sh +++ b/tests/drivers/xml.sh @@ -14,69 +14,7 @@ # specific language governing permissions and limitations # under the License. -build_xpath_string() { - if ! check_param_count_gt "XML tree" 1 $#; then - return 1 - fi - if ! build_xpath_string_for_element "$@"; then - return 1 - fi - xpath+='/text()' -} - -get_xpath_segment() { - if ! check_param_count_gt "XML element name" 1 $#; then - return 1 - fi - if [ "$1" == "" ]; then - log 2 "element has no name" - return 1 - fi - if [[ "$1" =~ [[:space:]] ]]; then - log 2 "element '$1' contains a space" - return 1 - fi - echo '*[local-name()="'"$1"'"]' -} - - -build_xpath_string_for_element() { - if ! check_param_count_gt "XML tree" 1 $#; then - return 1 - fi - local xpath='//' - for ((idx=1;idx<=$#;idx++)); do - if ! segment=$(get_xpath_segment "${!idx}" 2>&1); then - log 2 "error getting xpath segment: $segment" - return 1 - fi - xpath+="$segment" - if [ "$idx" != $# ]; then - xpath+='/' - fi - done - echo "$xpath" - return 0 -} - -get_inner_xpath_string_for_element() { - if ! check_param_count_gt "compare element, XML tree" 2 $#; then - return 1 - fi - local xpath='[' - for ((idx=2;idx<=$#;idx++)); do - if ! xpath+=$(get_xpath_segment "${!idx}" 2>&1); then - log 2 "error getting xpath segment: $xpath" - return 1 - fi - if [ "$idx" != $# ]; then - xpath+='/' - fi - done - xpath+="='$1']" - echo "$xpath" - return 0 -} +source ./tests/drivers/xml_string.sh check_for_empty_or_nonexistent_element() { if ! check_param_count_gt "data file, XML tree" 2 $#; then @@ -167,52 +105,6 @@ check_xml_element() { return 0 } -check_xml_element_inside_string() { - if ! check_param_count_gt "string, expected value, XML tree" 3 $#; then - return 1 - fi - if ! data_file=$(get_file_name 2>&1); then - log 2 "error getting data file: $data_file" - return 1 - fi - echo -n "$1" > "$TEST_FILE_FOLDER/$data_file" - if ! check_xml_element "$TEST_FILE_FOLDER/$data_file" "$2" "${@:3}"; then - log 2 "error checking XML element" - return 1 - fi - return 0 -} - -get_element_text_inside_string() { - if ! check_param_count_gt "string, XML tree" 2 $#; then - return 1 - fi - local response xpath result - - if ! response=$(build_xpath_string_for_element "${@:2}" 2>&1); then - log 2 "error building XPath search string: $response" - return 1 - fi - xpath="$response" - - result=$(echo "$1" | xmllint --xpath "boolean($xpath)" - 2>&1) - if [ "$result" == "false" ]; then - log 2 "element matching '$xpath' doesn't exist" - return 1 - fi - - if ! response=$(echo "$1" | xmllint --xpath "${xpath}/text()" - 2>&1); then - if [[ "$response" == *"XPath set is empty"* ]]; then - echo "" - return 0 - fi - log 2 "error getting element text: $response" - return 1 - fi - echo "$response" - return 0 -} - check_xml_element_contains() { if [ $# -lt 3 ]; then log 2 "'check_xml_element_contains' requires data source, expected value, XML tree" diff --git a/tests/drivers/xml_string.sh b/tests/drivers/xml_string.sh new file mode 100644 index 00000000..c3e02e78 --- /dev/null +++ b/tests/drivers/xml_string.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash + +# Copyright 2026 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. + +build_xpath_string() { + if ! check_param_count_gt "XML tree" 1 $#; then + return 1 + fi + local response xpath + + if ! response=$(build_xpath_string_for_element "$@" 2>&1); then + log 2 "error building xpath: $response" + return 1 + fi + xpath+='/text()' + echo "$xpath" + return 0 +} + +get_xpath_segment() { + if ! check_param_count_gt "XML element name" 1 $#; then + return 1 + fi + if [ "$1" == "" ]; then + log 2 "element has no name" + return 1 + fi + if [[ "$1" =~ [[:space:]] ]]; then + log 2 "element '$1' contains a space" + return 1 + fi + echo '*[local-name()="'"$1"'"]' +} + + +build_xpath_string_for_element() { + if ! check_param_count_gt "XML tree" 1 $#; then + return 1 + fi + local xpath='//' + for ((idx=1;idx<=$#;idx++)); do + if ! segment=$(get_xpath_segment "${!idx}" 2>&1); then + log 2 "error getting xpath segment: $segment" + return 1 + fi + xpath+="$segment" + if [ "$idx" != $# ]; then + xpath+='/' + fi + done + echo "$xpath" + return 0 +} + +get_inner_xpath_string_for_element() { + if ! check_param_count_gt "compare element, XML tree" 2 $#; then + return 1 + fi + local xpath='[' + for ((idx=2;idx<=$#;idx++)); do + if ! xpath+=$(get_xpath_segment "${!idx}" 2>&1); then + log 2 "error getting xpath segment: $xpath" + return 1 + fi + if [ "$idx" != $# ]; then + xpath+='/' + fi + done + xpath+="='$1']" + echo "$xpath" + return 0 +} + +check_xml_element_inside_string() { + if ! check_param_count_gt "string, expected value, XML tree" 3 $#; then + return 1 + fi + local response xml_value + + if ! response=$(get_element_text_inside_string "$1" "${@:3}" 2>&1); then + log 2 "error getting actual value: $response" + return 1 + fi + xml_value="$response" + + if [ "$xml_value" != "$2" ]; then + log 2 "expected value '$2', was '$xml_value'" + return 1 + fi + return 0 +} + +get_elements_inside_string() { + if ! check_param_count_gt "string, XML tree" 2 $#; then + return 1 + fi + + local response xpath + if ! response=$(build_xpath_string_for_element "${@:2}" 2>&1); then + log 2 "error building XPath search string: $response" + return 1 + fi + xpath="$response" + + if ! response=$(xmllint --xpath "${xpath}" - <<< "$1" 2>&1); then + if [[ "$response" == *"XPath set is empty"* ]]; then + echo "" + return 0 + fi + log 2 "error getting element text: $response" + return 1 + fi + echo "$response" + return 0 +} + +get_element_text_inside_string() { + if ! check_param_count_gt "string, XML tree" 2 $#; then + return 1 + fi + local response xpath result + + if ! response=$(build_xpath_string_for_element "${@:2}" 2>&1); then + log 2 "error building XPath search string: $response" + return 1 + fi + xpath="$response" + + result=$(xmllint --xpath "boolean($xpath)" - <<< "$1" 2>&1) + if [ "$result" == "false" ]; then + log 2 "element matching '$xpath' doesn't exist" + return 1 + fi + + if ! response=$(xmllint --xpath "${xpath}/text()" - <<< "$1" 2>&1); then + if [[ "$response" == *"XPath set is empty"* ]]; then + echo "" + return 0 + fi + log 2 "error getting element text: $response" + return 1 + fi + echo "$response" + return 0 +} + + diff --git a/tests/test_common.sh b/tests/test_common.sh index c9413c3e..7eda0859 100644 --- a/tests/test_common.sh +++ b/tests/test_common.sh @@ -30,11 +30,11 @@ source ./tests/commands/put_object_tagging.sh source ./tests/commands/put_object.sh source ./tests/commands/put_public_access_block.sh source ./tests/drivers/create_bucket/create_bucket_rest.sh +source ./tests/drivers/create_presigned_url/create_presigned_url.sh source ./tests/drivers/file.sh source ./tests/drivers/params.sh source ./tests/util/util_object.sh source ./tests/util/util_policy.sh -source ./tests/util/util_presigned_url.sh # param: command type # fail on test failure diff --git a/tests/test_rest_bucket.sh b/tests/test_rest_bucket.sh index 872395b3..0b09e076 100755 --- a/tests/test_rest_bucket.sh +++ b/tests/test_rest_bucket.sh @@ -23,13 +23,13 @@ source ./tests/commands/list_buckets.sh source ./tests/drivers/create_bucket/create_bucket_rest.sh source ./tests/drivers/get_bucket_ownership_controls/get_bucket_ownership_controls_rest.sh source ./tests/drivers/get_bucket_tagging/get_bucket_tagging_rest.sh +source ./tests/drivers/get_object_lock_config/get_object_lock_config_rest.sh source ./tests/drivers/head_bucket/head_bucket_s3api.sh source ./tests/drivers/list_buckets/list_buckets_rest.sh source ./tests/drivers/put_bucket_ownership_controls/put_bucket_ownership_controls_rest.sh source ./tests/drivers/put_bucket_tagging/put_bucket_tagging_rest.sh source ./tests/logger.sh source ./tests/setup.sh -source ./tests/util/util_lock_config.sh source ./tests/util/util_public_access_block.sh source ./tests/util/util_rest.sh @@ -92,8 +92,9 @@ export RUN_USERS=true run setup_bucket_v2 "$bucket_name" assert_success - run check_no_object_lock_config_rest "$bucket_name" + run check_object_lock_config "$bucket_name" assert_success + assert_output "false" run get_bucket_name "$BUCKET_ONE_NAME" assert_success diff --git a/tests/test_rest_list_parts.sh b/tests/test_rest_list_parts.sh new file mode 100755 index 00000000..0e8bf9f9 --- /dev/null +++ b/tests/test_rest_list_parts.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bats + +# Copyright 2026 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. + +load ./bats-support/load +load ./bats-assert/load + +source ./tests/drivers/create_bucket/create_bucket_rest.sh +source ./tests/setup.sh + +@test "REST - ListParts - invalid part number marker" { + local bucket_name file_name upload_id invalid_marker="a" + local -a parts=() + + run setup_bucket_and_large_file_v3 "$BUCKET_ONE_NAME" + assert_success + read -r bucket_name file_name <<< "$output" + + run split_file "$TEST_FILE_FOLDER/$file_name" 4 + assert_success + read -r -a parts <<< "$output" + + run create_multipart_upload_rest "$bucket_name" "$file_name" "" "parse_upload_id" + assert_success + upload_id=$output + + run upload_part_rest "$bucket_name" "$file_name" "$upload_id" 1 "${parts[0]}" + assert_success + + run send_rest_go_command_expect_error_with_arg_name_value "400" "InvalidArgument" "not an integer or within integer range" \ + "part-number-marker" "$invalid_marker" \ + "-bucketName" "$bucket_name" "-objectKey" "$file_name" "-query" "part-number-marker=$invalid_marker&uploadId=$upload_id" + assert_success +} + +@test "REST - ListParts - part number marker" { + local bucket_name file_name upload_id + local -a parts=() sizes=() etags=() + + run setup_bucket_and_large_file_v3 "$BUCKET_ONE_NAME" + assert_success + read -r bucket_name file_name <<< "$output" + + run create_multipart_upload_rest "$bucket_name" "$file_name" "" "parse_upload_id" + assert_success + upload_id=$output + + run split_file "$TEST_FILE_FOLDER/$file_name" 4 + assert_success + read -r -a parts <<< "$output" + + for ((i=0; i<${#parts[@]}; i++)) do + run get_file_size "${parts[$i]}" + assert_success + sizes+=("$output") + + run upload_part_rest "$bucket_name" "$file_name" "$upload_id" "$((i+1))" "${parts[i]}" + assert_success + etags+=("$output") + done + + run list_parts_check_with_marker_and_max_parts "$bucket_name" "$file_name" "$upload_id" 1 0 1 "${etags[0]}" "${sizes[0]}" + assert_success + + run list_parts_check_with_marker_and_max_parts "$bucket_name" "$file_name" "$upload_id" 2 1 3 "${etags[1]}" "${sizes[1]}" "${etags[2]}" "${sizes[2]}" + assert_success + + run list_parts_check_with_marker_and_max_parts "$bucket_name" "$file_name" "$upload_id" 2 3 4 "${etags[3]}" "${sizes[3]}" + assert_success + + run list_parts_check_with_marker_and_max_parts "$bucket_name" "$file_name" "$upload_id" 1 4 0 + assert_success +} diff --git a/tests/test_s3api_bucket.sh b/tests/test_s3api_bucket.sh index 1d893e77..96b28063 100755 --- a/tests/test_s3api_bucket.sh +++ b/tests/test_s3api_bucket.sh @@ -50,11 +50,11 @@ source ./tests/drivers/get_bucket_acl/get_bucket_acl.sh source ./tests/drivers/get_bucket_location/get_bucket_location.sh source ./tests/drivers/get_bucket_tagging/get_bucket_tagging.sh source ./tests/drivers/get_bucket_tagging/get_bucket_tagging_rest.sh +source ./tests/drivers/get_object_lock_config/get_object_lock_config_s3api.sh source ./tests/drivers/head_bucket/head_bucket_rest.sh source ./tests/drivers/head_bucket/head_bucket_s3api.sh source ./tests/drivers/list_buckets/list_buckets.sh source ./tests/drivers/put_bucket_ownership_controls/put_bucket_ownership_controls_rest.sh -source ./tests/util/util_lock_config.sh source ./tests/util/util_object.sh export RUN_USERS=true diff --git a/tests/test_s3api_object.sh b/tests/test_s3api_object.sh index 629ff6c6..ba7285a9 100755 --- a/tests/test_s3api_object.sh +++ b/tests/test_s3api_object.sh @@ -45,6 +45,7 @@ source ./tests/commands/select_object_content.sh source ./tests/drivers/copy_object/copy_object_rest.sh source ./tests/drivers/get_object_attributes/get_object_attributes_s3api.sh source ./tests/drivers/get_object_legal_hold/get_object_legal_hold.sh +source ./tests/drivers/get_object_lock_config/get_object_lock_config_s3api.sh source ./tests/drivers/get_object_retention/get_object_retention_s3api.sh source ./tests/drivers/get_object_tagging/get_object_tagging.sh source ./tests/drivers/list_buckets/list_buckets_rest.sh @@ -52,7 +53,6 @@ source ./tests/drivers/list_objects/list_objects.sh source ./tests/drivers/list_objects/list_objects_s3api.sh source ./tests/drivers/put_bucket_ownership_controls/put_bucket_ownership_controls_rest.sh source ./tests/drivers/file.sh -source ./tests/util/util_lock_config.sh source ./tests/util/util_object.sh source ./tests/test_s3api_root_inner.sh diff --git a/tests/util/util_object.sh b/tests/util/util_object.sh index 58001a44..599217e5 100644 --- a/tests/util/util_object.sh +++ b/tests/util/util_object.sh @@ -14,7 +14,6 @@ # specific language governing permissions and limitations # under the License. -source ./tests/util/util_mc.sh source ./tests/util/util_multipart.sh source ./tests/util/util_versioning.sh source ./tests/logger.sh @@ -44,6 +43,7 @@ source ./tests/commands/put_object_legal_hold.sh source ./tests/commands/put_object_lock_configuration.sh source ./tests/commands/upload_part_copy.sh source ./tests/commands/upload_part.sh +source ./tests/drivers/delete_bucket/delete_bucket_mc.sh source ./tests/drivers/head_object/head_object_rest.sh source ./tests/drivers/openssl.sh source ./tests/util/util_users.sh diff --git a/tests/util/util_presigned_url.sh b/tests/util/util_presigned_url.sh deleted file mode 100644 index e9a53a41..00000000 --- a/tests/util/util_presigned_url.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -source ./tests/commands/create_presigned_url.sh - -create_check_presigned_url() { - if [ $# -ne 4 ]; then - log 2 "'create_check_presigned_url' requires client, bucket, key, save location" - return 1 - fi - if ! create_presigned_url "$1" "$2" "$3"; then - log 2 "error creating presigned URL" - return 1 - fi - if ! error=$(curl -k -v "$presigned_url" -o "$4"); then - log 2 "error downloading file with curl: $error" - return 1 - fi - return 0 -} \ No newline at end of file