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