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))
+}