github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/testing/example.go (about) 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 "sort" 13 "strings" 14 "time" 15 ) 16 17 type InternalExample struct { 18 Name string 19 F func() 20 Output string 21 Unordered bool 22 } 23 24 func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) { 25 ok = true 26 27 var eg InternalExample 28 29 for _, eg = range examples { 30 matched, err := matchString(*match, eg.Name) 31 if err != nil { 32 fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err) 33 os.Exit(1) 34 } 35 if !matched { 36 continue 37 } 38 if !runExample(eg) { 39 ok = false 40 } 41 } 42 43 return 44 } 45 46 func sortLines(output string) string { 47 lines := strings.Split(output, "\n") 48 sort.Strings(lines) 49 return strings.Join(lines, "\n") 50 } 51 52 func runExample(eg InternalExample) (ok bool) { 53 if *chatty { 54 fmt.Printf("=== RUN %s\n", eg.Name) 55 } 56 57 // Capture stdout. 58 stdout := os.Stdout 59 r, w, err := os.Pipe() 60 if err != nil { 61 fmt.Fprintln(os.Stderr, err) 62 os.Exit(1) 63 } 64 os.Stdout = w 65 outC := make(chan string) 66 go func() { 67 var buf bytes.Buffer 68 _, err := io.Copy(&buf, r) 69 r.Close() 70 if err != nil { 71 fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err) 72 os.Exit(1) 73 } 74 outC <- buf.String() 75 }() 76 77 start := time.Now() 78 ok = true 79 80 // Clean up in a deferred call so we can recover if the example panics. 81 defer func() { 82 dstr := fmtDuration(time.Now().Sub(start)) 83 84 // Close pipe, restore stdout, get output. 85 w.Close() 86 os.Stdout = stdout 87 out := <-outC 88 89 var fail string 90 err := recover() 91 got := strings.TrimSpace(out) 92 want := strings.TrimSpace(eg.Output) 93 if eg.Unordered { 94 if sortLines(got) != sortLines(want) && err == nil { 95 fail = fmt.Sprintf("got:\n%s\nwant (unordered):\n%s\n", out, eg.Output) 96 } 97 } else { 98 if got != want && err == nil { 99 fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", got, want) 100 } 101 } 102 if fail != "" || err != nil { 103 fmt.Printf("--- FAIL: %s (%s)\n%s", eg.Name, dstr, fail) 104 ok = false 105 } else if *chatty { 106 fmt.Printf("--- PASS: %s (%s)\n", eg.Name, dstr) 107 } 108 if err != nil { 109 panic(err) 110 } 111 }() 112 113 // Run example. 114 eg.F() 115 return 116 }