codekingpro/portable-devtools
114k
1// Copyright 2009 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5package testing6 7import (8 "fmt"9 "runtime"10 "slices"11 "strings"12 "time"13)14 15type InternalExample struct {16 Name string17 F func()18 Output string19 Unordered bool20}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.24func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) {25 _, ok = runExamples(matchString, examples)26 return ok27}28 29func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {30 ok = true31 32 m := newMatcher(matchString, *match, "-test.run", *skip)33 34 var eg InternalExample35 for _, eg = range examples {36 _, matched, _ := m.fullName(nil, eg.Name)37 if !matched {38 continue39 }40 ran = true41 if !runExample(eg) {42 ok = false43 }44 }45 46 return ran, ok47}48 49// processRunResult computes a summary and status of the result of running an example test.50// stdout is the captured output from stdout of the test.51// recovered is the result of invoking recover after running the test, in case it panicked.52//53// If stdout doesn't match the expected output or if recovered is non-nil, it'll print the cause of failure to stdout.54// If the test is chatty/verbose, it'll print a success message to stdout.55// If recovered is non-nil, it'll panic with that value.56// If the test panicked with nil, or invoked runtime.Goexit, it'll be57// made to fail and panic with errNilPanicOrGoexit58func (eg *InternalExample) processRunResult(stdout string, timeSpent time.Duration, finished bool, recovered any) (passed bool) {59 passed = true60 dstr := fmtDuration(timeSpent)61 var fail string62 got := strings.TrimSpace(stdout)63 want := strings.TrimSpace(eg.Output)64 if runtime.GOOS == "windows" {65 got = strings.ReplaceAll(got, "\r\n", "\n")66 want = strings.ReplaceAll(want, "\r\n", "\n")67 }68 if eg.Unordered {69 gotLines := slices.Sorted(strings.SplitSeq(got, "\n"))70 wantLines := slices.Sorted(strings.SplitSeq(want, "\n"))71 if !slices.Equal(gotLines, wantLines) && recovered == nil {72 fail = fmt.Sprintf("got:\n%s\nwant (unordered):\n%s\n", stdout, eg.Output)73 }74 } else {75 if got != want && recovered == nil {76 fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", got, want)77 }78 }79 if fail != "" || !finished || recovered != nil {80 fmt.Printf("%s--- FAIL: %s (%s)\n%s", chatty.prefix(), eg.Name, dstr, fail)81 passed = false82 } else if chatty.on {83 fmt.Printf("%s--- PASS: %s (%s)\n", chatty.prefix(), eg.Name, dstr)84 }85 86 if chatty.on && chatty.json {87 fmt.Printf("%s=== NAME %s\n", chatty.prefix(), "")88 }89 90 if recovered != nil {91 // Propagate the previously recovered result, by panicking.92 panic(recovered)93 } else if !finished {94 panic(errNilPanicOrGoexit)95 }96 97 return98}99 