From afad4671944c3a03f87fabd4bef00f06f9f67903 Mon Sep 17 00:00:00 2001 From: Mark Ryan Date: Wed, 19 Oct 2016 11:14:57 +0100 Subject: [PATCH 1/2] test-cases, travis: Add support for TAP reports This commit adds test-cases support for the generation of TAP reports. It also takes the oppurtunity to rationalize the options for specifying the output format. There is now one format option, --format, which accepts a number of different values; html, tap, colour-text and text. The default is colour-text. This change requires a modification to the travis script that executes test-cases, as the old formatting option used by travis.yml no longer exists. Signed-off-by: Mark Ryan --- .travis.yml | 8 ++-- test-cases/test-cases.go | 90 ++++++++++++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0bffabd13..29b1d31a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,10 +58,10 @@ script: - go list ./... | grep -v github.com/01org/ciao/vendor | xargs go list -f '{{.Dir}}' | xargs gofmt -s -l | wc -l | xargs -I % bash -c "test % -eq 0" - sudo mkdir -p /var/lib/ciao/instances - sudo chmod 0777 /var/lib/ciao/instances - - test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -short github.com/01org/ciao/ciao-controller/... - - test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -append-profile -short github.com/01org/ciao/ciao-launcher github.com/01org/ciao/ciao-scheduler github.com/01org/ciao/payloads github.com/01org/ciao/configuration github.com/01org/ciao/testutil github.com/01org/ciao/ssntp/uuid github.com/01org/ciao/qemu github.com/01org/ciao/openstack/... - - export GOROOT=`go env GOROOT` && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -text -coverprofile /tmp/cover.out -append-profile github.com/01org/ciao/ssntp - - export GOROOT=`go env GOROOT` && export SNNET_ENV=198.51.100.0/24 && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -text -short -tags travis -coverprofile /tmp/cover.out -append-profile github.com/01org/ciao/networking/libsnnet + - test-cases -v -timeout 9 -coverprofile /tmp/cover.out -short github.com/01org/ciao/ciao-controller/... + - test-cases -v -timeout 9 -coverprofile /tmp/cover.out -append-profile -short github.com/01org/ciao/ciao-launcher github.com/01org/ciao/ciao-scheduler github.com/01org/ciao/payloads github.com/01org/ciao/configuration github.com/01org/ciao/testutil github.com/01org/ciao/ssntp/uuid github.com/01org/ciao/qemu github.com/01org/ciao/openstack/... + - export GOROOT=`go env GOROOT` && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -coverprofile /tmp/cover.out -append-profile github.com/01org/ciao/ssntp + - export GOROOT=`go env GOROOT` && export SNNET_ENV=198.51.100.0/24 && sudo -E PATH=$PATH:$GOROOT/bin $GOPATH/bin/test-cases -v -timeout 9 -short -tags travis -coverprofile /tmp/cover.out -append-profile github.com/01org/ciao/networking/libsnnet # API Documentation is automated by swagger, every PR will verify the documentation can be generated # verify ciao-controller api documentation can be generated with swagger - go get github.com/yvasiyarov/swagger diff --git a/test-cases/test-cases.go b/test-cases/test-cases.go index 216baebde..e87e54c03 100644 --- a/test-cases/test-cases.go +++ b/test-cases/test-cases.go @@ -135,32 +135,55 @@ const htmlTemplate = ` ` +var newLineRegexp = regexp.MustCompile(`(\r\n)|[\n\r]`) + +type formatType string + +const ( + formatText formatType = "text" + formatColourText = "colour-text" + formatHTML = "html" + formatTAP = "tap" +) + +func (f *formatType) String() string { + return string(*f) +} +func (f *formatType) Set(val string) error { + v := formatType(val) + if v != formatText && v != formatColourText && v != formatHTML && v != formatTAP { + return fmt.Errorf("invalid format; %s, %s, %s, %s expected", + formatText, formatColourText, formatHTML, formatTAP) + } + *f = formatType(val) + return nil +} + var resultRegexp *regexp.Regexp var coverageRegexp *regexp.Regexp var cssPath string -var textOutput bool var short bool var race bool var tags string -var colour bool var coverProfile string var appendProfile bool +var format formatType = formatColourText var timeout int var verbose bool func init() { flag.StringVar(&cssPath, "css", "", "Full path to CSS file") - flag.BoolVar(&textOutput, "text", false, "Output text instead of HTML") flag.BoolVar(&short, "short", false, "If true -short is passed to go test") flag.BoolVar(&race, "race", false, "If true -race is passed to go test") flag.StringVar(&tags, "tags", "", "Build tags to pass to go test") flag.StringVar(&coverProfile, "coverprofile", "", "Path of coverage profile to be generated") flag.BoolVar(&appendProfile, "append-profile", false, "Append generated coverage profiles an existing file") - flag.BoolVar(&colour, "colour", true, "If true failed tests are coloured red in text mode") flag.BoolVar(&verbose, "v", false, "Output package names under test if true") flag.IntVar(&timeout, "timeout", 0, "Time in minutes after which a package's unit tests should time out. 0 = no timeout") + flag.Var(&format, "format", fmt.Sprintf("Specify output format. Can be '%s', '%s', '%s', or '%s'", + formatText, formatColourText, formatHTML, formatTAP)) flag.Usage = func() { fmt.Fprintf(os.Stderr, "usage: %s [flags] [packages]\n", os.Args[0]) @@ -672,6 +695,33 @@ func runTests(tests []*PackageTests) (int, *bytes.Buffer, error) { return exitCode, &errorOutput, nil } +func generateTAPOutput(tests []*PackageTests) { + i := 0 + prefix := findCommonPrefix(tests) + for _, p := range tests { + pkgName := p.Name[len(prefix):] + fmt.Printf("# Tests for %s\n", pkgName) + for _, t := range p.Tests { + if t.Result == "PASS" { + fmt.Printf("ok ") + } else { + fmt.Printf("not ok ") + } + testName := strings.TrimSpace(t.Summary) + if testName == "" { + testName = t.Name + } else { + testName = newLineRegexp.ReplaceAllString(testName, " ") + } + fmt.Printf("%d - %s\n", i+1, testName) + i++ + } + } + if i > 0 { + fmt.Printf("1..%d\n", i) + } +} + func main() { flag.Parse() @@ -687,26 +737,24 @@ func main() { log.Fatal(err) } - if textOutput { - if colour { - generateColourTextReport(tests, exitCode) - } else { - generateTextReport(tests, exitCode) + switch format { + case formatText: + generateTextReport(tests, exitCode) + if exitCode != 0 { + dumpErrorOutput(errorOutput) } - } else { - err = generateHTMLReport(tests) - } - - if exitCode != 0 { - if colour { + case formatColourText: + generateColourTextReport(tests, exitCode) + if exitCode != 0 { dumpColourErrorOutput(errorOutput) - } else { - dumpErrorOutput(errorOutput) } - } - - if err != nil { - log.Fatalf("Unable to generate report: %s\n", err) + case formatTAP: + generateTAPOutput(tests) + case formatHTML: + err := generateHTMLReport(tests) + if err != nil { + log.Fatalf("Unable to generate report: %s\n", err) + } } os.Exit(exitCode) From a8efaf8a8fc94be8182890fa8ac595b1425a20d2 Mon Sep 17 00:00:00 2001 From: Mark Ryan Date: Wed, 19 Oct 2016 16:41:31 +0100 Subject: [PATCH 2/2] openstack: Don't close request bodies in handlers The image service code seems to be closing the bodies of received requests in its handlers. This breaks in Go 1.8 as these bodies are likely to be nil. Also, unless I'm mistaken, there's no need for the server to close the bodies. This is only needed for clients that pass a file or a socket to http.NewRequest. Signed-off-by: Mark Ryan --- openstack/image/api.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/openstack/image/api.go b/openstack/image/api.go index 437ff9e5f..5b1907184 100644 --- a/openstack/image/api.go +++ b/openstack/image/api.go @@ -367,8 +367,6 @@ func getImage(context *Context, w http.ResponseWriter, r *http.Request) (APIResp vars := mux.Vars(r) imageID := vars["image_id"] - defer r.Body.Close() - resp, err := context.GetImage(imageID) if err != nil { return errorResponse(err), err @@ -380,8 +378,6 @@ func uploadImage(context *Context, w http.ResponseWriter, r *http.Request) (APIR vars := mux.Vars(r) imageID := vars["image_id"] - defer r.Body.Close() - _, err := context.UploadImage(imageID, r.Body) if err != nil { return errorResponse(err), err @@ -393,8 +389,6 @@ func deleteImage(context *Context, w http.ResponseWriter, r *http.Request) (APIR vars := mux.Vars(r) imageID := vars["image_id"] - defer r.Body.Close() - _, err := context.DeleteImage(imageID) if err != nil { return errorResponse(err), err