diff --git a/backend/posix/posix.go b/backend/posix/posix.go index e389593..eab959f 100644 --- a/backend/posix/posix.go +++ b/backend/posix/posix.go @@ -1231,6 +1231,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput) if errors.Is(err, fs.ErrNotExist) { return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrNoSuchUpload) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return s3response.CopyObjectResult{}, fmt.Errorf("stat uploadid: %w", err) } @@ -1258,6 +1261,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput) if errors.Is(err, fs.ErrNotExist) { return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrNoSuchKey) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return s3response.CopyObjectResult{}, fmt.Errorf("stat object: %w", err) } @@ -1413,6 +1419,12 @@ func (p *Posix) PutObject(ctx context.Context, po *s3.PutObjectInput) (string, e if err == nil && d.IsDir() { return "", s3err.GetAPIError(s3err.ErrExistingObjectIsDirectory) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return "", s3err.GetAPIError(s3err.ErrKeyTooLong) + } + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return "", fmt.Errorf("stat object: %w", err) + } f, err := p.openTmpFile(filepath.Join(*po.Bucket, metaTmpDir), *po.Bucket, *po.Key, contentLength, acct, doFalloc) @@ -1516,12 +1528,12 @@ func (p *Posix) DeleteObject(_ context.Context, input *s3.DeleteObjectInput) err objpath := filepath.Join(bucket, object) fi, err := os.Stat(objpath) - if errors.Is(err, fs.ErrNotExist) { - // AWS returns success if the object does not exist - return nil - } if err != nil { - return fmt.Errorf("stat object: %w", err) + // AWS returns success if the object does not exist or + // is invalid somehow. + // TODO: log if !errors.Is(err, fs.ErrNotExist) somewhere? + + return nil } if strings.HasSuffix(object, "/") && !fi.IsDir() { // requested object is expecting a directory with a trailing @@ -1642,6 +1654,9 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return nil, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return nil, fmt.Errorf("stat object: %w", err) } @@ -1785,6 +1800,9 @@ func (p *Posix) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s3. if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrInvalidPart) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return nil, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return nil, fmt.Errorf("stat part: %w", err) } @@ -1819,6 +1837,9 @@ func (p *Posix) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s3. if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return nil, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return nil, fmt.Errorf("stat object: %w", err) } @@ -1989,8 +2010,11 @@ func (p *Posix) CopyObject(ctx context.Context, input *s3.CopyObjectInput) (*s3. if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return nil, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { - return nil, fmt.Errorf("stat object: %w", err) + return nil, fmt.Errorf("open object: %w", err) } defer f.Close() diff --git a/backend/scoutfs/scoutfs.go b/backend/scoutfs/scoutfs.go index 5465b26..fb48b0c 100644 --- a/backend/scoutfs/scoutfs.go +++ b/backend/scoutfs/scoutfs.go @@ -458,6 +458,9 @@ func (s *ScoutFS) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrInvalidPart) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return nil, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return nil, fmt.Errorf("stat part: %w", err) } @@ -492,6 +495,9 @@ func (s *ScoutFS) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return nil, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return nil, fmt.Errorf("stat object: %w", err) } @@ -613,6 +619,9 @@ func (s *ScoutFS) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.Ge if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } + if errors.Is(err, syscall.ENAMETOOLONG) { + return nil, s3err.GetAPIError(s3err.ErrKeyTooLong) + } if err != nil { return nil, fmt.Errorf("stat object: %w", err) } diff --git a/s3err/s3err.go b/s3err/s3err.go index 8433ca9..2767d0c 100644 --- a/s3err/s3err.go +++ b/s3err/s3err.go @@ -131,6 +131,7 @@ const ( ErrUnexpectedContent ErrMissingSecurityHeader ErrInvalidMetadataDirective + ErrKeyTooLong // Non-AWS errors ErrExistingObjectIsDirectory @@ -152,7 +153,7 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrBucketNotEmpty: { Code: "BucketNotEmpty", - Description: "The bucket you tried to delete is not empty", + Description: "The bucket you tried to delete is not empty.", HTTPStatusCode: http.StatusConflict, }, ErrBucketAlreadyExists: { @@ -177,17 +178,17 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrInvalidMaxUploads: { Code: "InvalidArgument", - Description: "Argument max-uploads must be an integer between 0 and 2147483647", + Description: "Argument max-uploads must be an integer between 0 and 2147483647.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidMaxKeys: { Code: "InvalidArgument", - Description: "Argument maxKeys must be an integer between 0 and 2147483647", + Description: "Argument maxKeys must be an integer between 0 and 2147483647.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidMaxParts: { Code: "InvalidArgument", - Description: "Argument max-parts must be an integer between 0 and 2147483647", + Description: "Argument max-parts must be an integer between 0 and 2147483647.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidPartNumberMarker: { @@ -197,7 +198,7 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrNoSuchBucket: { Code: "NoSuchBucket", - Description: "The specified bucket does not exist", + Description: "The specified bucket does not exist.", HTTPStatusCode: http.StatusNotFound, }, ErrNoSuchKey: { @@ -222,7 +223,7 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrInvalidPartNumber: { Code: "InvalidArgument", - Description: "Part number must be an integer between 1 and 10000, inclusive", + Description: "Part number must be an integer between 1 and 10000, inclusive.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidCopyDest: { @@ -267,7 +268,7 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrPostPolicyConditionInvalidFormat: { Code: "PostPolicyInvalidKeyName", - Description: "Invalid according to Policy: Policy Condition failed", + Description: "Invalid according to Policy: Policy Condition failed.", HTTPStatusCode: http.StatusForbidden, }, ErrEntityTooSmall: { @@ -302,7 +303,7 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrMalformedPresignedDate: { Code: "AuthorizationQueryParametersError", - Description: "X-Amz-Date must be in the ISO8601 Long Format \"yyyyMMdd'T'HHmmss'Z'\"", + Description: "X-Amz-Date must be in the ISO8601 Long Format \"yyyyMMdd'T'HHmmss'Z'\".", HTTPStatusCode: http.StatusBadRequest, }, ErrMissingSignHeadersTag: { @@ -317,7 +318,7 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrUnsignedHeaders: { Code: "AccessDenied", - Description: "There were headers present in the request which were not signed", + Description: "There were headers present in the request which were not signed.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidQueryParams: { @@ -332,22 +333,22 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrExpiredPresignRequest: { Code: "AccessDenied", - Description: "Request has expired", + Description: "Request has expired.", HTTPStatusCode: http.StatusForbidden, }, ErrMalformedExpires: { Code: "AuthorizationQueryParametersError", - Description: "X-Amz-Expires should be a number", + Description: "X-Amz-Expires should be a number.", HTTPStatusCode: http.StatusBadRequest, }, ErrNegativeExpires: { Code: "AuthorizationQueryParametersError", - Description: "X-Amz-Expires must be non-negative", + Description: "X-Amz-Expires must be non-negative.", HTTPStatusCode: http.StatusBadRequest, }, ErrMaximumExpires: { Code: "AuthorizationQueryParametersError", - Description: "X-Amz-Expires must be less than a week (in seconds); that is, the given X-Amz-Expires must be less than 604800 seconds", + Description: "X-Amz-Expires must be less than a week (in seconds); that is, the given X-Amz-Expires must be less than 604800 seconds.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidAccessKeyID: { @@ -357,7 +358,7 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrRequestNotReadyYet: { Code: "AccessDenied", - Description: "Request is not valid yet", + Description: "Request is not valid yet.", HTTPStatusCode: http.StatusForbidden, }, ErrSignatureDoesNotMatch: { @@ -367,17 +368,17 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrSignatureDateDoesNotMatch: { Code: "SignatureDoesNotMatch", - Description: "Date in Credential scope does not match YYYYMMDD from ISO-8601 version of date from HTTP", + Description: "Date in Credential scope does not match YYYYMMDD from ISO-8601 version of date from HTTP.", HTTPStatusCode: http.StatusForbidden, }, ErrSignatureTerminationStr: { Code: "SignatureDoesNotMatch", - Description: "Credential should be scoped with a valid terminator: 'aws4_request'", + Description: "Credential should be scoped with a valid terminator: 'aws4_request'.", HTTPStatusCode: http.StatusForbidden, }, ErrSignatureIncorrService: { Code: "SignatureDoesNotMatch", - Description: "Credential should be scoped to correct service: s3", + Description: "Credential should be scoped to correct service: s3.", HTTPStatusCode: http.StatusForbidden, }, ErrContentSHA256Mismatch: { @@ -387,32 +388,32 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrMissingDateHeader: { Code: "AccessDenied", - Description: "AWS authentication requires a valid Date or x-amz-date header", + Description: "AWS authentication requires a valid Date or x-amz-date header.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidRequest: { Code: "InvalidRequest", - Description: "Invalid Request", + Description: "Invalid Request.", HTTPStatusCode: http.StatusBadRequest, }, ErrAuthNotSetup: { Code: "InvalidRequest", - Description: "Signed request requires setting up SeaweedFS S3 authentication", + Description: "Signed request requires setting up SeaweedFS S3 authentication.", HTTPStatusCode: http.StatusBadRequest, }, ErrNotImplemented: { Code: "NotImplemented", - Description: "A header you provided implies functionality that is not implemented", + Description: "A header you provided implies functionality that is not implemented.", HTTPStatusCode: http.StatusNotImplemented, }, ErrPreconditionFailed: { Code: "PreconditionFailed", - Description: "At least one of the pre-conditions you specified did not hold", + Description: "At least one of the pre-conditions you specified did not hold.", HTTPStatusCode: http.StatusPreconditionFailed, }, ErrInvalidObjectState: { Code: "InvalidObjectState", - Description: "The operation is not valid for the current state of the object", + Description: "The operation is not valid for the current state of the object.", HTTPStatusCode: http.StatusForbidden, }, ErrInvalidRange: { @@ -427,52 +428,52 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrObjectLockConfigurationNotFound: { Code: "ObjectLockConfigurationNotFoundError", - Description: "Object Lock configuration does not exist for this bucket", + Description: "Object Lock configuration does not exist for this bucket.", HTTPStatusCode: http.StatusNotFound, }, ErrNoSuchObjectLockConfiguration: { Code: "NoSuchObjectLockConfiguration", - Description: "The specified object does not have an ObjectLock configuration", + Description: "The specified object does not have an ObjectLock configuration.", HTTPStatusCode: http.StatusBadRequest, }, ErrInvalidBucketObjectLockConfiguration: { Code: "InvalidRequest", - Description: "Bucket is missing ObjectLockConfiguration", + Description: "Bucket is missing ObjectLockConfiguration.", HTTPStatusCode: http.StatusBadRequest, }, ErrObjectLockConfigurationNotAllowed: { Code: "InvalidBucketState", - Description: "Object Lock configuration cannot be enabled on existing buckets", + Description: "Object Lock configuration cannot be enabled on existing buckets.", HTTPStatusCode: http.StatusConflict, }, ErrObjectLocked: { Code: "InvalidRequest", - Description: "Object is WORM protected and cannot be overwritten", + Description: "Object is WORM protected and cannot be overwritten.", HTTPStatusCode: http.StatusBadRequest, }, ErrPastObjectLockRetainDate: { Code: "InvalidRequest", - Description: "the retain until date must be in the future", + Description: "the retain until date must be in the future.", HTTPStatusCode: http.StatusBadRequest, }, ErrObjectLockInvalidRetentionPeriod: { Code: "InvalidRetentionPeriod", - Description: "the retention days/years must be positive integer", + Description: "the retention days/years must be positive integer.", HTTPStatusCode: http.StatusBadRequest, }, ErrNoSuchBucketPolicy: { Code: "NoSuchBucketPolicy", - Description: "The bucket policy does not exist", + Description: "The bucket policy does not exist.", HTTPStatusCode: http.StatusNotFound, }, ErrBucketTaggingNotFound: { Code: "NoSuchTagSet", - Description: "The TagSet does not exist", + Description: "The TagSet does not exist.", HTTPStatusCode: http.StatusNotFound, }, ErrObjectLockInvalidHeaders: { Code: "InvalidRequest", - Description: "x-amz-object-lock-retain-until-date and x-amz-object-lock-mode must both be supplied", + Description: "x-amz-object-lock-retain-until-date and x-amz-object-lock-mode must both be supplied.", HTTPStatusCode: http.StatusBadRequest, }, ErrRequestTimeTooSkewed: { @@ -482,37 +483,37 @@ var errorCodeResponse = map[ErrorCode]APIError{ }, ErrInvalidBucketAclWithObjectOwnership: { Code: "ErrInvalidBucketAclWithObjectOwnership", - Description: "Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting", + Description: "Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting.", HTTPStatusCode: http.StatusBadRequest, }, ErrBothCannedAndHeaderGrants: { Code: "InvalidRequest", - Description: "Specifying both Canned ACLs and Header Grants is not allowed", + Description: "Specifying both Canned ACLs and Header Grants is not allowed.", HTTPStatusCode: http.StatusBadRequest, }, ErrOwnershipControlsNotFound: { Code: "OwnershipControlsNotFoundError", - Description: "The bucket ownership controls were not found", + Description: "The bucket ownership controls were not found.", HTTPStatusCode: http.StatusNotFound, }, ErrAclNotSupported: { Code: "AccessControlListNotSupported", - Description: "The bucket does not allow ACLs", + Description: "The bucket does not allow ACLs.", HTTPStatusCode: http.StatusBadRequest, }, ErrMalformedACL: { Code: "MalformedACLError", - Description: "The XML you provided was not well-formed or did not validate against our published schema", + Description: "The XML you provided was not well-formed or did not validate against our published schema.", HTTPStatusCode: http.StatusBadRequest, }, ErrUnexpectedContent: { Code: "UnexpectedContent", - Description: "This request does not support content", + Description: "This request does not support content.", HTTPStatusCode: http.StatusBadRequest, }, ErrMissingSecurityHeader: { Code: "MissingSecurityHeader", - Description: "Your request was missing a required header", + Description: "Your request was missing a required header.", HTTPStatusCode: http.StatusNotFound, }, ErrInvalidMetadataDirective: { @@ -520,6 +521,11 @@ var errorCodeResponse = map[ErrorCode]APIError{ Description: "Unknown metadata directive.", HTTPStatusCode: http.StatusBadRequest, }, + ErrKeyTooLong: { + Code: "KeyTooLongError", + Description: "Your key is too long.", + HTTPStatusCode: http.StatusBadRequest, + }, // non aws errors ErrExistingObjectIsDirectory: { diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 6772b3d..06e0ecd 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -132,6 +132,7 @@ func TestPutObject(s *S3Conf) { PutObject_special_chars(s) PutObject_invalid_long_tags(s) PutObject_missing_object_lock_retention_config(s) + PutObject_name_too_long(s) PutObject_with_object_lock(s) PutObject_success(s) PutObject_invalid_credentials(s) @@ -143,6 +144,7 @@ func TestHeadObject(s *S3Conf) { HeadObject_non_existing_mp(s) HeadObject_mp_success(s) HeadObject_non_existing_dir_object(s) + HeadObject_name_too_long(s) HeadObject_success(s) } @@ -186,6 +188,7 @@ func TestListObjectsV2(s *S3Conf) { func TestDeleteObject(s *S3Conf) { DeleteObject_non_existing_object(s) + DeleteObject_name_too_long(s) DeleteObject_non_existing_dir_object(s) DeleteObject_success(s) DeleteObject_success_status_code(s) @@ -539,6 +542,7 @@ func GetIntTests() IntTests { "PresignedAuth_incorrect_secret_key": PresignedAuth_incorrect_secret_key, "PresignedAuth_PutObject_success": PresignedAuth_PutObject_success, "PutObject_missing_object_lock_retention_config": PutObject_missing_object_lock_retention_config, + "PutObject_name_too_long": PutObject_name_too_long, "PutObject_with_object_lock": PutObject_with_object_lock, "PresignedAuth_Put_GetObject_with_data": PresignedAuth_Put_GetObject_with_data, "PresignedAuth_Put_GetObject_with_UTF8_chars": PresignedAuth_Put_GetObject_with_UTF8_chars, @@ -588,6 +592,7 @@ func GetIntTests() IntTests { "HeadObject_non_existing_mp": HeadObject_non_existing_mp, "HeadObject_mp_success": HeadObject_mp_success, "HeadObject_non_existing_dir_object": HeadObject_non_existing_dir_object, + "HeadObject_name_too_long": HeadObject_name_too_long, "HeadObject_success": HeadObject_success, "GetObjectAttributes_non_existing_bucket": GetObjectAttributes_non_existing_bucket, "GetObjectAttributes_non_existing_object": GetObjectAttributes_non_existing_object, @@ -616,6 +621,7 @@ func GetIntTests() IntTests { "ListObjectsV2_both_delimiter_and_prefix": ListObjectsV2_both_delimiter_and_prefix, "ListObjectsV2_single_dir_object_with_delim_and_prefix": ListObjectsV2_single_dir_object_with_delim_and_prefix, "DeleteObject_non_existing_object": DeleteObject_non_existing_object, + "DeleteObject_name_too_long": DeleteObject_name_too_long, "DeleteObject_non_existing_dir_object": DeleteObject_non_existing_dir_object, "DeleteObject_success": DeleteObject_success, "DeleteObject_success_status_code": DeleteObject_success_status_code, diff --git a/tests/integration/tests.go b/tests/integration/tests.go index 8281858..4dcc505 100644 --- a/tests/integration/tests.go +++ b/tests/integration/tests.go @@ -2769,6 +2769,25 @@ func PutObject_missing_object_lock_retention_config(s *S3Conf) error { }) } +func PutObject_name_too_long(s *S3Conf) error { + testName := "PutObject_name_too_long" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + key := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: &bucket, + Key: &key, + }) + cancel() + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrKeyTooLong)); err != nil { + return err + } + + return nil + }) +} + func PutObject_with_object_lock(s *S3Conf) error { testName := "PutObject_with_object_lock" runF(testName) @@ -2876,6 +2895,22 @@ func HeadObject_non_existing_object(s *S3Conf) error { }) } +func HeadObject_name_too_long(s *S3Conf) error { + testName := "HeadObject_name_too_long" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: &bucket, + Key: getPtr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + }) + cancel() + if err := checkSdkApiErr(err, "BadRequest"); err != nil { + return err + } + return nil + }) +} + func HeadObject_invalid_part_number(s *S3Conf) error { testName := "HeadObject_invalid_part_number" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { @@ -4051,6 +4086,19 @@ func DeleteObject_non_existing_object(s *S3Conf) error { }) } +func DeleteObject_name_too_long(s *S3Conf) error { + testName := "DeleteObject_name_too_long" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.DeleteObject(ctx, &s3.DeleteObjectInput{ + Bucket: &bucket, + Key: getPtr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + }) + cancel() + return err + }) +} + func DeleteObject_non_existing_dir_object(s *S3Conf) error { testName := "DeleteObject_non_existing_dir_object" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {