github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/test/go-spew/spew/common_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 "fmt" 21 "reflect" 22 "testing" 23 24 "github.com/davecgh/go-spew/spew" 25 ) 26 27 // custom type to test Stinger interface on non-pointer receiver. 28 type stringer string 29 30 // String implements the Stringer interface for testing invocation of custom 31 // stringers on types with non-pointer receivers. 32 func (s stringer) String() string { 33 return "stringer " + string(s) 34 } 35 36 // custom type to test Stinger interface on pointer receiver. 37 type pstringer string 38 39 // String implements the Stringer interface for testing invocation of custom 40 // stringers on types with only pointer receivers. 41 func (s *pstringer) String() string { 42 return "stringer " + string(*s) 43 } 44 45 // xref1 and xref2 are cross referencing structs for testing circular reference 46 // detection. 47 type xref1 struct { 48 ps2 *xref2 49 } 50 type xref2 struct { 51 ps1 *xref1 52 } 53 54 // indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular 55 // reference for testing detection. 56 type indirCir1 struct { 57 ps2 *indirCir2 58 } 59 type indirCir2 struct { 60 ps3 *indirCir3 61 } 62 type indirCir3 struct { 63 ps1 *indirCir1 64 } 65 66 // embed is used to test embedded structures. 67 type embed struct { 68 a string 69 } 70 71 // embedwrap is used to test embedded structures. 72 type embedwrap struct { 73 *embed 74 e *embed 75 } 76 77 // panicer is used to intentionally cause a panic for testing spew properly 78 // handles them 79 type panicer int 80 81 func (p panicer) String() string { 82 panic("test panic") 83 } 84 85 // customError is used to test custom error interface invocation. 86 type customError int 87 88 func (e customError) Error() string { 89 return fmt.Sprintf("error: %d", int(e)) 90 } 91 92 // stringizeWants converts a slice of wanted test output into a format suitable 93 // for a test error message. 94 func stringizeWants(wants []string) string { 95 s := "" 96 for i, want := range wants { 97 if i > 0 { 98 s += fmt.Sprintf("want%d: %s", i+1, want) 99 } else { 100 s += "want: " + want 101 } 102 } 103 return s 104 } 105 106 // testFailed returns whether or not a test failed by checking if the result 107 // of the test is in the slice of wanted strings. 108 func testFailed(result string, wants []string) bool { 109 for _, want := range wants { 110 if result == want { 111 return false 112 } 113 } 114 return true 115 } 116 117 type sortableStruct struct { 118 x int 119 } 120 121 func (ss sortableStruct) String() string { 122 return fmt.Sprintf("ss.%d", ss.x) 123 } 124 125 type unsortableStruct struct { 126 x int 127 } 128 129 type sortTestCase struct { 130 input []reflect.Value 131 expected []reflect.Value 132 } 133 134 func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) { 135 getInterfaces := func(values []reflect.Value) []interface{} { 136 interfaces := []interface{}{} 137 for _, v := range values { 138 interfaces = append(interfaces, v.Interface()) 139 } 140 return interfaces 141 } 142 143 for _, test := range tests { 144 spew.SortValues(test.input, cs) 145 // reflect.DeepEqual cannot really make sense of reflect.Value, 146 // probably because of all the pointer tricks. For instance, 147 // v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{} 148 // instead. 149 input := getInterfaces(test.input) 150 expected := getInterfaces(test.expected) 151 if !reflect.DeepEqual(input, expected) { 152 t.Errorf("Sort mismatch:\n %v != %v", input, expected) 153 } 154 } 155 } 156 157 // TestSortValues ensures the sort functionality for relect.Value based sorting 158 // works as intended. 159 func TestSortValues(t *testing.T) { 160 v := reflect.ValueOf 161 162 a := v("a") 163 b := v("b") 164 c := v("c") 165 embedA := v(embed{"a"}) 166 embedB := v(embed{"b"}) 167 embedC := v(embed{"c"}) 168 tests := []sortTestCase{ 169 // No values. 170 { 171 []reflect.Value{}, 172 []reflect.Value{}, 173 }, 174 // Bools. 175 { 176 []reflect.Value{v(false), v(true), v(false)}, 177 []reflect.Value{v(false), v(false), v(true)}, 178 }, 179 // Ints. 180 { 181 []reflect.Value{v(2), v(1), v(3)}, 182 []reflect.Value{v(1), v(2), v(3)}, 183 }, 184 // Uints. 185 { 186 []reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))}, 187 []reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))}, 188 }, 189 // Floats. 190 { 191 []reflect.Value{v(2.0), v(1.0), v(3.0)}, 192 []reflect.Value{v(1.0), v(2.0), v(3.0)}, 193 }, 194 // Strings. 195 { 196 []reflect.Value{b, a, c}, 197 []reflect.Value{a, b, c}, 198 }, 199 // Array 200 { 201 []reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})}, 202 []reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})}, 203 }, 204 // Uintptrs. 205 { 206 []reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))}, 207 []reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))}, 208 }, 209 // SortableStructs. 210 { 211 // Note: not sorted - DisableMethods is set. 212 []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, 213 []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, 214 }, 215 // UnsortableStructs. 216 { 217 // Note: not sorted - SpewKeys is false. 218 []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, 219 []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, 220 }, 221 // Invalid. 222 { 223 []reflect.Value{embedB, embedA, embedC}, 224 []reflect.Value{embedB, embedA, embedC}, 225 }, 226 } 227 cs := spew.ConfigState{DisableMethods: true, SpewKeys: false} 228 helpTestSortValues(tests, &cs, t) 229 } 230 231 // TestSortValuesWithMethods ensures the sort functionality for relect.Value 232 // based sorting works as intended when using string methods. 233 func TestSortValuesWithMethods(t *testing.T) { 234 v := reflect.ValueOf 235 236 a := v("a") 237 b := v("b") 238 c := v("c") 239 tests := []sortTestCase{ 240 // Ints. 241 { 242 []reflect.Value{v(2), v(1), v(3)}, 243 []reflect.Value{v(1), v(2), v(3)}, 244 }, 245 // Strings. 246 { 247 []reflect.Value{b, a, c}, 248 []reflect.Value{a, b, c}, 249 }, 250 // SortableStructs. 251 { 252 []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, 253 []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, 254 }, 255 // UnsortableStructs. 256 { 257 // Note: not sorted - SpewKeys is false. 258 []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, 259 []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, 260 }, 261 } 262 cs := spew.ConfigState{DisableMethods: false, SpewKeys: false} 263 helpTestSortValues(tests, &cs, t) 264 } 265 266 // TestSortValuesWithSpew ensures the sort functionality for relect.Value 267 // based sorting works as intended when using spew to stringify keys. 268 func TestSortValuesWithSpew(t *testing.T) { 269 v := reflect.ValueOf 270 271 a := v("a") 272 b := v("b") 273 c := v("c") 274 tests := []sortTestCase{ 275 // Ints. 276 { 277 []reflect.Value{v(2), v(1), v(3)}, 278 []reflect.Value{v(1), v(2), v(3)}, 279 }, 280 // Strings. 281 { 282 []reflect.Value{b, a, c}, 283 []reflect.Value{a, b, c}, 284 }, 285 // SortableStructs. 286 { 287 []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, 288 []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, 289 }, 290 // UnsortableStructs. 291 { 292 []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, 293 []reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})}, 294 }, 295 } 296 cs := spew.ConfigState{DisableMethods: true, SpewKeys: true} 297 helpTestSortValues(tests, &cs, t) 298 }