blob: eebf63ea02e6a41ced1418cc30b04def08fd8407 [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001package reflectutil
2
3import (
4 "reflect"
5 "testing"
6 "unsafe"
7)
8
9type (
10 Struct struct {
11 A uint
12 B string
13 }
14
15 Recurse struct {
16 U uint
17 R *Recurse
18 }
19
20 RecurseA struct {
21 Ua uint
22 B *RecurseB
23 }
24 RecurseB struct {
25 Ub uint
26 A *RecurseA
27 }
28
29 abIntPtr struct {
30 A, B *int
31 }
32)
33
34var (
35 recurseCycle *Recurse = &Recurse{}
36 recurseABCycle *RecurseA = &RecurseA{}
37
38 intPtr1a *int = new(int)
39 intPtr1b *int = new(int)
40
41 iface interface{}
42)
43
44func init() {
45 recurseCycle.U = 5
46 recurseCycle.R = recurseCycle
47
48 recurseABCycle.Ua = 5
49 recurseABCycle.B = &RecurseB{6, recurseABCycle}
50
51 *intPtr1a = 1
52 *intPtr1b = 1
53}
54
Benjamin Prosnitz235346e2015-02-13 10:55:55 -080055func TestDeepEqual(t *testing.T) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070056 tests := []struct {
57 a, b interface{}
58 expect bool
59 }{
60 {true, true, true},
61 {1, 1, true},
62 {-1, -1, true},
63 {1.1, 1.1, true},
64 {"abc", "abc", true},
65 {1 + 1i, 1 + 1i, true},
66 {[2]uint{1, 1}, [2]uint{1, 1}, true},
67 {[]uint{1, 1}, []uint{1, 1}, true},
68 {map[uint]string{1: "1", 2: "2"}, map[uint]string{1: "1", 2: "2"}, true},
69 {Struct{1, "a"}, Struct{1, "a"}, true},
70 {recurseCycle, recurseCycle, true},
71 {recurseABCycle, recurseABCycle, true},
72 {abIntPtr{intPtr1a, intPtr1a}, abIntPtr{intPtr1a, intPtr1a}, true},
73 {abIntPtr{intPtr1a, intPtr1b}, abIntPtr{intPtr1a, intPtr1b}, true},
74
75 {true, false, false},
76 {1, 2, false},
77 {-1, -2, false},
78 {1.1, 2.2, false},
79 {"abc", "def", false},
80 {1 + 1i, 2 + 2i, false},
81 {[2]uint{1, 1}, [2]uint{2, 2}, false},
82 {[]uint{1, 1}, []uint{2, 2}, false},
83 {map[uint]string{1: "1", 2: "2"}, map[uint]string{3: "3", 4: "4"}, false},
84 {Struct{1, "a"}, Struct{1, "b"}, false},
85 {recurseCycle, &Recurse{5, &Recurse{5, nil}}, false},
86 {recurseABCycle, &RecurseA{5, &RecurseB{6, nil}}, false},
87 {abIntPtr{intPtr1a, intPtr1a}, abIntPtr{intPtr1a, intPtr1b}, false},
88 {abIntPtr{intPtr1a, intPtr1b}, abIntPtr{intPtr1a, intPtr1a}, false},
89 }
90 for _, test := range tests {
Benjamin Prosnitz235346e2015-02-13 10:55:55 -080091 actual := DeepEqual(test.a, test.b, &DeepEqualOpts{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -070092 if actual != test.expect {
Benjamin Prosnitz235346e2015-02-13 10:55:55 -080093 t.Errorf("DeepEqual(%#v, %#v) != %v", test.a, test.b, test.expect)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070094 }
95 }
96}
97
98func TestAreComparable(t *testing.T) {
99 tests := []struct {
100 a, b interface{}
101 expect bool
102 }{
103 {true, true, true},
104 {"", "", true},
105 {uint(0), uint(0), true},
106 {uint8(0), uint8(0), true},
107 {uint16(0), uint16(0), true},
108 {uint32(0), uint32(0), true},
109 {uint64(0), uint64(0), true},
110 {uintptr(0), uintptr(0), true},
111 {int(0), int(0), true},
112 {int8(0), int8(0), true},
113 {int16(0), int16(0), true},
114 {int32(0), int32(0), true},
115 {int64(0), int64(0), true},
116 {float32(0), float32(0), true},
117 {float64(0), float64(0), true},
118 {complex64(0), complex64(0), true},
119 {complex128(0), complex128(0), true},
120 {[2]uint{1, 1}, [2]uint{1, 1}, true},
121 {[]uint{1, 1}, []uint{1, 1}, true},
122 {Struct{1, "a"}, Struct{1, "a"}, true},
123 {(*int)(nil), (*int)(nil), true},
124 {recurseCycle, recurseCycle, true},
125 {recurseABCycle, recurseABCycle, true},
126 {abIntPtr{intPtr1a, intPtr1a}, abIntPtr{intPtr1a, intPtr1a}, true},
127 {abIntPtr{intPtr1a, intPtr1b}, abIntPtr{intPtr1a, intPtr1b}, true},
128
129 {map[uint]string{1: "1"}, map[uint]string{1: "1"}, false},
130 {&iface, &iface, false},
131 {make(chan int), make(chan int), false},
132 {TestAreComparable, TestAreComparable, false},
133 {unsafe.Pointer(nil), unsafe.Pointer(nil), false},
134 }
135 for _, test := range tests {
136 actual := AreComparable(test.a, test.b)
137 if actual != test.expect {
138 t.Errorf("AreComparable(%#v, %#v) != %v", test.a, test.b, test.expect)
139 }
140 }
141}
142
143func TestLess(t *testing.T) {
144 for _, test := range compareTests {
145 actual := Less(test.a, test.b)
146 expect := false
147 if test.expect == -1 {
148 expect = true // For eq and gt we expect Less to return false.
149 }
150 if actual != expect {
151 t.Errorf("Less(%#v, %#v) != %v", test.a, test.b, expect)
152 }
153 }
154}
155
156func TestCompare(t *testing.T) {
157 for _, test := range compareTests {
158 actual := Compare(test.a, test.b)
159 if actual != test.expect {
160 t.Errorf("Compare(%#v, %#v) != %v", test.a, test.b, test.expect)
161 }
162 }
163}
164
165var compareTests = []struct {
166 a, b interface{}
167 expect int
168}{
169 {false, true, -1},
170 {false, false, 0},
171 {true, false, +1},
172 {true, true, 0},
173
174 {"", "aa", -1},
175 {"a", "aa", -1},
176 {"aa", "ab", -1},
177 {"aa", "b", -1},
178 {"", "", 0},
179 {"aa", "", +1},
180 {"aa", "a", +1},
181 {"ab", "aa", +1},
182 {"b", "aa", +1},
183
184 {uint(0), uint(1), -1},
185 {uint(0), uint(0), 0},
186 {uint(1), uint(0), +1},
187 {uint(1), uint(1), 0},
188
189 {int(-1), int(+1), -1},
190 {int(-1), int(-1), 0},
191 {int(+1), int(-1), +1},
192 {int(+1), int(+1), 0},
193
194 {float32(-1.1), float32(+1.1), -1},
195 {float32(-1.1), float32(-1.1), 0},
196 {float32(+1.1), float32(-1.1), +1},
197 {float32(+1.1), float32(+1.1), 0},
198
199 {complex64(1 + 1i), complex64(1 + 2i), -1},
200 {complex64(1 + 2i), complex64(2 + 1i), -1},
201 {complex64(1 + 2i), complex64(2 + 2i), -1},
202 {complex64(1 + 2i), complex64(2 + 3i), -1},
203 {complex64(1 + 1i), complex64(1 + 1i), 0},
204 {complex64(1 + 2i), complex64(1 + 1i), +1},
205 {complex64(2 + 1i), complex64(1 + 2i), +1},
206 {complex64(2 + 2i), complex64(1 + 2i), +1},
207 {complex64(2 + 3i), complex64(1 + 2i), +1},
208
209 {[2]int{1, 1}, [2]int{1, 2}, -1},
210 {[2]int{1, 2}, [2]int{2, 1}, -1},
211 {[2]int{1, 2}, [2]int{2, 2}, -1},
212 {[2]int{1, 2}, [2]int{2, 3}, -1},
213 {[2]int{1, 1}, [2]int{1, 1}, 0},
214 {[2]int{1, 2}, [2]int{1, 1}, +1},
215 {[2]int{2, 1}, [2]int{1, 2}, +1},
216 {[2]int{2, 2}, [2]int{1, 2}, +1},
217 {[2]int{2, 3}, [2]int{1, 2}, +1},
218
219 {[]int{}, []int{1, 1}, -1},
220 {[]int{1}, []int{1, 1}, -1},
221 {[]int{1, 1}, []int{}, +1},
222 {[]int{1, 1}, []int{1}, +1},
223 {[]int{1, 1}, []int{1, 2}, -1},
224 {[]int{1, 2}, []int{2, 1}, -1},
225 {[]int{1, 2}, []int{2, 2}, -1},
226 {[]int{1, 2}, []int{2, 3}, -1},
227 {[]int{1, 1}, []int{1, 1}, 0},
228 {[]int{1, 2}, []int{1, 1}, +1},
229 {[]int{2, 1}, []int{1, 2}, +1},
230 {[]int{2, 2}, []int{1, 2}, +1},
231 {[]int{2, 3}, []int{1, 2}, +1},
232
233 {Struct{1, "a"}, Struct{1, "b"}, -1},
234 {Struct{1, "b"}, Struct{2, "a"}, -1},
235 {Struct{1, "b"}, Struct{2, "b"}, -1},
236 {Struct{1, "b"}, Struct{2, "c"}, -1},
237 {Struct{1, "a"}, Struct{1, "a"}, 0},
238 {Struct{1, "b"}, Struct{1, "a"}, +1},
239 {Struct{2, "a"}, Struct{1, "b"}, +1},
240 {Struct{2, "b"}, Struct{1, "b"}, +1},
241 {Struct{2, "c"}, Struct{1, "b"}, +1},
242
243 {(*Struct)(nil), &Struct{1, "a"}, -1},
244 {&Struct{1, "a"}, &Struct{1, "b"}, -1},
245 {&Struct{1, "b"}, &Struct{2, "a"}, -1},
246 {&Struct{1, "b"}, &Struct{2, "b"}, -1},
247 {&Struct{1, "b"}, &Struct{2, "c"}, -1},
248 {(*Struct)(nil), (*Struct)(nil), 0},
249 {&Struct{1, "a"}, (*Struct)(nil), +1},
250 {&Struct{1, "a"}, &Struct{1, "a"}, 0},
251 {&Struct{1, "b"}, &Struct{1, "a"}, +1},
252 {&Struct{2, "a"}, &Struct{1, "b"}, +1},
253 {&Struct{2, "b"}, &Struct{1, "b"}, +1},
254 {&Struct{2, "c"}, &Struct{1, "b"}, +1},
255}
256
257type v []interface{}
258
259func toRVS(values v) (rvs []reflect.Value) {
260 for _, val := range values {
261 rvs = append(rvs, reflect.ValueOf(val))
262 }
263 return
264}
265
266func fromRVS(rvs []reflect.Value) (values v) {
267 for _, rv := range rvs {
268 values = append(values, rv.Interface())
269 }
270 return
271}
272
273func TestTrySortValues(t *testing.T) {
274 tests := []struct {
275 values v
276 expect v
277 }{
278 {
279 v{true, false},
280 v{false, true},
281 },
282 {
283 v{"c", "b", "a"},
284 v{"a", "b", "c"},
285 },
286 {
287 v{3, 1, 2},
288 v{1, 2, 3},
289 },
290 {
291 v{3.3, 1.1, 2.2},
292 v{1.1, 2.2, 3.3},
293 },
294 {
295 v{3 + 3i, 1 + 1i, 2 + 2i},
296 v{1 + 1i, 2 + 2i, 3 + 3i},
297 },
298 {
299 v{[1]int{3}, [1]int{1}, [1]int{2}},
300 v{[1]int{1}, [1]int{2}, [1]int{3}},
301 },
302 {
303 v{[]int{3}, []int{}, []int{2, 2}},
304 v{[]int{}, []int{2, 2}, []int{3}},
305 },
306 {
307 v{Struct{3, "c"}, Struct{1, "a"}, Struct{2, "b"}},
308 v{Struct{1, "a"}, Struct{2, "b"}, Struct{3, "c"}},
309 },
310 {
311 v{&Struct{3, "c"}, (*Struct)(nil), &Struct{2, "b"}},
312 v{(*Struct)(nil), &Struct{2, "b"}, &Struct{3, "c"}},
313 },
314 }
315 for _, test := range tests {
316 actual := fromRVS(TrySortValues(toRVS(test.values)))
317 if !reflect.DeepEqual(actual, test.expect) {
318 t.Errorf("TrySortValues(%v) got %v, want %v", test.values, actual, test.expect)
319 }
320 }
321}
Benjamin Prosnitz235346e2015-02-13 10:55:55 -0800322
323func TestOptionSliceEqNilEmpty(t *testing.T) {
324 tests := []struct {
325 first interface{}
326 second interface{}
327 resultWithoutOption bool
328 resultWithOption bool
329 }{
330 {
331 []int{}, []int{}, true, true,
332 },
333 {
334 []int(nil), []int(nil), true, true,
335 },
336 {
337 []int{}, []int(nil), false, true,
338 },
339 {
340 []([]int){([]int)(nil)}, []([]int){[]int{}}, false, true,
341 },
342 }
343
344 for _, nilEqOpt := range []bool{true, false} {
345 for _, test := range tests {
346 options := &DeepEqualOpts{
347 SliceEqNilEmpty: nilEqOpt,
348 }
349
350 result := DeepEqual(test.first, test.second, options)
351
352 if nilEqOpt {
353 if result != test.resultWithOption {
354 t.Errorf("Unexpected result with SliceEqNilEmpty option: inputs %#v and %#v. Got %v, expected: %v", test.first, test.second, result, test.resultWithOption)
355 }
356 } else {
357 if result != test.resultWithoutOption {
358 t.Errorf("Unexpected result without SliceEqNilEmpty option: inputs %#v and %#v. Got %v, expected: %v", test.first, test.second, result, test.resultWithoutOption)
359 }
360 }
361 }
362 }
363}