s3-tests-parser/cmd/parser/modules/compatibility.go

185 lines
4.1 KiB
Go
Raw Normal View History

package modules
import (
_ "embed"
"fmt"
"os"
"sort"
"strings"
"git.frostfs.info/TrueCloudLab/s3-tests-parser/internal/parser"
"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 compatibilityCmd = &cobra.Command{
Use: "compatibility",
Short: "Shows compatibility results",
Long: "Form compatibility table based on passed s3 tests",
Example: `s3-tests-parser compatibility suite.csv
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`,
RunE: runCompatibilityCmd,
}
type (
Results struct {
Legend []Status
TagGroups []TagGroup
}
TagGroup struct {
Name string
Tests []TestResult
}
Status struct {
Color string
Description string
}
TestResult struct {
Color string
Name string
Comment string
Passed int
Total int
}
)
const (
formatFlag = "format"
outputFlag = "output"
outputFormatFlag = "output-format"
)
func initCompatibilityCmd() {
compatibilityCmd.Flags().String(formatFlag, "csv", "format of input test suite file")
compatibilityCmd.Flags().String(outputFlag, "", "file to write output, if missed the stdout is used")
compatibilityCmd.Flags().String(outputFormatFlag, "txt", "format of output")
}
func runCompatibilityCmd(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
return fmt.Errorf("expected exactly one arg, got: %v", args)
}
testStruct, err := s3.ParseTestsStruct()
if err != nil {
return err
}
testsMap, err := parser.ParseSuite(args[0], viper.GetString(formatFlag))
if err != nil {
return fmt.Errorf("parse tests: %w", err)
}
res := formResults(testStruct, testsMap)
return printResults(cmd, res)
}
var legend = []Status{
{
Color: templates.GreenColor,
Description: "Supported",
},
{
Color: templates.YellowColor,
Description: "Partially supported",
},
{
Color: templates.RedColor,
Description: "Badly supported",
},
{
Color: templates.BlueColor,
Description: "Not supported yet, but will be in future",
},
{
Color: templates.BlackColor,
Description: "Not applicable or will never be supported",
},
}
func formResults(testStruct s3.TestsStructure, testsMap map[string]bool) Results {
tagGroups := make(map[string]TagGroup)
for _, group := range testStruct.Groups {
tagGroup, ok := tagGroups[group.Tag]
if !ok {
tagGroup.Name = group.Tag
}
tagGroup.Tests = append(tagGroup.Tests, formTestResult(group, testsMap))
tagGroups[group.Tag] = tagGroup
}
res := Results{Legend: legend}
for _, group := range tagGroups {
res.TagGroups = append(res.TagGroups, group)
}
sort.Slice(res.TagGroups, func(i, j int) bool {
return res.TagGroups[i].Name < res.TagGroups[j].Name
})
return res
}
func formTestResult(group s3.Group, testsMap map[string]bool) TestResult {
ln := len(group.Tests)
pass := 0
for _, test := range group.Tests {
if testsMap[test] {
pass++
}
}
var color string
if strings.Contains(group.Comment, "Not supported yet") {
color = templates.BlueColor
} else if strings.Contains(group.Comment, "Not applicable") {
color = templates.BlackColor
}
if color == "" {
color = templates.RedColor
rate := float64(pass) / float64(ln)
if rate > 0.9 {
color = templates.GreenColor
} else if rate > 0.5 {
color = templates.YellowColor
}
}
return TestResult{
Color: color,
Name: group.Name,
Comment: group.Comment,
Passed: pass,
Total: ln,
}
}
func printResults(cmd *cobra.Command, res Results) 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.GetTemplate(viper.GetString(outputFormatFlag))
if err != nil {
return fmt.Errorf("form out template: %w", err)
}
return outTemplate.Execute(w, res)
}