From 47200ce03b85204fb331db1ed683eeb653ed0dd5 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Mon, 14 Apr 2025 17:49:02 +0300 Subject: [PATCH 1/4] [#11] Add all tests Signed-off-by: Denis Kirillov --- internal/s3/resources/tests-struct.json | 527 +++++++++++++++++++++++- 1 file changed, 510 insertions(+), 17 deletions(-) diff --git a/internal/s3/resources/tests-struct.json b/internal/s3/resources/tests-struct.json index a00d9ff..ed9f467 100644 --- a/internal/s3/resources/tests-struct.json +++ b/internal/s3/resources/tests-struct.json @@ -1,4 +1,7 @@ { + "info": { + "commit": "https://git.frostfs.info/TrueCloudLab/s3-tests/commit/7aae6ce2ca48ccd0ac35100af074281c7c88a210" + }, "groups": [ { "name": "AbortMultipartUpload", @@ -61,7 +64,8 @@ "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_copy_source", "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_copy_source_meta", "s3tests_boto3/functional/test_s3.py::test_object_copy_bucket_not_found", - "s3tests_boto3/functional/test_s3.py::test_object_copy_key_not_found" + "s3tests_boto3/functional/test_s3.py::test_object_copy_key_not_found", + "s3tests_boto3/functional/test_s3.py::test_versioning_obj_suspended_copy" ], "skip": false, "comment": "" @@ -268,8 +272,11 @@ "name": "DeletePublicAccessBlock", "tag": "API", "tests": [], - "skip": true, - "comment": "Not supported" + "include": [ + "PublicAccessBlock" + ], + "skip": false, + "comment": "See PublicAccessBlock feature" }, { "name": "GetBucketAccelerateConfiguration", @@ -486,6 +493,9 @@ "name": "GetObjectAcl", "tag": "API", "tests": [], + "include": [ + "ObjectACL" + ], "skip": true, "comment": "Not supported" }, @@ -549,8 +559,11 @@ "name": "GetPublicAccessBlock", "tag": "API", "tests": [], - "skip": true, - "comment": "Not supported" + "include": [ + "PublicAccessBlock" + ], + "skip": false, + "comment": "See PublicAccessBlock feature" }, { "name": "HeadBucket", @@ -667,7 +680,8 @@ "s3tests_boto3/functional/test_s3.py::test_multi_object_delete", "s3tests_boto3/functional/test_s3.py::test_bucket_list_delimiter_prefix", "s3tests_boto3/functional/test_s3.py::test_bucket_list_delimiter_prefix_ends_with_delimiter", - "s3tests_boto3/functional/test_s3.py::test_bucket_list_delimiter_prefix_underscore" + "s3tests_boto3/functional/test_s3.py::test_bucket_list_delimiter_prefix_underscore", + "s3tests_boto3/functional/test_s3.py::test_bucket_list_special_prefix" ], "skip": false, "comment": "" @@ -940,7 +954,8 @@ "s3tests_boto3/functional/test_s3.py::test_object_anon_put", "s3tests_boto3/functional/test_s3.py::test_object_anon_put_write_access", "s3tests_boto3/functional/test_s3.py::test_object_put_authenticated", - "s3tests_boto3/functional/test_s3.py::test_object_raw_put_authenticated_expired" + "s3tests_boto3/functional/test_s3.py::test_object_raw_put_authenticated_expired", + "s3tests_boto3/functional/test_s3.py::test_object_write_to_nonexist_bucket" ], "skip": false, "comment": "" @@ -949,6 +964,9 @@ "name": "PutObjectAcl", "tag": "API", "tests": [], + "include": [ + "ObjectACL" + ], "skip": true, "comment": "Not supported" }, @@ -995,15 +1013,12 @@ { "name": "PutPublicAccessBlock", "tag": "API", - "tests": [ - "s3tests_boto3/functional/test_s3.py::test_put_public_block", - "s3tests_boto3/functional/test_s3.py::test_block_public_put_bucket_acls", - "s3tests_boto3/functional/test_s3.py::test_block_public_object_canned_acls", - "s3tests_boto3/functional/test_s3.py::test_block_public_policy", - "s3tests_boto3/functional/test_s3.py::test_ignore_public_acls" + "tests": [], + "include": [ + "PublicAccessBlock" ], - "skip": true, - "comment": "Not supported" + "skip": false, + "comment": "See PublicAccessBlock feature" }, { "name": "RestoreObject", @@ -1277,6 +1292,21 @@ "skip": false, "comment": "Only sse-c currently supported" }, + { + "name": "PublicAccessBlock", + "tag": "Features", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_put_public_block", + "s3tests_boto3/functional/test_s3.py::test_block_public_put_bucket_acls", + "s3tests_boto3/functional/test_s3.py::test_block_public_object_canned_acls", + "s3tests_boto3/functional/test_s3.py::test_block_public_policy", + "s3tests_boto3/functional/test_s3.py::test_ignore_public_acls", + "s3tests_boto3/functional/test_s3.py::test_get_public_block_deny_bucket_policy", + "s3tests_boto3/functional/test_s3.py::test_get_undefined_public_block" + ], + "skip": false, + "comment": "" + }, { "name": "PostObject", "tag": "Features", @@ -1299,7 +1329,54 @@ "s3tests_boto3/functional/test_headers.py::test_object_create_bad_date_none_aws2", "s3tests_boto3/functional/test_headers.py::test_object_create_bad_date_before_today_aws2", "s3tests_boto3/functional/test_headers.py::test_object_create_bad_date_before_epoch_aws2", - "s3tests_boto3/functional/test_headers.py::test_object_create_bad_date_after_end_aws2" + "s3tests_boto3/functional/test_headers.py::test_object_create_bad_date_after_end_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_authorization_invalid_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_date_after_today_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_date_before_epoch_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_date_before_today_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_date_empty_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_date_invalid_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_date_none_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_ua_empty_aws2", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_ua_none_aws2", + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_s3_noenc", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_get_object_v2", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_get_object_tenant_v2", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_put_object_v2", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_put_object_tenant_v2", + "s3tests_boto3/functional/test_s3.py::test_encryption_sse_c_post_object_authenticated_request", + "s3tests_boto3/functional/test_s3.py::test_post_object_authenticated_no_content_type", + "s3tests_boto3/functional/test_s3.py::test_post_object_authenticated_request", + "s3tests_boto3/functional/test_s3.py::test_post_object_authenticated_request_bad_access_key", + "s3tests_boto3/functional/test_s3.py::test_post_object_case_insensitive_condition_fields", + "s3tests_boto3/functional/test_s3.py::test_post_object_condition_is_case_sensitive", + "s3tests_boto3/functional/test_s3.py::test_post_object_empty_conditions", + "s3tests_boto3/functional/test_s3.py::test_post_object_escaped_field_values", + "s3tests_boto3/functional/test_s3.py::test_post_object_expired_policy", + "s3tests_boto3/functional/test_s3.py::test_post_object_expires_is_case_sensitive", + "s3tests_boto3/functional/test_s3.py::test_post_object_ignored_header", + "s3tests_boto3/functional/test_s3.py::test_post_object_invalid_access_key", + "s3tests_boto3/functional/test_s3.py::test_post_object_invalid_content_length_argument", + "s3tests_boto3/functional/test_s3.py::test_post_object_invalid_date_format", + "s3tests_boto3/functional/test_s3.py::test_post_object_invalid_request_field_value", + "s3tests_boto3/functional/test_s3.py::test_post_object_invalid_signature", + "s3tests_boto3/functional/test_s3.py::test_post_object_missing_conditions_list", + "s3tests_boto3/functional/test_s3.py::test_post_object_missing_content_length_argument", + "s3tests_boto3/functional/test_s3.py::test_post_object_missing_expires_condition", + "s3tests_boto3/functional/test_s3.py::test_post_object_missing_policy_condition", + "s3tests_boto3/functional/test_s3.py::test_post_object_missing_signature", + "s3tests_boto3/functional/test_s3.py::test_post_object_no_key_specified", + "s3tests_boto3/functional/test_s3.py::test_post_object_request_missing_policy_specified_field", + "s3tests_boto3/functional/test_s3.py::test_post_object_set_key_from_filename", + "s3tests_boto3/functional/test_s3.py::test_post_object_success_redirect_action", + "s3tests_boto3/functional/test_s3.py::test_post_object_tags_anonymous_request", + "s3tests_boto3/functional/test_s3.py::test_post_object_tags_authenticated_request", + "s3tests_boto3/functional/test_s3.py::test_post_object_upload_larger_than_chunk", + "s3tests_boto3/functional/test_s3.py::test_post_object_upload_size_below_minimum", + "s3tests_boto3/functional/test_s3.py::test_post_object_upload_size_limit_exceeded", + "s3tests_boto3/functional/test_s3.py::test_post_object_upload_size_rgw_chunk_size_bug", + "s3tests_boto3/functional/test_s3.py::test_post_object_user_specified_header", + "s3tests_boto3/functional/test_s3.py::test_post_object_wrong_bucket" ], "skip": true, "comment": "Not supported. AWS v2 signature is deprecated." @@ -1343,10 +1420,426 @@ "s3tests_boto3/functional/test_s3.py::test_object_lock_changing_mode_from_governance_with_bypass", "s3tests_boto3/functional/test_s3.py::test_object_lock_changing_mode_from_governance_without_bypass", "s3tests_boto3/functional/test_s3.py::test_object_lock_changing_mode_from_compliance", - "s3tests_boto3/functional/test_s3.py::test_object_lock_put_obj_lock_invalid_mode" + "s3tests_boto3/functional/test_s3.py::test_object_lock_put_obj_lock_invalid_mode", + "s3tests_boto3/functional/test_s3.py::test_object_lock_delete_multipart_object_with_legal_hold_on", + "s3tests_boto3/functional/test_s3.py::test_object_lock_delete_multipart_object_with_retention" ], "skip": true, "comment": "Not supported" + }, + { + "name": "ObjectACL", + "tag": "Features", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_access_bucket_private_object_private", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_private_object_publicread", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_private_object_publicreadwrite", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_private_objectv2_private", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_private_objectv2_publicread", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_private_objectv2_publicreadwrite", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_publicread_object_private", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_publicread_object_publicread", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_publicread_object_publicreadwrite", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_publicreadwrite_object_private", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_publicreadwrite_object_publicread", + "s3tests_boto3/functional/test_s3.py::test_access_bucket_publicreadwrite_object_publicreadwrite", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_special_key_names", + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_acl", + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_grant", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_get_object", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_get_object_tenant", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_put_object", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_put_object_with_acl", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_put_object_tenant", + "s3tests_boto3/functional/test_s3.py::test_cors_presigned_put_object_tenant_with_acl", + "s3tests_boto3/functional/test_s3.py::test_object_presigned_put_object_with_acl", + "s3tests_boto3/functional/test_s3.py::test_object_presigned_put_object_with_acl_tenant", + "s3tests_boto3/functional/test_s3.py::test_object_acl", + "s3tests_boto3/functional/test_s3.py::test_object_acl_canned", + "s3tests_boto3/functional/test_s3.py::test_object_acl_canned_authenticatedread", + "s3tests_boto3/functional/test_s3.py::test_object_acl_canned_bucketownerfullcontrol", + "s3tests_boto3/functional/test_s3.py::test_object_acl_canned_bucketownerread", + "s3tests_boto3/functional/test_s3.py::test_object_acl_canned_during_create", + "s3tests_boto3/functional/test_s3.py::test_object_acl_canned_publicreadwrite", + "s3tests_boto3/functional/test_s3.py::test_object_acl_create_contentlength_none", + "s3tests_boto3/functional/test_s3.py::test_object_acl_default", + "s3tests_boto3/functional/test_s3.py::test_object_acl_full_control_verify_attributes", + "s3tests_boto3/functional/test_s3.py::test_object_acl_full_control_verify_owner", + "s3tests_boto3/functional/test_s3.py::test_object_acl_read", + "s3tests_boto3/functional/test_s3.py::test_object_acl_readacp", + "s3tests_boto3/functional/test_s3.py::test_object_acl_write", + "s3tests_boto3/functional/test_s3.py::test_object_acl_writeacp", + "s3tests_boto3/functional/test_s3.py::test_object_copy_canned_acl", + "s3tests_boto3/functional/test_s3.py::test_object_copy_not_owned_object_bucket", + "s3tests_boto3/functional/test_s3.py::test_object_delete_key_bucket_gone", + "s3tests_boto3/functional/test_s3.py::test_object_put_acl_mtime", + "s3tests_boto3/functional/test_s3.py::test_object_raw_authenticated", + "s3tests_boto3/functional/test_s3.py::test_object_raw_authenticated_bucket_acl", + "s3tests_boto3/functional/test_s3.py::test_object_raw_authenticated_bucket_gone", + "s3tests_boto3/functional/test_s3.py::test_object_raw_authenticated_object_acl", + "s3tests_boto3/functional/test_s3.py::test_object_raw_authenticated_object_gone", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_bucket_acl", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_bucket_gone", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_object_acl", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_object_gone", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_x_amz_expires_not_expired", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_x_amz_expires_not_expired_tenant", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_x_amz_expires_out_max_range", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_x_amz_expires_out_positive_range", + "s3tests_boto3/functional/test_s3.py::test_object_raw_get_x_amz_expires_out_range_zero", + "s3tests_boto3/functional/test_s3.py::test_object_raw_response_headers", + "s3tests_boto3/functional/test_s3.py::test_post_object_anonymous_request", + "s3tests_boto3/functional/test_s3.py::test_post_object_set_invalid_success_code", + "s3tests_boto3/functional/test_s3.py::test_post_object_set_success_code", + "s3tests_boto3/functional/test_s3.py::test_versioned_object_acl", + "s3tests_boto3/functional/test_s3.py::test_versioned_object_acl_no_version_specified" + ], + "skip": true, + "comment": "Not supported" + }, + { + "name": "Atomicity", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_atomic_dual_write_1mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_dual_write_4mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_dual_write_8mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_read_1mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_read_4mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_read_8mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_write_1mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_write_4mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_write_8mb" + ], + "skip": true, + "comment": "Passed but don't fit any API related group, so skip" + }, + { + "name": "Bucket canned ACL, owner full control", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_canned", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_canned_authenticatedread", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_canned_during_create", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_canned_publicreadwrite", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_default" + ], + "skip": true, + "comment": "Not supported, Full Control to bucket owner is required" + }, + { + "name": "Bucket ACL, using payload", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_nonexist_user", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_userid_fullcontrol", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_userid_read", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_userid_readacp", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_userid_write", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_userid_writeacp", + "s3tests_boto3/functional/test_s3.py::test_bucket_header_acl_grants" + ], + "skip": true, + "comment": "Not supported, Full Control to bucket owner is required" + }, + { + "name": "Email checking", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_email", + "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_email_not_exist" + ], + "skip": true, + "comment": "Not supported, email checking" + }, + { + "name": "Authorization header manipulating", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_authorization_empty", + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_authorization_none" + ], + "skip": true, + "comment": "Bad test, railed_on_rwg, # TODO: remove 'fails_on_rgw' and once we have learned how to manipulate the authorization header" + }, + { + "name": "test_bucket_create_bad_expect_mismatch", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_expect_mismatch" + ], + "skip": true, + "comment": "Don't support 'Expect: 200'" + }, + { + "name": "test_bucket_create_exists", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_create_exists" + ], + "skip": true, + "comment": "Bad test. Incorrect asserting response error" + }, + { + "name": "Checking object owner", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_list_return_data", + "s3tests_boto3/functional/test_s3.py::test_bucket_list_return_data_versioning", + "s3tests_boto3/functional/test_s3.py::test_list_multipart_upload_owner" + ], + "skip": true, + "comment": "Checking object owner. In s3-gw it's always gate key." + }, + { + "name": "test_bucket_listv2_continuationtoken_empty", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_listv2_continuationtoken_empty" + ], + "skip": true, + "comment": "Empty continuation token not supported" + }, + { + "name": "authenticated-read bucket acl", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_acl", + "s3tests_boto3/functional/test_s3.py::test_bucketv2_policy_acl" + ], + "skip": true, + "comment": "authenticated-read bucket ACL not supported" + }, + { + "name": "any bucket as resource in bucket policy", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_another_bucket", + "s3tests_boto3/functional/test_s3.py::test_bucketv2_policy_another_bucket" + ], + "skip": true, + "comment": "Bucket policy with 'arn:aws:s3:::*' resource not supported" + }, + { + "name": "tenants", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_different_tenant", + "s3tests_boto3/functional/test_s3.py::test_bucketv2_policy_different_tenant" + ], + "skip": true, + "comment": "Such tenants not supported" + }, + { + "name": "kms", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_kms_noenc", + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_kms_s3", + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_s3_kms", + "s3tests_boto3/functional/test_s3.py::test_put_obj_enc_conflict_bad_enc_kms", + "s3tests_boto3/functional/test_s3.py::test_put_obj_enc_conflict_c_kms", + "s3tests_boto3/functional/test_s3.py::test_put_obj_enc_conflict_c_s3", + "s3tests_boto3/functional/test_s3.py::test_put_obj_enc_conflict_s3_kms", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_method_head", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_multipart_invalid_chunks_1", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_multipart_invalid_chunks_2", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_multipart_upload", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_no_key", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_not_declared", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_post_object_authenticated_request", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_present", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_read_declare", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_transfer_13b", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_transfer_1MB", + "s3tests_boto3/functional/test_s3.py::test_sse_kms_transfer_1b" + ], + "skip": true, + "comment": "KMS not supported" + }, + { + "name": "sse_s3", + "tag": "Ignored", + "tests": [ + + "s3tests_boto3/functional/test_s3.py::test_sse_s3_encrypted_upload_1b", + "s3tests_boto3/functional/test_s3.py::test_sse_s3_encrypted_upload_1kb", + "s3tests_boto3/functional/test_s3.py::test_sse_s3_encrypted_upload_1mb", + "s3tests_boto3/functional/test_s3.py::test_sse_s3_encrypted_upload_8mb" + ], + "skip": true, + "comment": "sse_s3 not supported" + }, + { + "name": "alternative client in different account", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_put_obj_request_obj_tag", + "s3tests_boto3/functional/test_s3.py::test_object_copy_not_owned_bucket" + ], + "skip": true, + "comment": "Alternative client must be in different namespace. Couldn't be used without additional header." + }, + { + "name": "test_bucket_policy_set_condition_operator_end_with_IfExists", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_policy_set_condition_operator_end_with_IfExists" + ], + "skip": true, + "comment": "StringLikeIfExists operator not supported." + }, + { + "name": "Recreate bucket with acl", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_recreate_new_acl", + "s3tests_boto3/functional/test_s3.py::test_bucket_recreate_overwrite_acl" + ], + "skip": true, + "comment": "Expected BucketAlreadyExists but s3-gw returns BucketAlreadyOwnedByYou because tests use the same client." + }, + { + "name": "Recreate bucket", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_bucket_recreate_not_overriding" + ], + "skip": true, + "comment": "Expect success on bucket recreate in default region https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/537" + }, + { + "name": "test_lifecycle_expiration_header_tags_head", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_header_tags_head" + ], + "skip": true, + "comment": "Probably bad test, AWS fails, https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/545" + }, + { + "name": "get bucket policy status", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_get_authpublic_acl_bucket_policy_status", + "s3tests_boto3/functional/test_s3.py::test_get_public_acl_bucket_policy_status", + "s3tests_boto3/functional/test_s3.py::test_get_publicpolicy_acl_bucket_policy_status", + "s3tests_boto3/functional/test_s3.py::test_get_bucket_policy_status", + "s3tests_boto3/functional/test_s3.py::test_get_nonpublicpolicy_acl_bucket_policy_status" + ], + "skip": true, + "comment": "Not supported, S3 gate computes status based on policy, not on canned acl. AWS also fails" + }, + { + "name": "Lifecycle transition", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_lifecycle_plain_null_version_current_transition", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_set_noncurrent_transition", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_transition", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_transition_set_invalid_date", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_transition_single_rule_multi_trans" + ], + "skip": true, + "comment": "Lifecycle transition not supported." + }, + { + "name": "Repeated complete multipart upload", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_multipart_upload_small", + "s3tests_boto3/functional/test_s3.py::test_multipart_upload" + ], + "skip": true, + "comment": "https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/530" + }, + { + "name": "bad authorization tests", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_headers.py::test_object_create_amz_date_and_no_date", + "s3tests_boto3/functional/test_headers.py::test_object_create_bad_authorization_empty", + "s3tests_boto3/functional/test_headers.py::test_object_create_bad_authorization_none", + "s3tests_boto3/functional/test_headers.py::test_object_create_bad_contentlength_none", + "s3tests_boto3/functional/test_headers.py::test_object_create_date_and_amz_date", + "s3tests_boto3/functional/test_headers.py::test_object_read_unreadable", + "s3tests_boto3/functional/test_headers.py::test_object_set_get_unicode_metadata", + "s3tests_boto3/functional/test_s3.py::test_object_write_with_chunked_transfer_encoding", + "s3tests_boto3/functional/test_s3.py::test_put_excess_tags" + ], + "skip": true, + "comment": "Fails on aws though there are not fails_on_aws mark" + }, + { + "name": "empty metadata", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_object_set_get_metadata_none_to_empty", + "s3tests_boto3/functional/test_s3.py::test_object_set_get_metadata_overwrite_to_empty" + ], + "skip": true, + "comment": "Empty metadata not supported" + }, + { + "name": "fails_on_aws", + "tag": "Ignored", + "tests": [ + "s3tests_boto3/functional/test_s3.py::test_account_usage", + "s3tests_boto3/functional/test_s3.py::test_head_bucket_usage", + "s3tests_boto3/functional/test_s3.py::test_atomic_conditional_write_1mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_dual_conditional_write_1mb", + "s3tests_boto3/functional/test_s3.py::test_atomic_write_bucket_gone", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_bad_ip", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_bad_starts_nonalpha", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_dns_dash_at_end", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_dns_dash_dot", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_dns_dot_dash", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_dns_dot_dot", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_dns_long", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_dns_underscore", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_good_long_60", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_good_long_61", + "s3tests_boto3/functional/test_s3.py::test_bucket_create_naming_good_long_62", + "s3tests_boto3/functional/test_s3.py::test_bucket_head_extended", + "s3tests_boto3/functional/test_s3.py::test_bucket_list_long_name", + "s3tests_boto3/functional/test_s3.py::test_bucket_list_unordered", + "s3tests_boto3/functional/test_s3.py::test_bucket_listv2_unordered", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_cloud_multiple_transition", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_cloud_transition", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_cloud_transition_large_obj", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_deletemarker_expiration", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_date", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_newer_noncurrent", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_noncur_tags1", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_size_gt", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_size_lt", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_tags1", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_tags2", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_versioned_tags2", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_versioning_enabled", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_multipart_expiration", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_noncur_cloud_transition", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_noncur_expiration", + "s3tests_boto3/functional/test_s3.py::test_lifecycle_noncur_transition", + "s3tests_boto3/functional/test_s3.py::test_lifecyclev2_expiration", + "s3tests_boto3/functional/test_s3.py::test_list_buckets_anonymous", + "s3tests_boto3/functional/test_s3.py::test_object_header_acl_grants", + "s3tests_boto3/functional/test_s3.py::test_multipart_get_part", + "s3tests_boto3/functional/test_s3.py::test_non_multipart_get_part", + "s3tests_boto3/functional/test_s3.py::test_multipart_resend_first_finishes_last", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifmatch_failed", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifmatch_good", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifmatch_nonexisted_failed", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifmatch_overwrite_existed_good", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifnonmatch_failed", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifnonmatch_good", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifnonmatch_nonexisted_good", + "s3tests_boto3/functional/test_s3.py::test_put_object_ifnonmatch_overwrite_existed_failed" + ], + "skip": true, + "comment": "Fails on AWS" } ] } \ No newline at end of file -- 2.45.3 From c53f3fa5d06aa39e67d1d493d9923e5c7d3757dd Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Tue, 15 Apr 2025 09:49:20 +0300 Subject: [PATCH 2/4] [#11] Add all flag Signed-off-by: Denis Kirillov --- cmd/parser/modules/compatibility.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/cmd/parser/modules/compatibility.go b/cmd/parser/modules/compatibility.go index 807f97c..3549638 100644 --- a/cmd/parser/modules/compatibility.go +++ b/cmd/parser/modules/compatibility.go @@ -22,7 +22,10 @@ var compatibilityCmd = &cobra.Command{ s3-tests-parser compatibility suite.json --format json s3-tests-parser compatibility suite.json --format json --output-format md s3-tests-parser compatibility suite.json --format json --output-format md --output result.md -s3-tests-parser compatibility suite.json --format json --output-format txt --output result.txt --verbose`, +s3-tests-parser compatibility suite.json --format json --output-format txt --output result.txt --verbose +s3-tests-parser compatibility suite.json --format json --output-format txt --output result.txt --verbose +s3-tests-parser compatibility suite.json --format json --output-format txt --output result.txt --verbose --include-ignored +`, RunE: runCompatibilityCmd, } @@ -59,6 +62,7 @@ const ( outputFlag = "output" outputFormatFlag = "output-format" verboseFlag = "verbose" + allFlag = "all" ) func initCompatibilityCmd() { @@ -66,6 +70,7 @@ func initCompatibilityCmd() { compatibilityCmd.Flags().String(outputFlag, "", "file to write output, if missed the stdout is used") compatibilityCmd.Flags().String(outputFormatFlag, "txt", "format of output") compatibilityCmd.Flags().Bool(verboseFlag, false, "produce additional info") + compatibilityCmd.Flags().Bool(allFlag, false, "include in output ignored tests") } func runCompatibilityCmd(cmd *cobra.Command, args []string) error { @@ -85,6 +90,16 @@ func runCompatibilityCmd(cmd *cobra.Command, args []string) error { res := formResults(testStruct, testsMap) res.Verbose = viper.GetBool(verboseFlag) + + if !viper.GetBool(allFlag) { + for i, group := range res.TagGroups { + if group.Name == "Ignored" { + res.TagGroups = append(res.TagGroups[:i], res.TagGroups[i+1:]...) + break + } + } + } + return printResults(cmd, res) } -- 2.45.3 From 1440cebda12898a4d33f5f5c120530f9251cb724 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Tue, 15 Apr 2025 15:21:11 +0300 Subject: [PATCH 3/4] [#11] Add describe flag to tests subcommand Signed-off-by: Denis Kirillov --- cmd/parser/modules/tests.go | 77 ++++++++++++++----- internal/s3/resources/tests-struct.json | 26 +++---- .../resources/tests-describe-template.gotmpl | 7 ++ internal/templates/templates.go | 6 ++ 4 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 internal/templates/resources/tests-describe-template.gotmpl diff --git a/cmd/parser/modules/tests.go b/cmd/parser/modules/tests.go index 5fb1115..ee7fcaf 100644 --- a/cmd/parser/modules/tests.go +++ b/cmd/parser/modules/tests.go @@ -1,27 +1,41 @@ package modules import ( + "cmp" "fmt" "os" "slices" - "sort" "git.frostfs.info/TrueCloudLab/s3-tests-parser/internal/s3" + "git.frostfs.info/TrueCloudLab/s3-tests-parser/internal/templates" "github.com/spf13/cobra" "github.com/spf13/viper" ) var testsCmd = &cobra.Command{ Use: "tests", - Short: "Print tests to check", - Long: "Print all tests that will be checked by 'compatibility' command", + Short: "Print tests info", + Long: "Print all handled tests", Example: `s3-tests-parser tests s3-tests-parser tests --output tests.txt`, RunE: runTestsCmd, } +const ( + describeFlag = "describe" +) + func initTestsCmd() { testsCmd.Flags().String(outputFlag, "", "file to write output, if missed the stdout is used") + testsCmd.Flags().Bool(allFlag, false, "include all tests") + testsCmd.Flags().Bool(describeFlag, false, "describe test (its group, skip status, reason etc.)") +} + +type DescribedTest struct { + Name string + Group string + Skip bool + Comment string } func runTestsCmd(cmd *cobra.Command, _ []string) error { @@ -30,34 +44,40 @@ func runTestsCmd(cmd *cobra.Command, _ []string) error { return err } - var tests []string + includeAll := viper.GetBool(allFlag) - groupTests := make(map[string][]string) - for _, group := range testStruct.Groups { - if group.Skip { - continue - } - groupTests[group.Name] = group.Tests - } + var tests []DescribedTest for _, group := range testStruct.Groups { - if group.Skip { + if group.Skip && !includeAll { continue } - tests = append(tests, group.Tests...) - for _, include := range group.Include { - tests = append(tests, groupTests[include]...) + for _, test := range group.Tests { + tests = append(tests, DescribedTest{ + Name: test, + Group: group.Name, + Skip: group.Skip, + Comment: group.Comment, + }) } } - sort.Strings(tests) - tests = slices.Compact(tests) + slices.SortFunc(tests, func(a, b DescribedTest) int { + return cmp.Compare(a.Name, b.Name) + }) + tests = slices.CompactFunc(tests, func(a DescribedTest, b DescribedTest) bool { + return a.Name == b.Name + }) + + if viper.GetBool(describeFlag) { + return describeTests(cmd, tests) + } return printTests(cmd, tests) } -func printTests(cmd *cobra.Command, res []string) error { +func printTests(cmd *cobra.Command, res []DescribedTest) error { w := cmd.OutOrStdout() if outFile := viper.GetString(outputFlag); outFile != "" { f, err := os.Create(outFile) @@ -69,10 +89,29 @@ func printTests(cmd *cobra.Command, res []string) error { } for i := range res { - if _, err := fmt.Fprintln(w, res[i]); err != nil { + if _, err := fmt.Fprintln(w, res[i].Name); err != nil { return err } } return nil } + +func describeTests(cmd *cobra.Command, res []DescribedTest) error { + w := cmd.OutOrStdout() + if outFile := viper.GetString(outputFlag); outFile != "" { + f, err := os.Create(outFile) + if err != nil { + return fmt.Errorf("create out file: %w", err) + } + w = f + defer f.Close() + } + + outTemplate, err := templates.GetDescribeTemplate() + if err != nil { + return fmt.Errorf("form describe template: %w", err) + } + + return outTemplate.Execute(w, res) +} diff --git a/internal/s3/resources/tests-struct.json b/internal/s3/resources/tests-struct.json index ed9f467..beadb89 100644 --- a/internal/s3/resources/tests-struct.json +++ b/internal/s3/resources/tests-struct.json @@ -342,7 +342,7 @@ "tests": [], "include": [], "skip": true, - "comment": "Not supported. This method is deprecated by AWS. Use GetBucketLifecycleConfiguration" + "comment": "Not supported
This method is deprecated by AWS, use GetBucketLifecycleConfiguration" }, { "name": "GetBucketLifecycleConfiguration", @@ -829,7 +829,7 @@ "tests": [], "include": [], "skip": true, - "comment": "Not supported. This method is deprecated by AWS. Use PutBucketLifecycleConfiguration" + "comment": "Not supported
This method is deprecated by AWS, use PutBucketLifecycleConfiguration" }, { "name": "PutBucketLifecycleConfiguration", @@ -1219,7 +1219,7 @@ "s3tests_boto3/functional/test_s3.py::test_bucket_concurrent_set_canned_acl" ], "skip": false, - "comment": "Partly supported. Only restricted canned acl can be applied" + "comment": "Partly supported
Only restricted canned acl can be applied" }, { "name": "BucketVersioning", @@ -1249,7 +1249,7 @@ "s3tests_boto3/functional/test_s3.py::test_versioning_concurrent_multi_object_delete" ], "skip": false, - "comment": "Limitations: \n1. Don't create delete marker for non-existing objects" + "comment": "Limitations:
1. Don't create delete marker for non-existing objects" }, { "name": "MultipartUpload", @@ -1379,7 +1379,7 @@ "s3tests_boto3/functional/test_s3.py::test_post_object_wrong_bucket" ], "skip": true, - "comment": "Not supported. AWS v2 signature is deprecated." + "comment": "Not supported
AWS v2 signature is deprecated" }, { "name": "Locking", @@ -1526,7 +1526,7 @@ "s3tests_boto3/functional/test_s3.py::test_bucket_acl_default" ], "skip": true, - "comment": "Not supported, Full Control to bucket owner is required" + "comment": "Not supported
Full Control to bucket owner is required" }, { "name": "Bucket ACL, using payload", @@ -1541,7 +1541,7 @@ "s3tests_boto3/functional/test_s3.py::test_bucket_header_acl_grants" ], "skip": true, - "comment": "Not supported, Full Control to bucket owner is required" + "comment": "Not supported
Full Control to bucket owner is required" }, { "name": "Email checking", @@ -1551,7 +1551,7 @@ "s3tests_boto3/functional/test_s3.py::test_bucket_acl_grant_email_not_exist" ], "skip": true, - "comment": "Not supported, email checking" + "comment": "Not supported
Email checking" }, { "name": "Authorization header manipulating", @@ -1561,7 +1561,7 @@ "s3tests_boto3/functional/test_headers.py::test_bucket_create_bad_authorization_none" ], "skip": true, - "comment": "Bad test, railed_on_rwg, # TODO: remove 'fails_on_rgw' and once we have learned how to manipulate the authorization header" + "comment": "Bad test
failed_on_rwg
# TODO: remove 'fails_on_rgw' and once we have learned how to manipulate the authorization header" }, { "name": "test_bucket_create_bad_expect_mismatch", @@ -1579,7 +1579,7 @@ "s3tests_boto3/functional/test_s3.py::test_bucket_create_exists" ], "skip": true, - "comment": "Bad test. Incorrect asserting response error" + "comment": "Bad test
Incorrect asserting response error" }, { "name": "Checking object owner", @@ -1669,7 +1669,7 @@ "s3tests_boto3/functional/test_s3.py::test_sse_s3_encrypted_upload_8mb" ], "skip": true, - "comment": "sse_s3 not supported" + "comment": "SSE-S3 not supported" }, { "name": "alternative client in different account", @@ -1716,7 +1716,7 @@ "s3tests_boto3/functional/test_s3.py::test_lifecycle_expiration_header_tags_head" ], "skip": true, - "comment": "Probably bad test, AWS fails, https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/545" + "comment": "Probably bad test
AWS fails
https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/545" }, { "name": "get bucket policy status", @@ -1729,7 +1729,7 @@ "s3tests_boto3/functional/test_s3.py::test_get_nonpublicpolicy_acl_bucket_policy_status" ], "skip": true, - "comment": "Not supported, S3 gate computes status based on policy, not on canned acl. AWS also fails" + "comment": "Not supported
S3 gate computes status based on policy, not on canned acl
AWS also fails" }, { "name": "Lifecycle transition", diff --git a/internal/templates/resources/tests-describe-template.gotmpl b/internal/templates/resources/tests-describe-template.gotmpl new file mode 100644 index 0000000..c8e9435 --- /dev/null +++ b/internal/templates/resources/tests-describe-template.gotmpl @@ -0,0 +1,7 @@ +# S3 Tests + +Commit: [7aae6ce2ca48ccd0ac35100af074281c7c88a210](https://git.frostfs.info/TrueCloudLab/s3-tests/commit/7aae6ce2ca48ccd0ac35100af074281c7c88a210) + +| Test | Group | Skip | Comment | +|------|-------|------|---------|{{range .}} +| {{.Name}} | {{.Group}} | {{.Skip}} | {{.Comment}} |{{end}} diff --git a/internal/templates/templates.go b/internal/templates/templates.go index fc79875..df7f9b0 100644 --- a/internal/templates/templates.go +++ b/internal/templates/templates.go @@ -35,6 +35,8 @@ var ( txtTemplate []byte //go:embed resources/md-template.gotmpl mdTemplate []byte + //go:embed resources/tests-describe-template.gotmpl + describeTemplate []byte ) func GetTemplate(outFormat string) (*template.Template, error) { @@ -84,3 +86,7 @@ func ColorToTerminal(color string) string { return blackTerminal } } + +func GetDescribeTemplate() (*template.Template, error) { + return template.New("describe-tests").Parse(string(describeTemplate)) +} -- 2.45.3 From e7cfdc0f79404e61b9b4c217518e15355f0c68ce Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Wed, 16 Apr 2025 10:55:55 +0300 Subject: [PATCH 4/4] [#11] Ignore recreate bucket tests Signed-off-by: Denis Kirillov --- internal/s3/resources/tests-struct.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/s3/resources/tests-struct.json b/internal/s3/resources/tests-struct.json index beadb89..9d5167d 100644 --- a/internal/s3/resources/tests-struct.json +++ b/internal/s3/resources/tests-struct.json @@ -1245,8 +1245,7 @@ "s3tests_boto3/functional/test_s3.py::test_versioned_concurrent_object_create_and_remove", "s3tests_boto3/functional/test_s3.py::test_versioning_bucket_atomic_upload_return_version_id", "s3tests_boto3/functional/test_s3.py::test_versioning_bucket_multipart_upload_return_version_id", - "s3tests_boto3/functional/test_s3.py::test_versioning_multi_object_delete_with_marker_create", - "s3tests_boto3/functional/test_s3.py::test_versioning_concurrent_multi_object_delete" + "s3tests_boto3/functional/test_s3.py::test_versioning_multi_object_delete_with_marker_create" ], "skip": false, "comment": "Limitations:
1. Don't create delete marker for non-existing objects" @@ -1704,10 +1703,11 @@ "name": "Recreate bucket", "tag": "Ignored", "tests": [ - "s3tests_boto3/functional/test_s3.py::test_bucket_recreate_not_overriding" + "s3tests_boto3/functional/test_s3.py::test_bucket_recreate_not_overriding", + "s3tests_boto3/functional/test_s3.py::test_versioning_concurrent_multi_object_delete" ], "skip": true, - "comment": "Expect success on bucket recreate in default region https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/537" + "comment": "Not supported
Expect success on bucket recreate in default region https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/537" }, { "name": "test_lifecycle_expiration_header_tags_head", -- 2.45.3