formatter_test.go 5.0 KB

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