common_test.go 7.7 KB

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