example.go 1.9 KB

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