github.com/AndrienkoAleksandr/go@v0.0.19/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 "fmt" 9 "os" 10 "sort" 11 "strings" 12 "time" 13 ) 14 15 type InternalExample struct { 16 Name string 17 F func() 18 Output string 19 Unordered bool 20 } 21 22 // RunExamples is an internal function but exported because it is cross-package; 23 // it is part of the implementation of the "go test" command. 24 func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) { 25 _, ok = runExamples(matchString, examples) 26 return ok 27 } 28 29 func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) { 30 ok = true 31 32 var eg InternalExample 33 34 for _, eg = range examples { 35 matched, err := matchString(*match, eg.Name) 36 if err != nil { 37 fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err) 38 os.Exit(1) 39 } 40 if !matched { 41 continue 42 } 43 ran = true 44 if !runExample(eg) { 45 ok = false 46 } 47 } 48 49 return ran, ok 50 } 51 52 func sortLines(output string) string { 53 lines := strings.Split(output, "\n") 54 sort.Strings(lines) 55 return strings.Join(lines, "\n") 56 } 57 58 // processRunResult computes a summary and status of the result of running an example test. 59 // stdout is the captured output from stdout of the test. 60 // recovered is the result of invoking recover after running the test, in case it panicked. 61 // 62 // If stdout doesn't match the expected output or if recovered is non-nil, it'll print the cause of failure to stdout. 63 // If the test is chatty/verbose, it'll print a success message to stdout. 64 // If recovered is non-nil, it'll panic with that value. 65 // If the test panicked with nil, or invoked runtime.Goexit, it'll be 66 // made to fail and panic with errNilPanicOrGoexit 67 func (eg *InternalExample) processRunResult(stdout string, timeSpent time.Duration, finished bool, recovered any) (passed bool) { 68 passed = true 69 dstr := fmtDuration(timeSpent) 70 var fail string 71 got := strings.TrimSpace(stdout) 72 want := strings.TrimSpace(eg.Output) 73 if eg.Unordered { 74 if sortLines(got) != sortLines(want) && recovered == nil { 75 fail = fmt.Sprintf("got:\n%s\nwant (unordered):\n%s\n", stdout, eg.Output) 76 } 77 } else { 78 if got != want && recovered == nil { 79 fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", got, want) 80 } 81 } 82 if fail != "" || !finished || recovered != nil { 83 fmt.Printf("%s--- FAIL: %s (%s)\n%s", chatty.prefix(), eg.Name, dstr, fail) 84 passed = false 85 } else if chatty.on { 86 fmt.Printf("%s--- PASS: %s (%s)\n", chatty.prefix(), eg.Name, dstr) 87 } 88 89 if chatty.on && chatty.json { 90 fmt.Printf("%s=== NAME %s\n", chatty.prefix(), "") 91 } 92 93 if recovered != nil { 94 // Propagate the previously recovered result, by panicking. 95 panic(recovered) 96 } else if !finished { 97 panic(errNilPanicOrGoexit) 98 } 99 100 return 101 }