github.com/kr/pretty@v0.3.1/formatter_test.go (about) 1 package pretty 2 3 import ( 4 "fmt" 5 "io" 6 "strings" 7 "testing" 8 "time" 9 "unsafe" 10 ) 11 12 type test struct { 13 v interface{} 14 s string 15 } 16 17 type passtest struct { 18 v interface{} 19 f, s string 20 } 21 22 type LongStructTypeName struct { 23 longFieldName interface{} 24 otherLongFieldName interface{} 25 } 26 27 type SA struct { 28 t *T 29 v T 30 } 31 32 type T struct { 33 x, y int 34 } 35 36 type F int 37 38 func (f F) Format(s fmt.State, c rune) { 39 fmt.Fprintf(s, "F(%d)", int(f)) 40 } 41 42 type Stringer struct{ i int } 43 44 func (s *Stringer) String() string { return "foo" } 45 46 var long = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 47 48 var passthrough = []passtest{ 49 {1, "%d", "1"}, 50 {"a", "%s", "a"}, 51 {&Stringer{}, "%s", "foo"}, 52 } 53 54 func TestPassthrough(t *testing.T) { 55 for _, tt := range passthrough { 56 s := fmt.Sprintf(tt.f, Formatter(tt.v)) 57 if tt.s != s { 58 t.Errorf("expected %q", tt.s) 59 t.Errorf("got %q", s) 60 t.Errorf("expraw\n%s", tt.s) 61 t.Errorf("gotraw\n%s", s) 62 } 63 } 64 } 65 66 type StructWithPrivateFields struct { 67 A string 68 b string 69 } 70 71 func NewStructWithPrivateFields(a string) StructWithPrivateFields { 72 return StructWithPrivateFields{a, "fixedb"} 73 } 74 75 func (s StructWithPrivateFields) GoString() string { 76 return fmt.Sprintf("NewStructWithPrivateFields(%q)", s.A) 77 } 78 79 var gosyntax = []test{ 80 {nil, `nil`}, 81 {"", `""`}, 82 {"a", `"a"`}, 83 {1, "int(1)"}, 84 {1.0, "float64(1)"}, 85 {[]int(nil), "[]int(nil)"}, 86 {[0]int{}, "[0]int{}"}, 87 {complex(1, 0), "(1+0i)"}, 88 //{make(chan int), "(chan int)(0x1234)"}, 89 {unsafe.Pointer(uintptr(unsafe.Pointer(&long))), fmt.Sprintf("unsafe.Pointer(0x%02x)", uintptr(unsafe.Pointer(&long)))}, 90 {func(int) {}, "func(int) {...}"}, 91 {map[string]string{"a": "a", "b": "b"}, "map[string]string{\"a\":\"a\", \"b\":\"b\"}"}, 92 {map[int]int{1: 1}, "map[int]int{1:1}"}, 93 {int32(1), "int32(1)"}, 94 {io.EOF, `&errors.errorString{s:"EOF"}`}, 95 {[]string{"a"}, `[]string{"a"}`}, 96 { 97 []string{long}, 98 `[]string{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"}`, 99 }, 100 {F(5), "pretty.F(5)"}, 101 {NewStructWithPrivateFields("foo"), `NewStructWithPrivateFields("foo")`}, 102 { 103 SA{&T{1, 2}, T{3, 4}}, 104 `pretty.SA{ 105 t: &pretty.T{x:1, y:2}, 106 v: pretty.T{x:3, y:4}, 107 }`, 108 }, 109 { 110 map[int][]byte{1: {}}, 111 `map[int][]uint8{ 112 1: {}, 113 }`, 114 }, 115 { 116 map[int]T{1: {}}, 117 `map[int]pretty.T{ 118 1: {}, 119 }`, 120 }, 121 { 122 long, 123 `"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"`, 124 }, 125 { 126 LongStructTypeName{ 127 longFieldName: LongStructTypeName{}, 128 otherLongFieldName: long, 129 }, 130 `pretty.LongStructTypeName{ 131 longFieldName: pretty.LongStructTypeName{}, 132 otherLongFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 133 }`, 134 }, 135 { 136 &LongStructTypeName{ 137 longFieldName: &LongStructTypeName{}, 138 otherLongFieldName: (*LongStructTypeName)(nil), 139 }, 140 `&pretty.LongStructTypeName{ 141 longFieldName: &pretty.LongStructTypeName{}, 142 otherLongFieldName: (*pretty.LongStructTypeName)(nil), 143 }`, 144 }, 145 { 146 []LongStructTypeName{ 147 {nil, nil}, 148 {3, 3}, 149 {long, nil}, 150 }, 151 `[]pretty.LongStructTypeName{ 152 {}, 153 { 154 longFieldName: int(3), 155 otherLongFieldName: int(3), 156 }, 157 { 158 longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 159 otherLongFieldName: nil, 160 }, 161 }`, 162 }, 163 { 164 []interface{}{ 165 LongStructTypeName{nil, nil}, 166 []byte{1, 2, 3}, 167 T{3, 4}, 168 LongStructTypeName{long, nil}, 169 }, 170 `[]interface {}{ 171 pretty.LongStructTypeName{}, 172 []uint8{0x1, 0x2, 0x3}, 173 pretty.T{x:3, y:4}, 174 pretty.LongStructTypeName{ 175 longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 176 otherLongFieldName: nil, 177 }, 178 }`, 179 }, 180 {(*time.Time)(nil), "(*time.Time)(nil)"}, 181 {&ValueGoString{"vgs"}, `VGS vgs`}, 182 {(*ValueGoString)(nil), `(*pretty.ValueGoString)(nil)`}, 183 {(*VGSWrapper)(nil), `(*pretty.VGSWrapper)(nil)`}, 184 {&PointerGoString{"pgs"}, `PGS pgs`}, 185 {(*PointerGoString)(nil), "(*pretty.PointerGoString)(nil)"}, 186 {&PanicGoString{"oops!"}, `(*pretty.PanicGoString)(PANIC=calling method "GoString": oops!)`}, 187 } 188 189 type ValueGoString struct { 190 s string 191 } 192 193 func (g ValueGoString) GoString() string { 194 return "VGS " + g.s 195 } 196 197 type VGSWrapper struct { 198 ValueGoString 199 } 200 201 type PointerGoString struct { 202 s string 203 } 204 205 func (g *PointerGoString) GoString() string { 206 return "PGS " + g.s 207 } 208 209 type PanicGoString struct { 210 s string 211 } 212 213 func (g *PanicGoString) GoString() string { 214 panic(g.s) 215 } 216 217 func TestGoSyntax(t *testing.T) { 218 for _, tt := range gosyntax { 219 s := fmt.Sprintf("%# v", Formatter(tt.v)) 220 if tt.s != s { 221 t.Errorf("expected %q", tt.s) 222 t.Errorf("got %q", s) 223 t.Errorf("expraw\n%s", tt.s) 224 t.Errorf("gotraw\n%s", s) 225 } 226 } 227 } 228 229 type I struct { 230 i int 231 R interface{} 232 } 233 234 func (i *I) I() *I { return i.R.(*I) } 235 236 func TestCycle(t *testing.T) { 237 type A struct{ *A } 238 v := &A{} 239 v.A = v 240 241 // panics from stack overflow without cycle detection 242 t.Logf("Example cycle:\n%# v", Formatter(v)) 243 244 p := &A{} 245 s := fmt.Sprintf("%# v", Formatter([]*A{p, p})) 246 if strings.Contains(s, "CYCLIC") { 247 t.Errorf("Repeated address detected as cyclic reference:\n%s", s) 248 } 249 250 type R struct { 251 i int 252 *R 253 } 254 r := &R{ 255 i: 1, 256 R: &R{ 257 i: 2, 258 R: &R{ 259 i: 3, 260 }, 261 }, 262 } 263 r.R.R.R = r 264 t.Logf("Example longer cycle:\n%# v", Formatter(r)) 265 266 r = &R{ 267 i: 1, 268 R: &R{ 269 i: 2, 270 R: &R{ 271 i: 3, 272 R: &R{ 273 i: 4, 274 R: &R{ 275 i: 5, 276 R: &R{ 277 i: 6, 278 R: &R{ 279 i: 7, 280 R: &R{ 281 i: 8, 282 R: &R{ 283 i: 9, 284 R: &R{ 285 i: 10, 286 R: &R{ 287 i: 11, 288 }, 289 }, 290 }, 291 }, 292 }, 293 }, 294 }, 295 }, 296 }, 297 }, 298 } 299 // here be pirates 300 r.R.R.R.R.R.R.R.R.R.R.R = r 301 t.Logf("Example very long cycle:\n%# v", Formatter(r)) 302 303 i := &I{ 304 i: 1, 305 R: &I{ 306 i: 2, 307 R: &I{ 308 i: 3, 309 R: &I{ 310 i: 4, 311 R: &I{ 312 i: 5, 313 R: &I{ 314 i: 6, 315 R: &I{ 316 i: 7, 317 R: &I{ 318 i: 8, 319 R: &I{ 320 i: 9, 321 R: &I{ 322 i: 10, 323 R: &I{ 324 i: 11, 325 }, 326 }, 327 }, 328 }, 329 }, 330 }, 331 }, 332 }, 333 }, 334 }, 335 } 336 iv := i.I().I().I().I().I().I().I().I().I().I() 337 *iv = *i 338 t.Logf("Example long interface cycle:\n%# v", Formatter(i)) 339 }