From 2560fa4c5e4961dd15c9f94cbfca1da3056b9d33 Mon Sep 17 00:00:00 2001 From: Dan Rue Date: Tue, 2 Jan 2018 10:15:51 -0600 Subject: [PATCH] Generate a skipfile using yaml skipgen is a program that will generate a skiplist given a yaml file and optionally a board name, branch name, and enviornment name. --- .gitignore | 1 + LICENSE | 23 +++++++ Makefile | 5 ++ README.md | 41 ++++++++++++ examples/skipfile.yaml | 79 +++++++++++++++++++++++ skipgen.go | 121 +++++++++++++++++++++++++++++++++++ skipgen_test.go | 142 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 412 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 examples/skipfile.yaml create mode 100644 skipgen.go create mode 100644 skipgen_test.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..095334c --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2018, Linaro Limited +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4c1a965 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +test: + go test -v -cover + go vet + golint + diff --git a/README.md b/README.md new file mode 100644 index 0000000..b83597b --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ += Overview = + +skipgen is a program that will generate a skiplist given a yaml file and +optionally a board name, branch name, and enviornment name. + +== Usage == + + $ skipgen -skipfile examples/skipfile.yaml + seccomp_bpf + $ skipgen -skipfile examples/skipfile.yaml -board x15 -environment production + test_verifier + test_tag + test_maps + test_lru_map + test_lpm_map + test_progs + test_align + ... + +== Skipfile Format == + +See examples/skipfile.yaml. + +== Building == + +1. Install golang. i.e. on debian-based systems, run `apt-get install golang`. +2. Set GOPATH. See https://github.com/golang/go/wiki/SettingGOPATH. +3. Install go dependencies. `go get ./...` +4. go build +5. ./skipgen + +== Development == + +`$ go run skipgen.go` +`$ go run skipgen.go -skipfile examples/skipfile.yaml` +`$ go run skipgen.go -skipfile examples/skipfile.yaml -board x15 -environment production` + +== Testing == + +`make test` + diff --git a/examples/skipfile.yaml b/examples/skipfile.yaml new file mode 100644 index 0000000..2980aa7 --- /dev/null +++ b/examples/skipfile.yaml @@ -0,0 +1,79 @@ +skiplist: + - reason: kernel tests baselining + url: https://projects.linaro.org/projects/CTT/queues/issue/CTT-585 + environments: + - production + - staging + boards: + - all + branches: + - all + tests: + - test_verifier + - test_tag + - test_maps + - test_lru_map + - test_lpm_map + - test_progs + - test_align + - test_kmod.sh + - ftracetest + - run.sh + - run_fuse_test.sh + - pstore_tests + + - reason: "LKFT: linux-next: vm compaction_test : ERROR: Less that 1/730 of memory + is available" + url: https://bugs.linaro.org/show_bug.cgi?id=3145 + environments: + - staging + boards: all + branches: all + tests: + - run_vmtests + + - reason: "LKFT: selftests: seccomp TRACE_syscall.skip_after_RET_TRACE" + url: https://bugs.linaro.org/show_bug.cgi?id=2980 + environments: all + boards: all + branches: all + tests: + - seccomp_bpf + + - reason: "LKFT: linux-next: kselftest: breakpoint_test_arm64 build failed" + url: https://bugs.linaro.org/show_bug.cgi?id=3208 + environments: production + boards: + - hi6220 + - hikey + - juno + - x15 + branches: all + tests: + - breakpoint_test_arm64 + + - reason: "LKFT: linux-mainline: kselftest sync_test failed" + url: https://bugs.linaro.org/show_bug.cgi?id=3504 + environments: production + boards: all + branches: all + tests: + - sync_test + + - reason: "LKFT: linux-mainline: x86, x15, juno-r2: kselftest + fw_filesystem.sh failed" + url: https://bugs.linaro.org/show_bug.cgi?id=3503 + environments: production + boards: all + branches: all + tests: + - fw_filesystem.sh + + - reason: "LKFT: linux-mainline: kselftest BPF test_dev_cgroup failed (new test case) + on all devices" + url: https://bugs.linaro.org/show_bug.cgi?id=3500 + environments: production + boards: all + branches: all + tests: + - test_dev_cgroup diff --git a/skipgen.go b/skipgen.go new file mode 100644 index 0000000..b37ecc9 --- /dev/null +++ b/skipgen.go @@ -0,0 +1,121 @@ +// skipgen is a program that will generate a skiplist given a yaml file +// and optionally, board name, branch name, and environment name. + +package main + +import ( + "fmt" + "io/ioutil" + "gopkg.in/yaml.v2" + "flag" + "os" +) + +func check(e error) { + if e != nil { + panic(e) + } +} + +// StringArray is a custom type that can be used for parsing +// yaml fields that can be either a string, or an array. +// See https://github.com/go-yaml/yaml/issues/100 +type StringArray []string +// UnmarshalYAML is a custom version of UnmarshalYAML that implements +// StringArray. See https://github.com/go-yaml/yaml/issues/100 +func (a *StringArray) UnmarshalYAML(unmarshal func(interface{}) error) error { + var multi []string + err := unmarshal(&multi) + if err != nil { + var single string + err := unmarshal(&single) + if err != nil { + return err + } + *a = []string{single} + } else { + *a = multi + } + return nil +} + +// stringInSlice searches for a particular string +// in a slice of strings. If "all" is contained in +// the slice, then true is always returned. +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a || b == "all" { + return true + } + } + return false +} + +// Skipfile is a map of the structure in the yaml skipfile +type Skipfile struct { + Skiplist []struct { + Reason string + URL string + Environments StringArray + Boards StringArray + Branches StringArray + Tests []string + } +} + +// parseSkipfile parses a given buf and returns a Skipfile +// struct and err, if any. +func parseSkipfile(buf []byte) (Skipfile, error){ + var skips Skipfile + err := yaml.Unmarshal(buf, &skips) + return skips, err +} + +// getSkipfileContents returns a string containing a skipfile +// given a board, environment, branch, and Skipfile struct. +func getSkipfileContents(board string, branch string, environment string, skips Skipfile) (string){ + var buf string + buf = "" + for _, skip := range skips.Skiplist { + if stringInSlice(board, skip.Boards) && + stringInSlice(branch, skip.Branches) && + stringInSlice(environment, skip.Environments) { + for _, test := range skip.Tests { + buf = buf + fmt.Sprintf("%s\n", test) + } + } + } + return buf +} + +func main() { + + boardPtr := flag.String("board", "all", "(Optional) board name. If not specified, skips that apply to all boards will be returned.") + branchPtr := flag.String("branch", "all", "(Optional) branch name. If not specified, skips that apply to all branches will be returned.") + environmentPtr := flag.String("environment", "all", "(Optional) environment name. If not specified, skips that apply to all environments will be returned.") + skipfilePtr := flag.String("skipfile", "", "Required. Skipfile in yaml format.") + flag.Parse() + + if len(*skipfilePtr) < 1 { + fmt.Fprintf(os.Stderr, "Error: -skipfile not provided\n") + os.Exit(1) + } + + _, err := os.Stat(*skipfilePtr) + if os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, "Error: skipfile '%s' not found\n", *skipfilePtr) + os.Exit(1) + } + check(err) + + // Read skipfile.yaml + buf, err := ioutil.ReadFile(*skipfilePtr) + check(err) + + // Parse skipfile + skips, err := parseSkipfile(buf) + check(err) + + fmt.Printf(getSkipfileContents(*boardPtr, *branchPtr, *environmentPtr, skips)) + +} diff --git a/skipgen_test.go b/skipgen_test.go new file mode 100644 index 0000000..ab3b0af --- /dev/null +++ b/skipgen_test.go @@ -0,0 +1,142 @@ +package main + +import ( + "testing" +) + +func TestStringInSlicePositive(t *testing.T) { + slice := []string{"one", "two", "three", "four", "five"} + + result := stringInSlice("one", slice) + if ! result { + t.Errorf("'one' not found in %s", slice) + } +} +func TestStringInSliceNegative(t *testing.T) { + slice := []string{"one", "two", "three", "four", "five"} + + result := stringInSlice("zero", slice) + if result { + t.Errorf("'zero' found in %s", slice) + } +} + +func TestSkipAll(t *testing.T) { + + skipAll := ` +matrix: + environments: + - production + - staging + boards: + - x15 + - juno + - hikey + branches: + - 4.4 + - 4.9 + - mainline + +skiplist: + - reason: kernel tests baselining + url: https://projects.linaro.org/projects/CTT/queues/issue/CTT-585 + environments: all # Test this form + boards: + - all # And test this form + branches: + - all + tests: + - test_maps + - test_lru_map + - test_lpm_map + - test_progs + - reason: "LKFT: linux-next: vm compaction_test : ERROR: Less that 1/730 of memory + is available" + url: https://bugs.linaro.org/show_bug.cgi?id=3145 + environments: + - production + - staging + boards: + - x15 + - juno + - hikey + branches: + - "4.4" + - 4.9 + - mainline + tests: + - run_vmtests +` + skips, err := parseSkipfile([]byte(skipAll)) + if err != nil { + t.Errorf("Unexpected error parsing yaml, %s", err) + } + + t.Run("parseSkipfile spotcheck", func(t *testing.T) { + if skips.Skiplist[0].Reason != "kernel tests baselining" { + t.Errorf("Parsing error, skiplist is wrong") + } + }) + + t.Run("getSkipfileContents", func(t *testing.T) { + if getSkipfileContents("x15", "4.4", "production", skips) != +`test_maps +test_lru_map +test_lpm_map +test_progs +run_vmtests +`{ + t.Errorf("Incorrect Skipfile Contents") + } + }) + +} + +func TestSkipMinimum(t *testing.T) { + + skipAll := ` +matrix: + environments: + - production + boards: + - x15 + branches: + - 4.4 + +skiplist: + - reason: Some test reason + url: https://bugs.linaro.org/show_bug.cgi?id=3145 + environments: + - production + boards: + - x15 + branches: + - "4.4" + tests: + - run_vmtests +` + skips, err := parseSkipfile([]byte(skipAll)) + if err != nil { + t.Errorf("Unexpected error parsing yaml, %s", err) + } + + t.Run("parseSkipfile spotcheck", func(t *testing.T) { + if skips.Skiplist[0].Reason != "Some test reason" { + t.Errorf("Parsing error, skiplist is wrong") + } + }) + + t.Run("getSkipfileContents positive", func(t *testing.T) { + if getSkipfileContents("x15", "4.4", "production", skips) != +`run_vmtests +` { + t.Errorf("Incorrect Skipfile Contents") + } + }) + + t.Run("getSkipfileContents empty", func(t *testing.T) { + if getSkipfileContents("x15", "4.9", "production", skips) != "" { + t.Errorf("Incorrect Skipfile Contents") + } + }) +}