github.com/kr/pretty@v0.3.1/diff_test.go (about)

     1  package pretty
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"reflect"
     8  	"testing"
     9  	"unsafe"
    10  )
    11  
    12  var (
    13  	_ Logfer   = (*testing.T)(nil)
    14  	_ Logfer   = (*testing.B)(nil)
    15  	_ Printfer = (*log.Logger)(nil)
    16  )
    17  
    18  type difftest struct {
    19  	a   interface{}
    20  	b   interface{}
    21  	exp []string
    22  }
    23  
    24  type S struct {
    25  	A int
    26  	S *S
    27  	I interface{}
    28  	C []int
    29  }
    30  
    31  type (
    32  	N struct{ N int }
    33  	E interface{}
    34  )
    35  
    36  var (
    37  	c0 = make(chan int)
    38  	c1 = make(chan int)
    39  	f0 = func() {}
    40  	f1 = func() {}
    41  	i0 = 0
    42  	i1 = 1
    43  )
    44  
    45  var diffs = []difftest{
    46  	{a: nil, b: nil},
    47  	{a: S{A: 1}, b: S{A: 1}},
    48  
    49  	{0, "", []string{`int != string`}},
    50  	{0, 1, []string{`0 != 1`}},
    51  	{S{}, new(S), []string{`pretty.S != *pretty.S`}},
    52  	{"a", "b", []string{`"a" != "b"`}},
    53  	{S{}, S{A: 1}, []string{`A: 0 != 1`}},
    54  	{new(S), &S{A: 1}, []string{`A: 0 != 1`}},
    55  	{S{S: new(S)}, S{S: &S{A: 1}}, []string{`S.A: 0 != 1`}},
    56  	{S{}, S{I: 0}, []string{`I: nil != int(0)`}},
    57  	{S{I: 1}, S{I: "x"}, []string{`I: int != string`}},
    58  	{S{}, S{C: []int{1}}, []string{`C: []int[0] != []int[1]`}},
    59  	{S{C: []int{}}, S{C: []int{1}}, []string{`C: []int[0] != []int[1]`}},
    60  	{S{C: []int{1, 2, 3}}, S{C: []int{1, 2, 4}}, []string{`C[2]: 3 != 4`}},
    61  	{S{}, S{A: 1, S: new(S)}, []string{`A: 0 != 1`, `S: nil != &pretty.S{}`}},
    62  
    63  	// unexported fields of every reflect.Kind (both equal and unequal)
    64  	{struct{ x bool }{false}, struct{ x bool }{false}, nil},
    65  	{struct{ x bool }{false}, struct{ x bool }{true}, []string{`x: false != true`}},
    66  	{struct{ x int }{0}, struct{ x int }{0}, nil},
    67  	{struct{ x int }{0}, struct{ x int }{1}, []string{`x: 0 != 1`}},
    68  	{struct{ x int8 }{0}, struct{ x int8 }{0}, nil},
    69  	{struct{ x int8 }{0}, struct{ x int8 }{1}, []string{`x: 0 != 1`}},
    70  	{struct{ x int16 }{0}, struct{ x int16 }{0}, nil},
    71  	{struct{ x int16 }{0}, struct{ x int16 }{1}, []string{`x: 0 != 1`}},
    72  	{struct{ x int32 }{0}, struct{ x int32 }{0}, nil},
    73  	{struct{ x int32 }{0}, struct{ x int32 }{1}, []string{`x: 0 != 1`}},
    74  	{struct{ x int64 }{0}, struct{ x int64 }{0}, nil},
    75  	{struct{ x int64 }{0}, struct{ x int64 }{1}, []string{`x: 0 != 1`}},
    76  	{struct{ x uint }{0}, struct{ x uint }{0}, nil},
    77  	{struct{ x uint }{0}, struct{ x uint }{1}, []string{`x: 0 != 1`}},
    78  	{struct{ x uint8 }{0}, struct{ x uint8 }{0}, nil},
    79  	{struct{ x uint8 }{0}, struct{ x uint8 }{1}, []string{`x: 0 != 1`}},
    80  	{struct{ x uint16 }{0}, struct{ x uint16 }{0}, nil},
    81  	{struct{ x uint16 }{0}, struct{ x uint16 }{1}, []string{`x: 0 != 1`}},
    82  	{struct{ x uint32 }{0}, struct{ x uint32 }{0}, nil},
    83  	{struct{ x uint32 }{0}, struct{ x uint32 }{1}, []string{`x: 0 != 1`}},
    84  	{struct{ x uint64 }{0}, struct{ x uint64 }{0}, nil},
    85  	{struct{ x uint64 }{0}, struct{ x uint64 }{1}, []string{`x: 0 != 1`}},
    86  	{struct{ x uintptr }{0}, struct{ x uintptr }{0}, nil},
    87  	{struct{ x uintptr }{0}, struct{ x uintptr }{1}, []string{`x: 0 != 1`}},
    88  	{struct{ x float32 }{0}, struct{ x float32 }{0}, nil},
    89  	{struct{ x float32 }{0}, struct{ x float32 }{1}, []string{`x: 0 != 1`}},
    90  	{struct{ x float64 }{0}, struct{ x float64 }{0}, nil},
    91  	{struct{ x float64 }{0}, struct{ x float64 }{1}, []string{`x: 0 != 1`}},
    92  	{struct{ x complex64 }{0}, struct{ x complex64 }{0}, nil},
    93  	{struct{ x complex64 }{0}, struct{ x complex64 }{1}, []string{`x: (0+0i) != (1+0i)`}},
    94  	{struct{ x complex128 }{0}, struct{ x complex128 }{0}, nil},
    95  	{struct{ x complex128 }{0}, struct{ x complex128 }{1}, []string{`x: (0+0i) != (1+0i)`}},
    96  	{struct{ x [1]int }{[1]int{0}}, struct{ x [1]int }{[1]int{0}}, nil},
    97  	{struct{ x [1]int }{[1]int{0}}, struct{ x [1]int }{[1]int{1}}, []string{`x[0]: 0 != 1`}},
    98  	{struct{ x chan int }{c0}, struct{ x chan int }{c0}, nil},
    99  	{struct{ x chan int }{c0}, struct{ x chan int }{c1}, []string{fmt.Sprintf("x: %p != %p", c0, c1)}},
   100  	{struct{ x func() }{f0}, struct{ x func() }{f0}, nil},
   101  	{struct{ x func() }{f0}, struct{ x func() }{f1}, []string{fmt.Sprintf("x: %p != %p", f0, f1)}},
   102  	{struct{ x interface{} }{0}, struct{ x interface{} }{0}, nil},
   103  	{struct{ x interface{} }{0}, struct{ x interface{} }{1}, []string{`x: 0 != 1`}},
   104  	{struct{ x interface{} }{0}, struct{ x interface{} }{""}, []string{`x: int != string`}},
   105  	{struct{ x interface{} }{0}, struct{ x interface{} }{nil}, []string{`x: int(0) != nil`}},
   106  	{struct{ x interface{} }{nil}, struct{ x interface{} }{0}, []string{`x: nil != int(0)`}},
   107  	{struct{ x map[int]int }{map[int]int{0: 0}}, struct{ x map[int]int }{map[int]int{0: 0}}, nil},
   108  	{struct{ x map[int]int }{map[int]int{0: 0}}, struct{ x map[int]int }{map[int]int{0: 1}}, []string{`x[0]: 0 != 1`}},
   109  	{struct{ x *int }{new(int)}, struct{ x *int }{new(int)}, nil},
   110  	{struct{ x *int }{&i0}, struct{ x *int }{&i1}, []string{`x: 0 != 1`}},
   111  	{struct{ x *int }{nil}, struct{ x *int }{&i0}, []string{`x: nil != &int(0)`}},
   112  	{struct{ x *int }{&i0}, struct{ x *int }{nil}, []string{`x: &int(0) != nil`}},
   113  	{struct{ x []int }{[]int{0}}, struct{ x []int }{[]int{0}}, nil},
   114  	{struct{ x []int }{[]int{0}}, struct{ x []int }{[]int{1}}, []string{`x[0]: 0 != 1`}},
   115  	{struct{ x string }{"a"}, struct{ x string }{"a"}, nil},
   116  	{struct{ x string }{"a"}, struct{ x string }{"b"}, []string{`x: "a" != "b"`}},
   117  	{struct{ x N }{N{0}}, struct{ x N }{N{0}}, nil},
   118  	{struct{ x N }{N{0}}, struct{ x N }{N{1}}, []string{`x.N: 0 != 1`}},
   119  	{
   120  		struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(0))},
   121  		struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(0))},
   122  		nil,
   123  	},
   124  	{
   125  		struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(0))},
   126  		struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(1))},
   127  		[]string{`x: 0x0 != 0x1`},
   128  	},
   129  }
   130  
   131  func TestDiff(t *testing.T) {
   132  	for _, tt := range diffs {
   133  		expectDiffOutput(t, tt.a, tt.b, tt.exp)
   134  	}
   135  }
   136  
   137  func expectDiffOutput(t *testing.T, a, b interface{}, exp []string) {
   138  	got := Diff(a, b)
   139  	eq := len(got) == len(exp)
   140  	if eq {
   141  		for i := range got {
   142  			eq = eq && got[i] == exp[i]
   143  		}
   144  	}
   145  	if !eq {
   146  		t.Errorf("diffing % #v", a)
   147  		t.Errorf("with    % #v", b)
   148  		diffdiff(t, got, exp)
   149  	}
   150  }
   151  
   152  func TestKeyEqual(t *testing.T) {
   153  	var emptyInterfaceZero interface{} = 0
   154  
   155  	cases := []interface{}{
   156  		new(bool),
   157  		new(int),
   158  		new(int8),
   159  		new(int16),
   160  		new(int32),
   161  		new(int64),
   162  		new(uint),
   163  		new(uint8),
   164  		new(uint16),
   165  		new(uint32),
   166  		new(uint64),
   167  		new(uintptr),
   168  		new(float32),
   169  		new(float64),
   170  		new(complex64),
   171  		new(complex128),
   172  		new([1]int),
   173  		new(chan int),
   174  		new(unsafe.Pointer),
   175  		new(interface{}),
   176  		&emptyInterfaceZero,
   177  		new(*int),
   178  		new(string),
   179  		new(struct{ int }),
   180  	}
   181  
   182  	for _, test := range cases {
   183  		rv := reflect.ValueOf(test).Elem()
   184  		if !keyEqual(rv, rv) {
   185  			t.Errorf("keyEqual(%s, %s) = false want true", rv.Type(), rv.Type())
   186  		}
   187  	}
   188  }
   189  
   190  func TestFdiff(t *testing.T) {
   191  	var buf bytes.Buffer
   192  	Fdiff(&buf, 0, 1)
   193  	want := "0 != 1\n"
   194  	if got := buf.String(); got != want {
   195  		t.Errorf("Fdiff(0, 1) = %q want %q", got, want)
   196  	}
   197  }
   198  
   199  func TestDiffCycle(t *testing.T) {
   200  	// Diff two cyclic structs
   201  	a := &I{i: 1, R: nil}
   202  	a.R = a
   203  	b := &I{i: 2, R: nil}
   204  	b.R = b
   205  	expectDiffOutput(t, a, b, []string{
   206  		`i: 1 != 2`,
   207  	})
   208  
   209  	// Diff two equal cyclic structs
   210  	b.i = 1
   211  	expectDiffOutput(t, a, b, []string{})
   212  
   213  	// Diff two structs with different cycles
   214  	b2 := &I{i: 1, R: b}
   215  	b.R = b2
   216  	expectDiffOutput(t, a, b, []string{`R: pretty.I{
   217      i:  1,
   218      R:  &pretty.I{(CYCLIC REFERENCE)},
   219  } (previously visited) != pretty.I{
   220      i:  1,
   221      R:  &pretty.I{
   222          i:  1,
   223          R:  &pretty.I{(CYCLIC REFERENCE)},
   224      },
   225  }`})
   226  
   227  	// ... and the same in the other direction
   228  	expectDiffOutput(t, b, a, []string{`R: pretty.I{
   229      i:  1,
   230      R:  &pretty.I{
   231          i:  1,
   232          R:  &pretty.I{(CYCLIC REFERENCE)},
   233      },
   234  } != pretty.I{
   235      i:  1,
   236      R:  &pretty.I{(CYCLIC REFERENCE)},
   237  } (previously visited)`})
   238  }
   239  
   240  func diffdiff(t *testing.T, got, exp []string) {
   241  	minus(t, "unexpected:", got, exp)
   242  	minus(t, "missing:", exp, got)
   243  }
   244  
   245  func minus(t *testing.T, s string, a, b []string) {
   246  	var i, j int
   247  	for i = 0; i < len(a); i++ {
   248  		for j = 0; j < len(b); j++ {
   249  			if a[i] == b[j] {
   250  				break
   251  			}
   252  		}
   253  		if j == len(b) {
   254  			t.Error(s, a[i])
   255  		}
   256  	}
   257  }