2 * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
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.
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.
24 "github.com/davecgh/go-spew/spew"
27 // custom type to test Stinger interface on non-pointer receiver.
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)
36 // custom type to test Stinger interface on pointer receiver.
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)
45 // xref1 and xref2 are cross referencing structs for testing circular reference
54 // indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
55 // reference for testing detection.
56 type indirCir1 struct {
59 type indirCir2 struct {
62 type indirCir3 struct {
66 // embed is used to test embedded structures.
71 // embedwrap is used to test embedded structures.
72 type embedwrap struct {
77 // panicer is used to intentionally cause a panic for testing spew properly
81 func (p panicer) String() string {
85 // customError is used to test custom error interface invocation.
88 func (e customError) Error() string {
89 return fmt.Sprintf("error: %d", int(e))
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 {
96 for i, want := range wants {
98 s += fmt.Sprintf("want%d: %s", i+1, want)
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 {
117 type sortableStruct struct {
121 func (ss sortableStruct) String() string {
122 return fmt.Sprintf("ss.%d", ss.x)
125 type unsortableStruct struct {
129 type sortTestCase struct {
130 input []reflect.Value
131 expected []reflect.Value
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())
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{}
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)
157 // TestSortValues ensures the sort functionality for relect.Value based sorting
158 // works as intended.
159 func TestSortValues(t *testing.T) {
165 embedA := v(embed{"a"})
166 embedB := v(embed{"b"})
167 embedC := v(embed{"c"})
168 tests := []sortTestCase{
176 []reflect.Value{v(false), v(true), v(false)},
177 []reflect.Value{v(false), v(false), v(true)},
181 []reflect.Value{v(2), v(1), v(3)},
182 []reflect.Value{v(1), v(2), v(3)},
186 []reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))},
187 []reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))},
191 []reflect.Value{v(2.0), v(1.0), v(3.0)},
192 []reflect.Value{v(1.0), v(2.0), v(3.0)},
196 []reflect.Value{b, a, c},
197 []reflect.Value{a, b, c},
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})},
206 []reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))},
207 []reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))},
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})},
215 // UnsortableStructs.
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})},
223 []reflect.Value{embedB, embedA, embedC},
224 []reflect.Value{embedB, embedA, embedC},
227 cs := spew.ConfigState{DisableMethods: true, SpewKeys: false}
228 helpTestSortValues(tests, &cs, t)
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) {
239 tests := []sortTestCase{
242 []reflect.Value{v(2), v(1), v(3)},
243 []reflect.Value{v(1), v(2), v(3)},
247 []reflect.Value{b, a, c},
248 []reflect.Value{a, b, c},
252 []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
253 []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
255 // UnsortableStructs.
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})},
262 cs := spew.ConfigState{DisableMethods: false, SpewKeys: false}
263 helpTestSortValues(tests, &cs, t)
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) {
274 tests := []sortTestCase{
277 []reflect.Value{v(2), v(1), v(3)},
278 []reflect.Value{v(1), v(2), v(3)},
282 []reflect.Value{b, a, c},
283 []reflect.Value{a, b, c},
287 []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
288 []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
290 // UnsortableStructs.
292 []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
293 []reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})},
296 cs := spew.ConfigState{DisableMethods: true, SpewKeys: true}
297 helpTestSortValues(tests, &cs, t)