github.com/dvln/pretty@v0.0.0-20161024040402-00a5f9316993/formatter_test.go (about)

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