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 }