add tests for command line parsing

This commit is contained in:
Yann Hamon 2020-11-01 23:18:39 +01:00
parent 51e5f38430
commit 0152d8c209
4 changed files with 100 additions and 36 deletions

View file

@ -100,10 +100,12 @@ func processResults(o output.Output, validationResults <-chan validator.Result,
} }
func realMain() int { func realMain() int {
var err error cfg, out, err := config.FromFlags(os.Args[0], os.Args[1:])
if out != "" {
cfg := config.FromFlags() fmt.Println(out)
if cfg.Help { return 1
} else if err != nil {
fmt.Fprintf(os.Stderr, "failed parsing command line: %s\n", err.Error())
return 1 return 1
} }

View file

@ -1,6 +1,7 @@
package config package config
import ( import (
"bytes"
"flag" "flag"
"fmt" "fmt"
"os" "os"
@ -45,29 +46,32 @@ func skipKinds(skipKindsCSV string) map[string]bool {
return skipKinds return skipKinds
} }
func FromFlags() Config { func FromFlags(progName string, args []string) (Config, string, error) {
var schemaLocationsParam arrayParam var schemaLocationsParam arrayParam
var skipKindsCSV string var skipKindsCSV string
flags := flag.NewFlagSet(progName, flag.PanicOnError)
var buf bytes.Buffer
flags.SetOutput(&buf)
c := Config{} c := Config{}
c.Files = []string{} c.Files = []string{}
flag.StringVar(&c.KubernetesVersion, "kubernetes-version", "1.18.0", "version of Kubernetes to validate against") flags.StringVar(&c.KubernetesVersion, "kubernetes-version", "1.18.0", "version of Kubernetes to validate against")
flag.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)") flags.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)")
flag.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds to ignore") flags.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds to ignore")
flag.BoolVar(&c.IgnoreMissingSchemas, "ignore-missing-schemas", false, "skip files with missing schemas instead of failing") flags.BoolVar(&c.IgnoreMissingSchemas, "ignore-missing-schemas", false, "skip files with missing schemas instead of failing")
flag.BoolVar(&c.Summary, "summary", false, "print a summary at the end") flags.BoolVar(&c.Summary, "summary", false, "print a summary at the end")
flag.IntVar(&c.NumberOfWorkers, "n", 4, "number of goroutines to run concurrently") flags.IntVar(&c.NumberOfWorkers, "n", 4, "number of goroutines to run concurrently")
flag.BoolVar(&c.Strict, "strict", false, "disallow additional properties not in schema") flags.BoolVar(&c.Strict, "strict", false, "disallow additional properties not in schema")
flag.StringVar(&c.OutputFormat, "output", "text", "output format - text, json") flags.StringVar(&c.OutputFormat, "output", "text", "output format - text, json")
flag.BoolVar(&c.Verbose, "verbose", false, "print results for all resources") flags.BoolVar(&c.Verbose, "verbose", false, "print results for all resources")
flag.BoolVar(&c.Help, "h", false, "show help information") flags.BoolVar(&c.Help, "h", false, "show help information")
flag.Usage = func() { flags.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]... [FILE OR FOLDER]...\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]... [FILE OR FOLDER]...\n", progName)
flag.PrintDefaults() flags.PrintDefaults()
} }
flag.Parse() err := flags.Parse(args)
c.SkipKinds = skipKinds(skipKindsCSV) c.SkipKinds = skipKinds(skipKindsCSV)
c.SchemaLocations = schemaLocationsParam c.SchemaLocations = schemaLocationsParam
@ -75,13 +79,11 @@ func FromFlags() Config {
c.SchemaLocations = append(c.SchemaLocations, "https://kubernetesjsonschema.dev") // if not specified, default behaviour is to use kubernetesjson-schema.dev as registry c.SchemaLocations = append(c.SchemaLocations, "https://kubernetesjsonschema.dev") // if not specified, default behaviour is to use kubernetesjson-schema.dev as registry
} }
for _, file := range flag.Args() { c.Files = flags.Args()
c.Files = append(c.Files, file)
}
if c.Help { if c.Help {
flag.Usage() flags.Usage()
} }
return c return c, buf.String(), err
} }

View file

@ -39,3 +39,65 @@ func TestSkipKindMaps(t *testing.T) {
} }
} }
} }
func TestFromFlags(t *testing.T) {
testCases := []struct {
args []string
conf Config
}{
{
[]string{},
Config{
Files: []string{},
KubernetesVersion: "1.18.0",
NumberOfWorkers: 4,
OutputFormat: "text",
SchemaLocations: []string{"https://kubernetesjsonschema.dev"},
SkipKinds: map[string]bool{},
},
},
{
[]string{"-h"},
Config{
Files: []string{},
Help: true,
KubernetesVersion: "1.18.0",
NumberOfWorkers: 4,
OutputFormat: "text",
SchemaLocations: []string{"https://kubernetesjsonschema.dev"},
SkipKinds: map[string]bool{},
},
},
{
[]string{"-skip", "a,b,c"},
Config{
Files: []string{},
KubernetesVersion: "1.18.0",
NumberOfWorkers: 4,
OutputFormat: "text",
SchemaLocations: []string{"https://kubernetesjsonschema.dev"},
SkipKinds: map[string]bool{"a": true, "b": true, "c": true},
},
},
{
[]string{"-summary", "-verbose", "file1", "file2"},
Config{
Files: []string{"file1", "file2"},
KubernetesVersion: "1.18.0",
NumberOfWorkers: 4,
OutputFormat: "text",
SchemaLocations: []string{"https://kubernetesjsonschema.dev"},
SkipKinds: map[string]bool{},
Summary: true,
Verbose: true,
},
},
}
for _, testCase := range testCases {
cfg, _, _ := FromFlags("kubeconform", testCase.args)
if reflect.DeepEqual(cfg, testCase.conf) != true {
t.Errorf("failed parsing config - expected , got: \n%+v\n%+v", testCase.conf, cfg)
}
}
}

View file

@ -10,25 +10,23 @@ import (
"testing" "testing"
) )
func TestFromStream(t *testing.T) { func TestFromStream(t *testing.T) {
type have struct { type have struct {
Path string Path string
Reader io.Reader Reader io.Reader
} }
type want struct { type want struct {
Resources []resource.Resource Resources []resource.Resource
Errors []error Errors []error
} }
testCases := []struct { testCases := []struct {
Have have Have have
Want want Want want
} { }{
{ {
Have: have { Have: have{
Path: "myfile", Path: "myfile",
Reader: strings.NewReader(` Reader: strings.NewReader(`
apiVersion: v1 apiVersion: v1
@ -49,7 +47,7 @@ kind: ReplicationController
}, },
}, },
{ {
Have: have { Have: have{
Path: "myfile", Path: "myfile",
Reader: strings.NewReader(`apiVersion: v1 Reader: strings.NewReader(`apiVersion: v1
--- ---
@ -65,7 +63,7 @@ apiVersion: v2
`), `),
}, },
{ {
Path: "myfile", Path: "myfile",
Bytes: []byte(``), Bytes: []byte(``),
}, },
{ {
@ -78,7 +76,7 @@ apiVersion: v2
}, },
}, },
{ {
Have: have { Have: have{
Path: "myfile", Path: "myfile",
Reader: strings.NewReader(`apiVersion: v1 Reader: strings.NewReader(`apiVersion: v1
kind: ReplicationController kind: ReplicationController
@ -115,7 +113,7 @@ kind: CronJob
}, },
}, },
{ {
Have: have { Have: have{
Path: "myfile", Path: "myfile",
Reader: strings.NewReader(`apiVersion: v1 Reader: strings.NewReader(`apiVersion: v1
kind: ReplicationController kind: ReplicationController
@ -145,7 +143,7 @@ kind: Deployment
} }
for _, testCase := range testCases { for _, testCase := range testCases {
resChan, errChan :=resource.FromStream(testCase.Have.Path, testCase.Have.Reader) resChan, errChan := resource.FromStream(testCase.Have.Path, testCase.Have.Reader)
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(2) wg.Add(2)
@ -180,4 +178,4 @@ kind: Deployment
wg.Wait() wg.Wait()
} }
} }