1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package testing 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "os" 12 "strings" 13 "time" 14 ) 15 16 type InternalExample struct { 17 Name string 18 F func() 19 Output string 20 } 21 22 func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) { 23 ok = true 24 25 var eg InternalExample 26 27 for _, eg = range examples { 28 matched, err := matchString(*match, eg.Name) 29 if err != nil { 30 fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err) 31 os.Exit(1) 32 } 33 if !matched { 34 continue 35 } 36 if !runExample(eg) { 37 ok = false 38 } 39 } 40 41 return 42 } 43 44 func runExample(eg InternalExample) (ok bool) { 45 if *chatty { 46 fmt.Printf("=== RUN %s\n", eg.Name) 47 } 48 49 // Capture stdout. 50 stdout := os.Stdout 51 r, w, err := os.Pipe() 52 if err != nil { 53 fmt.Fprintln(os.Stderr, err) 54 os.Exit(1) 55 } 56 os.Stdout = w 57 outC := make(chan string) 58 go func() { 59 var buf bytes.Buffer 60 _, err := io.Copy(&buf, r) 61 r.Close() 62 if err != nil { 63 fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err) 64 os.Exit(1) 65 } 66 outC <- buf.String() 67 }() 68 69 start := time.Now() 70 ok = true 71 72 // Clean up in a deferred call so we can recover if the example panics. 73 defer func() { 74 dstr := fmtDuration(time.Now().Sub(start)) 75 76 // Close pipe, restore stdout, get output. 77 w.Close() 78 os.Stdout = stdout 79 out := <-outC 80 81 var fail string 82 err := recover() 83 if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e && err == nil { 84 fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", g, e) 85 } 86 if fail != "" || err != nil { 87 fmt.Printf("--- FAIL: %s (%s)\n%s", eg.Name, dstr, fail) 88 ok = false 89 } else if *chatty { 90 fmt.Printf("--- PASS: %s (%s)\n", eg.Name, dstr) 91 } 92 if err != nil { 93 panic(err) 94 } 95 }() 96 97 // Run example. 98 eg.F() 99 return 100 } 101