spew_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * Copyright (c) 2013 Dave Collins <dave@davec.name>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. package spew_test
  17. import (
  18. "bytes"
  19. "fmt"
  20. "github.com/davecgh/go-spew/spew"
  21. "io/ioutil"
  22. "os"
  23. "testing"
  24. )
  25. // stringizeWants converts a slice of wanted test output into a format suitable
  26. // for an test error message.
  27. func stringizeWants(wants []string) string {
  28. s := ""
  29. for i, want := range wants {
  30. if i > 0 {
  31. s += fmt.Sprintf("want%d: %s", i+1, want)
  32. } else {
  33. s += "want: " + want
  34. }
  35. }
  36. return s
  37. }
  38. // testFailed returns whether or not a test failed by checking if the result
  39. // of the test is in the slice of wanted strings.
  40. func testFailed(result string, wants []string) bool {
  41. for _, want := range wants {
  42. if result == want {
  43. return false
  44. }
  45. }
  46. return true
  47. }
  48. // panicer is used to intentionally cause a panic for testing spew properly
  49. // handles them
  50. type panicer int
  51. func (p panicer) String() string {
  52. panic("test panic")
  53. }
  54. // spewFunc is used to identify which public function of the spew package or
  55. // ConfigState a test applies to.
  56. type spewFunc int
  57. const (
  58. fCSFdump spewFunc = iota
  59. fCSFprint
  60. fCSFprintf
  61. fCSFprintln
  62. fCSPrint
  63. fCSPrintln
  64. fCSErrorf
  65. fCSNewFormatter
  66. fErrorf
  67. fFprint
  68. fFprintln
  69. fPrint
  70. fPrintln
  71. )
  72. // Map of spewFunc values to names for pretty printing.
  73. var spewFuncStrings = map[spewFunc]string{
  74. fCSFdump: "ConfigState.Fdump",
  75. fCSFprint: "ConfigState.Fprint",
  76. fCSFprintf: "ConfigState.Fprintf",
  77. fCSFprintln: "ConfigState.Fprintln",
  78. fCSPrint: "ConfigState.Print",
  79. fCSPrintln: "ConfigState.Println",
  80. fCSErrorf: "ConfigState.Errorf",
  81. fCSNewFormatter: "ConfigState.NewFormatter",
  82. fErrorf: "spew.Errorf",
  83. fFprint: "spew.Fprint",
  84. fFprintln: "spew.Fprintln",
  85. fPrint: "spew.Print",
  86. fPrintln: "spew.Println",
  87. }
  88. func (f spewFunc) String() string {
  89. if s, ok := spewFuncStrings[f]; ok {
  90. return s
  91. }
  92. return fmt.Sprintf("Unknown spewFunc (%d)", int(f))
  93. }
  94. // spewTest is used to describe a test to be performed against the public
  95. // functions of the spew package or ConfigState.
  96. type spewTest struct {
  97. f spewFunc
  98. format string
  99. in interface{}
  100. want string
  101. }
  102. // spewTests houses the tests to be performed against the public functions of
  103. // the spew package and ConfigState.
  104. //
  105. // These tests are only intended to ensure the public functions are exercised
  106. // and are intentionally not exhaustive of types. The exhaustive type
  107. // tests are handled in the dump and format tests.
  108. var spewTests = []spewTest{
  109. {fCSFdump, "", int8(127), "(int8) 127\n"},
  110. {fCSFprint, "", int16(32767), "32767"},
  111. {fCSFprintf, "%v", int32(2147483647), "2147483647"},
  112. {fCSFprintln, "", int(2147483647), "2147483647\n"},
  113. {fCSPrint, "", int64(9223372036854775807), "9223372036854775807"},
  114. {fCSPrintln, "", uint8(255), "255\n"},
  115. {fCSErrorf, "%#v", uint16(65535), "(uint16)65535"},
  116. {fCSNewFormatter, "%v", uint32(4294967295), "4294967295"},
  117. {fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"},
  118. {fFprint, "", float32(3.14), "3.14"},
  119. {fFprintln, "", float64(6.28), "6.28\n"},
  120. {fPrint, "", true, "true"},
  121. {fPrintln, "", false, "false\n"},
  122. }
  123. // redirStdout is a helper function to return the standard output from f as a
  124. // byte slice.
  125. func redirStdout(f func()) ([]byte, error) {
  126. tempFile, err := ioutil.TempFile("", "ss-test")
  127. if err != nil {
  128. return nil, err
  129. }
  130. fileName := tempFile.Name()
  131. defer os.Remove(fileName) // Ignore error
  132. origStdout := os.Stdout
  133. os.Stdout = tempFile
  134. f()
  135. os.Stdout = origStdout
  136. tempFile.Close()
  137. return ioutil.ReadFile(fileName)
  138. }
  139. // TestSpew executes all of the tests described by spewTests.
  140. func TestSpew(t *testing.T) {
  141. scs := spew.NewDefaultConfig()
  142. t.Logf("Running %d tests", len(spewTests))
  143. for i, test := range spewTests {
  144. buf := new(bytes.Buffer)
  145. switch test.f {
  146. case fCSFdump:
  147. scs.Fdump(buf, test.in)
  148. case fCSFprint:
  149. scs.Fprint(buf, test.in)
  150. case fCSFprintf:
  151. scs.Fprintf(buf, test.format, test.in)
  152. case fCSFprintln:
  153. scs.Fprintln(buf, test.in)
  154. case fCSPrint:
  155. b, err := redirStdout(func() { scs.Print(test.in) })
  156. if err != nil {
  157. t.Errorf("%v #%d %v", test.f, i, err)
  158. continue
  159. }
  160. buf.Write(b)
  161. case fCSPrintln:
  162. b, err := redirStdout(func() { scs.Println(test.in) })
  163. if err != nil {
  164. t.Errorf("%v #%d %v", test.f, i, err)
  165. continue
  166. }
  167. buf.Write(b)
  168. case fCSErrorf:
  169. err := scs.Errorf(test.format, test.in)
  170. buf.WriteString(err.Error())
  171. case fCSNewFormatter:
  172. fmt.Fprintf(buf, test.format, scs.NewFormatter(test.in))
  173. case fErrorf:
  174. err := spew.Errorf(test.format, test.in)
  175. buf.WriteString(err.Error())
  176. case fFprint:
  177. spew.Fprint(buf, test.in)
  178. case fFprintln:
  179. spew.Fprintln(buf, test.in)
  180. case fPrint:
  181. b, err := redirStdout(func() { spew.Print(test.in) })
  182. if err != nil {
  183. t.Errorf("%v #%d %v", test.f, i, err)
  184. continue
  185. }
  186. buf.Write(b)
  187. case fPrintln:
  188. b, err := redirStdout(func() { spew.Println(test.in) })
  189. if err != nil {
  190. t.Errorf("%v #%d %v", test.f, i, err)
  191. continue
  192. }
  193. buf.Write(b)
  194. default:
  195. t.Errorf("%v #%d unrecognized function", test.f, i)
  196. continue
  197. }
  198. s := buf.String()
  199. if test.want != s {
  200. t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want)
  201. continue
  202. }
  203. }
  204. }