github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/test/go-spew/spew/spew_test.go (about) 1 /* 2 * Copyright (c) 2013-2016 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 17 package spew_test 18 19 import ( 20 "bytes" 21 "fmt" 22 "io/ioutil" 23 "os" 24 "testing" 25 26 "github.com/davecgh/go-spew/spew" 27 ) 28 29 // spewFunc is used to identify which public function of the spew package or 30 // ConfigState a test applies to. 31 type spewFunc int 32 33 const ( 34 fCSFdump spewFunc = iota 35 fCSFprint 36 fCSFprintf 37 fCSFprintln 38 fCSPrint 39 fCSPrintln 40 fCSSdump 41 fCSSprint 42 fCSSprintf 43 fCSSprintln 44 fCSErrorf 45 fCSNewFormatter 46 fErrorf 47 fFprint 48 fFprintln 49 fPrint 50 fPrintln 51 fSdump 52 fSprint 53 fSprintf 54 fSprintln 55 ) 56 57 // Map of spewFunc values to names for pretty printing. 58 var spewFuncStrings = map[spewFunc]string{ 59 fCSFdump: "ConfigState.Fdump", 60 fCSFprint: "ConfigState.Fprint", 61 fCSFprintf: "ConfigState.Fprintf", 62 fCSFprintln: "ConfigState.Fprintln", 63 fCSSdump: "ConfigState.Sdump", 64 fCSPrint: "ConfigState.Print", 65 fCSPrintln: "ConfigState.Println", 66 fCSSprint: "ConfigState.Sprint", 67 fCSSprintf: "ConfigState.Sprintf", 68 fCSSprintln: "ConfigState.Sprintln", 69 fCSErrorf: "ConfigState.Errorf", 70 fCSNewFormatter: "ConfigState.NewFormatter", 71 fErrorf: "spew.Errorf", 72 fFprint: "spew.Fprint", 73 fFprintln: "spew.Fprintln", 74 fPrint: "spew.Print", 75 fPrintln: "spew.Println", 76 fSdump: "spew.Sdump", 77 fSprint: "spew.Sprint", 78 fSprintf: "spew.Sprintf", 79 fSprintln: "spew.Sprintln", 80 } 81 82 func (f spewFunc) String() string { 83 if s, ok := spewFuncStrings[f]; ok { 84 return s 85 } 86 return fmt.Sprintf("Unknown spewFunc (%d)", int(f)) 87 } 88 89 // spewTest is used to describe a test to be performed against the public 90 // functions of the spew package or ConfigState. 91 type spewTest struct { 92 cs *spew.ConfigState 93 f spewFunc 94 format string 95 in interface{} 96 want string 97 } 98 99 // spewTests houses the tests to be performed against the public functions of 100 // the spew package and ConfigState. 101 // 102 // These tests are only intended to ensure the public functions are exercised 103 // and are intentionally not exhaustive of types. The exhaustive type 104 // tests are handled in the dump and format tests. 105 var spewTests []spewTest 106 107 // redirStdout is a helper function to return the standard output from f as a 108 // byte slice. 109 func redirStdout(f func()) ([]byte, error) { 110 tempFile, err := ioutil.TempFile("", "ss-test") 111 if err != nil { 112 return nil, err 113 } 114 fileName := tempFile.Name() 115 defer os.Remove(fileName) // Ignore error 116 117 origStdout := os.Stdout 118 os.Stdout = tempFile 119 f() 120 os.Stdout = origStdout 121 tempFile.Close() 122 123 return ioutil.ReadFile(fileName) 124 } 125 126 func initSpewTests() { 127 // Config states with various settings. 128 scsDefault := spew.NewDefaultConfig() 129 scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true} 130 scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true} 131 scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1} 132 scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true} 133 scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true} 134 scsNoCap := &spew.ConfigState{DisableCapacities: true} 135 136 // Variables for tests on types which implement Stringer interface with and 137 // without a pointer receiver. 138 ts := stringer("test") 139 tps := pstringer("test") 140 141 type ptrTester struct { 142 s *struct{} 143 } 144 tptr := &ptrTester{s: &struct{}{}} 145 146 // depthTester is used to test max depth handling for structs, array, slices 147 // and maps. 148 type depthTester struct { 149 ic indirCir1 150 arr [1]string 151 slice []string 152 m map[string]int 153 } 154 dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"}, 155 map[string]int{"one": 1}} 156 157 // Variable for tests on types which implement error interface. 158 te := customError(10) 159 160 spewTests = []spewTest{ 161 {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"}, 162 {scsDefault, fCSFprint, "", int16(32767), "32767"}, 163 {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"}, 164 {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"}, 165 {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, 166 {scsDefault, fCSPrintln, "", uint8(255), "255\n"}, 167 {scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"}, 168 {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"}, 169 {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"}, 170 {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"}, 171 {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, 172 {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, 173 {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, 174 {scsDefault, fFprint, "", float32(3.14), "3.14"}, 175 {scsDefault, fFprintln, "", float64(6.28), "6.28\n"}, 176 {scsDefault, fPrint, "", true, "true"}, 177 {scsDefault, fPrintln, "", false, "false\n"}, 178 {scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"}, 179 {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"}, 180 {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"}, 181 {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"}, 182 {scsNoMethods, fCSFprint, "", ts, "test"}, 183 {scsNoMethods, fCSFprint, "", &ts, "<*>test"}, 184 {scsNoMethods, fCSFprint, "", tps, "test"}, 185 {scsNoMethods, fCSFprint, "", &tps, "<*>test"}, 186 {scsNoPmethods, fCSFprint, "", ts, "stringer test"}, 187 {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"}, 188 {scsNoPmethods, fCSFprint, "", tps, "test"}, 189 {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"}, 190 {scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"}, 191 {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" + 192 " ic: (spew_test.indirCir1) {\n <max depth reached>\n },\n" + 193 " arr: ([1]string) (len=1 cap=1) {\n <max depth reached>\n },\n" + 194 " slice: ([]string) (len=1 cap=1) {\n <max depth reached>\n },\n" + 195 " m: (map[string]int) (len=1) {\n <max depth reached>\n }\n}\n"}, 196 {scsContinue, fCSFprint, "", ts, "(stringer test) test"}, 197 {scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " + 198 "(len=4) (stringer test) \"test\"\n"}, 199 {scsContinue, fCSFprint, "", te, "(error: 10) 10"}, 200 {scsContinue, fCSFdump, "", te, "(spew_test.customError) " + 201 "(error: 10) 10\n"}, 202 {scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"}, 203 {scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"}, 204 {scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"}, 205 {scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"}, 206 } 207 } 208 209 // TestSpew executes all of the tests described by spewTests. 210 func TestSpew(t *testing.T) { 211 initSpewTests() 212 213 t.Logf("Running %d tests", len(spewTests)) 214 for i, test := range spewTests { 215 buf := new(bytes.Buffer) 216 switch test.f { 217 case fCSFdump: 218 test.cs.Fdump(buf, test.in) 219 220 case fCSFprint: 221 test.cs.Fprint(buf, test.in) 222 223 case fCSFprintf: 224 test.cs.Fprintf(buf, test.format, test.in) 225 226 case fCSFprintln: 227 test.cs.Fprintln(buf, test.in) 228 229 case fCSPrint: 230 b, err := redirStdout(func() { test.cs.Print(test.in) }) 231 if err != nil { 232 t.Errorf("%v #%d %v", test.f, i, err) 233 continue 234 } 235 buf.Write(b) 236 237 case fCSPrintln: 238 b, err := redirStdout(func() { test.cs.Println(test.in) }) 239 if err != nil { 240 t.Errorf("%v #%d %v", test.f, i, err) 241 continue 242 } 243 buf.Write(b) 244 245 case fCSSdump: 246 str := test.cs.Sdump(test.in) 247 buf.WriteString(str) 248 249 case fCSSprint: 250 str := test.cs.Sprint(test.in) 251 buf.WriteString(str) 252 253 case fCSSprintf: 254 str := test.cs.Sprintf(test.format, test.in) 255 buf.WriteString(str) 256 257 case fCSSprintln: 258 str := test.cs.Sprintln(test.in) 259 buf.WriteString(str) 260 261 case fCSErrorf: 262 err := test.cs.Errorf(test.format, test.in) 263 buf.WriteString(err.Error()) 264 265 case fCSNewFormatter: 266 fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in)) 267 268 case fErrorf: 269 err := spew.Errorf(test.format, test.in) 270 buf.WriteString(err.Error()) 271 272 case fFprint: 273 spew.Fprint(buf, test.in) 274 275 case fFprintln: 276 spew.Fprintln(buf, test.in) 277 278 case fPrint: 279 b, err := redirStdout(func() { spew.Print(test.in) }) 280 if err != nil { 281 t.Errorf("%v #%d %v", test.f, i, err) 282 continue 283 } 284 buf.Write(b) 285 286 case fPrintln: 287 b, err := redirStdout(func() { spew.Println(test.in) }) 288 if err != nil { 289 t.Errorf("%v #%d %v", test.f, i, err) 290 continue 291 } 292 buf.Write(b) 293 294 case fSdump: 295 str := spew.Sdump(test.in) 296 buf.WriteString(str) 297 298 case fSprint: 299 str := spew.Sprint(test.in) 300 buf.WriteString(str) 301 302 case fSprintf: 303 str := spew.Sprintf(test.format, test.in) 304 buf.WriteString(str) 305 306 case fSprintln: 307 str := spew.Sprintln(test.in) 308 buf.WriteString(str) 309 310 default: 311 t.Errorf("%v #%d unrecognized function", test.f, i) 312 continue 313 } 314 s := buf.String() 315 if test.want != s { 316 t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want) 317 continue 318 } 319 } 320 }