From 1440cebda12898a4d33f5f5c120530f9251cb724 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Tue, 15 Apr 2025 15:21:11 +0300 Subject: [PATCH] [#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)) +}