formatter_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. package pretty
  2. import (
  3. "fmt"
  4. "io"
  5. "strings"
  6. "testing"
  7. "unsafe"
  8. )
  9. type test struct {
  10. v interface{}
  11. s string
  12. }
  13. type LongStructTypeName struct {
  14. longFieldName interface{}
  15. otherLongFieldName interface{}
  16. }
  17. type SA struct {
  18. t *T
  19. v T
  20. }
  21. type T struct {
  22. x, y int
  23. }
  24. type F int
  25. func (f F) Format(s fmt.State, c rune) {
  26. fmt.Fprintf(s, "F(%d)", int(f))
  27. }
  28. var long = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  29. var gosyntax = []test{
  30. {nil, `nil`},
  31. {"", `""`},
  32. {"a", `"a"`},
  33. {1, "int(1)"},
  34. {1.0, "float64(1)"},
  35. {[]int(nil), "[]int(nil)"},
  36. {[0]int{}, "[0]int{}"},
  37. {complex(1, 0), "(1+0i)"},
  38. //{make(chan int), "(chan int)(0x1234)"},
  39. {unsafe.Pointer(uintptr(unsafe.Pointer(&long))), fmt.Sprintf("unsafe.Pointer(0x%02x)", uintptr(unsafe.Pointer(&long)))},
  40. {func(int) {}, "func(int) {...}"},
  41. {map[int]int{1: 1}, "map[int]int{1:1}"},
  42. {int32(1), "int32(1)"},
  43. {io.EOF, `&errors.errorString{s:"EOF"}`},
  44. {[]string{"a"}, `[]string{"a"}`},
  45. {
  46. []string{long},
  47. `[]string{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"}`,
  48. },
  49. {F(5), "pretty.F(5)"},
  50. {
  51. SA{&T{1, 2}, T{3, 4}},
  52. `pretty.SA{
  53. t: &pretty.T{x:1, y:2},
  54. v: pretty.T{x:3, y:4},
  55. }`,
  56. },
  57. {
  58. map[int][]byte{1: {}},
  59. `map[int][]uint8{
  60. 1: {},
  61. }`,
  62. },
  63. {
  64. map[int]T{1: {}},
  65. `map[int]pretty.T{
  66. 1: {},
  67. }`,
  68. },
  69. {
  70. long,
  71. `"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"`,
  72. },
  73. {
  74. LongStructTypeName{
  75. longFieldName: LongStructTypeName{},
  76. otherLongFieldName: long,
  77. },
  78. `pretty.LongStructTypeName{
  79. longFieldName: pretty.LongStructTypeName{},
  80. otherLongFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
  81. }`,
  82. },
  83. {
  84. &LongStructTypeName{
  85. longFieldName: &LongStructTypeName{},
  86. otherLongFieldName: (*LongStructTypeName)(nil),
  87. },
  88. `&pretty.LongStructTypeName{
  89. longFieldName: &pretty.LongStructTypeName{},
  90. otherLongFieldName: (*pretty.LongStructTypeName)(nil),
  91. }`,
  92. },
  93. {
  94. []LongStructTypeName{
  95. {nil, nil},
  96. {3, 3},
  97. {long, nil},
  98. },
  99. `[]pretty.LongStructTypeName{
  100. {},
  101. {
  102. longFieldName: int(3),
  103. otherLongFieldName: int(3),
  104. },
  105. {
  106. longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
  107. otherLongFieldName: nil,
  108. },
  109. }`,
  110. },
  111. {
  112. []interface{}{
  113. LongStructTypeName{nil, nil},
  114. []byte{1, 2, 3},
  115. T{3, 4},
  116. LongStructTypeName{long, nil},
  117. },
  118. `[]interface {}{
  119. pretty.LongStructTypeName{},
  120. []uint8{0x1, 0x2, 0x3},
  121. pretty.T{x:3, y:4},
  122. pretty.LongStructTypeName{
  123. longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
  124. otherLongFieldName: nil,
  125. },
  126. }`,
  127. },
  128. }
  129. func TestGoSyntax(t *testing.T) {
  130. for _, tt := range gosyntax {
  131. s := fmt.Sprintf("%# v", Formatter(tt.v))
  132. if tt.s != s {
  133. t.Errorf("expected %q", tt.s)
  134. t.Errorf("got %q", s)
  135. t.Errorf("expraw\n%s", tt.s)
  136. t.Errorf("gotraw\n%s", s)
  137. }
  138. }
  139. }
  140. type I struct {
  141. i int
  142. R interface{}
  143. }
  144. func (i *I) I() *I { return i.R.(*I) }
  145. func TestCycle(t *testing.T) {
  146. type A struct{ *A }
  147. v := &A{}
  148. v.A = v
  149. // panics from stack overflow without cycle detection
  150. t.Logf("Example cycle:\n%# v", Formatter(v))
  151. p := &A{}
  152. s := fmt.Sprintf("%# v", Formatter([]*A{p, p}))
  153. if strings.Contains(s, "CYCLIC") {
  154. t.Errorf("Repeated address detected as cyclic reference:\n%s", s)
  155. }
  156. type R struct {
  157. i int
  158. *R
  159. }
  160. r := &R{
  161. i: 1,
  162. R: &R{
  163. i: 2,
  164. R: &R{
  165. i: 3,
  166. },
  167. },
  168. }
  169. r.R.R.R = r
  170. t.Logf("Example longer cycle:\n%# v", Formatter(r))
  171. r = &R{
  172. i: 1,
  173. R: &R{
  174. i: 2,
  175. R: &R{
  176. i: 3,
  177. R: &R{
  178. i: 4,
  179. R: &R{
  180. i: 5,
  181. R: &R{
  182. i: 6,
  183. R: &R{
  184. i: 7,
  185. R: &R{
  186. i: 8,
  187. R: &R{
  188. i: 9,
  189. R: &R{
  190. i: 10,
  191. R: &R{
  192. i: 11,
  193. },
  194. },
  195. },
  196. },
  197. },
  198. },
  199. },
  200. },
  201. },
  202. },
  203. }
  204. // here be pirates
  205. r.R.R.R.R.R.R.R.R.R.R.R = r
  206. t.Logf("Example very long cycle:\n%# v", Formatter(r))
  207. i := &I{
  208. i: 1,
  209. R: &I{
  210. i: 2,
  211. R: &I{
  212. i: 3,
  213. R: &I{
  214. i: 4,
  215. R: &I{
  216. i: 5,
  217. R: &I{
  218. i: 6,
  219. R: &I{
  220. i: 7,
  221. R: &I{
  222. i: 8,
  223. R: &I{
  224. i: 9,
  225. R: &I{
  226. i: 10,
  227. R: &I{
  228. i: 11,
  229. },
  230. },
  231. },
  232. },
  233. },
  234. },
  235. },
  236. },
  237. },
  238. },
  239. }
  240. iv := i.I().I().I().I().I().I().I().I().I().I()
  241. *iv = *i
  242. t.Logf("Example long interface cycle:\n%# v", Formatter(i))
  243. }