github.com/seeker-insurance/kit@v0.0.13/pretty/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  type I struct {
   179  	i int
   180  	R interface{}
   181  }
   182  
   183  func (i *I) I() *I { return i.R.(*I) }
   184  
   185  func TestCycle(t *testing.T) {
   186  	type A struct{ *A }
   187  	v := &A{}
   188  	v.A = v
   189  
   190  	// panics from stack overflow without cycle detection
   191  	t.Logf("Example cycle:\n%# v", Formatter(v))
   192  
   193  	p := &A{}
   194  	s := fmt.Sprintf("%# v", Formatter([]*A{p, p}))
   195  	if strings.Contains(s, "CYCLIC") {
   196  		t.Errorf("Repeated address detected as cyclic reference:\n%s", s)
   197  	}
   198  
   199  	type R struct {
   200  		i int
   201  		*R
   202  	}
   203  	r := &R{
   204  		i: 1,
   205  		R: &R{
   206  			i: 2,
   207  			R: &R{
   208  				i: 3,
   209  			},
   210  		},
   211  	}
   212  	r.R.R.R = r
   213  	t.Logf("Example longer cycle:\n%# v", Formatter(r))
   214  
   215  	r = &R{
   216  		i: 1,
   217  		R: &R{
   218  			i: 2,
   219  			R: &R{
   220  				i: 3,
   221  				R: &R{
   222  					i: 4,
   223  					R: &R{
   224  						i: 5,
   225  						R: &R{
   226  							i: 6,
   227  							R: &R{
   228  								i: 7,
   229  								R: &R{
   230  									i: 8,
   231  									R: &R{
   232  										i: 9,
   233  										R: &R{
   234  											i: 10,
   235  											R: &R{
   236  												i: 11,
   237  											},
   238  										},
   239  									},
   240  								},
   241  							},
   242  						},
   243  					},
   244  				},
   245  			},
   246  		},
   247  	}
   248  	// here be pirates
   249  	r.R.R.R.R.R.R.R.R.R.R.R = r
   250  	t.Logf("Example very long cycle:\n%# v", Formatter(r))
   251  
   252  	i := &I{
   253  		i: 1,
   254  		R: &I{
   255  			i: 2,
   256  			R: &I{
   257  				i: 3,
   258  				R: &I{
   259  					i: 4,
   260  					R: &I{
   261  						i: 5,
   262  						R: &I{
   263  							i: 6,
   264  							R: &I{
   265  								i: 7,
   266  								R: &I{
   267  									i: 8,
   268  									R: &I{
   269  										i: 9,
   270  										R: &I{
   271  											i: 10,
   272  											R: &I{
   273  												i: 11,
   274  											},
   275  										},
   276  									},
   277  								},
   278  							},
   279  						},
   280  					},
   281  				},
   282  			},
   283  		},
   284  	}
   285  	iv := i.I().I().I().I().I().I().I().I().I().I()
   286  	*iv = *i
   287  	t.Logf("Example long interface cycle:\n%# v", Formatter(i))
   288  }