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