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