...
Run Format

Source file src/testing/example.go

Documentation: testing

     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  }
   124  

View as plain text