From: Andrew Gerrand Date: Thu, 17 Jan 2013 23:28:18 +0000 (+1100) Subject: testing: catch panicking example and report, just like tests X-Git-Tag: go1.1rc2~1371 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5bd5ed2b579f656e5804ec6c1f715b5b43161932;p=gostls13.git testing: catch panicking example and report, just like tests Fixes #4670. R=rsc CC=golang-dev https://golang.org/cl/7148043 --- diff --git a/src/pkg/testing/example.go b/src/pkg/testing/example.go index 34d4b2bda9..4aec4830e1 100644 --- a/src/pkg/testing/example.go +++ b/src/pkg/testing/example.go @@ -24,8 +24,6 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int var eg InternalExample - stdout := os.Stdout - for _, eg = range examples { matched, err := matchString(*match, eg.Name) if err != nil { @@ -35,49 +33,66 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int if !matched { continue } - if *chatty { - fmt.Printf("=== RUN: %s\n", eg.Name) + if !runExample(eg) { + ok = false } + } + + return +} + +func runExample(eg InternalExample) (ok bool) { + if *chatty { + fmt.Printf("=== RUN: %s\n", eg.Name) + } - // capture stdout - r, w, err := os.Pipe() + // Capture stdout. + stdout := os.Stdout + r, w, err := os.Pipe() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + os.Stdout = w + outC := make(chan string) + go func() { + buf := new(bytes.Buffer) + _, err := io.Copy(buf, r) + r.Close() if err != nil { - fmt.Fprintln(os.Stderr, err) + fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err) os.Exit(1) } - os.Stdout = w - outC := make(chan string) - go func() { - buf := new(bytes.Buffer) - _, err := io.Copy(buf, r) - r.Close() - if err != nil { - fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err) - os.Exit(1) - } - outC <- buf.String() - }() + outC <- buf.String() + }() - // run example - t0 := time.Now() - eg.F() - dt := time.Now().Sub(t0) + start := time.Now() - // close pipe, restore stdout, get output + // Clean up in a deferred call so we can recover if the example panics. + defer func() { + d := time.Now().Sub(start) + + // Close pipe, restore stdout, get output. w.Close() os.Stdout = stdout out := <-outC - // report any errors - tstr := fmt.Sprintf("(%.2f seconds)", dt.Seconds()) - if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e { - fmt.Printf("--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n", - eg.Name, tstr, g, e) - ok = false + var fail string + err := recover() + if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e && err == nil { + fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", g, e) + } + if fail != "" || err != nil { + fmt.Printf("--- FAIL: %s (%v)\n%s", eg.Name, d, fail) } else if *chatty { - fmt.Printf("--- PASS: %s %s\n", eg.Name, tstr) + fmt.Printf("--- PASS: %s (%v)\n", eg.Name, d) } - } + if err != nil { + panic(err) + } + }() + // Run example. + eg.F() return }