1
2
3
4
5
6
7 package test_helpers
8
9 import (
10 "math"
11 "strings"
12 "testing"
13 )
14
15 type signed interface {
16 ~int | ~int8 | ~int16 | ~int32 | ~int64
17 }
18
19 type integer interface {
20 ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
21 }
22
23 type float interface {
24 ~float32 | ~float64
25 }
26
27 type number interface {
28 ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
29 }
30
31 func CheckSlices[T number](t *testing.T, got, want []T) bool {
32 t.Helper()
33 return CheckSlicesLogInput[T](t, got, want, 0.0, nil)
34 }
35
36 func isSameFloat(ia, ib any, flakiness float64) bool {
37 switch x := ia.(type) {
38 case float32:
39 y := ib.(float32)
40 if math.IsNaN(float64(x)) && math.IsNaN(float64(y)) {
41 return true
42 }
43 if flakiness > 0 {
44 if y == 0 {
45 if math.Abs(float64(x)) < flakiness {
46 return true
47 }
48 } else {
49 if math.Abs(float64((x-y)/y)) < flakiness {
50 return true
51 }
52 }
53 }
54 case float64:
55 y := ib.(float64)
56 if math.IsNaN(x) && math.IsNaN(y) {
57 return true
58 }
59 if flakiness > 0 {
60 if y == 0 {
61 if math.Abs(x) < flakiness {
62 return true
63 }
64 } else if math.Abs((x-y)/y) < flakiness {
65 return true
66 }
67 }
68
69 default:
70 }
71 return false
72 }
73
74 func isDifferentSignZero(ia, ib any) bool {
75 switch x := ia.(type) {
76 case float32:
77 y := ib.(float32)
78 if math.Float32bits(x) != math.Float32bits(y) {
79 return true
80 }
81 case float64:
82 y := ib.(float64)
83 if math.Float64bits(x) != math.Float64bits(y) {
84 return true
85 }
86 default:
87 }
88 return false
89 }
90
91
92
93
94
95 func CheckSlicesLogInput[T number](t *testing.T, got, want []T, flakiness float64, logInput func()) bool {
96 t.Helper()
97 var z T
98 for i := range want {
99 if got[i] != want[i] {
100 var ia any = got[i]
101 var ib any = want[i]
102 if isSameFloat(ia, ib, flakiness) {
103 continue
104 }
105
106 t.Logf("For %T vector elements:", z)
107 t.Logf("got =%v", got)
108 t.Logf("want=%v", want)
109 if logInput != nil {
110 logInput()
111 }
112 t.Errorf("at index %d, got=%v, want=%v", i, got[i], want[i])
113 return false
114 } else if got[i] == 0 {
115 var ia any = got[i]
116 var ib any = want[i]
117 if isDifferentSignZero(ia, ib) {
118 t.Logf("For %T vector elements:", z)
119 t.Logf("got =%v", got)
120 t.Logf("want=%v", want)
121 if logInput != nil {
122 logInput()
123 }
124 t.Errorf("at index %d, different signs of zero", i)
125 return false
126 }
127 }
128 }
129 return true
130 }
131
132
133
134
135
136
137
138 func CheckScalarsLogInput[T number](t *testing.T, got, want T, flakiness float64, logInput func()) bool {
139 t.Helper()
140 var z T
141 if got != want {
142 var ia any = got
143 var ib any = want
144 if isSameFloat(ia, ib, flakiness) {
145 return true
146 }
147
148 t.Logf("For %T scalar:", z)
149 t.Logf("got =%v", got)
150 t.Logf("want=%v", want)
151 if logInput != nil {
152 logInput()
153 }
154 t.Errorf("got=%v, want=%v", got, want)
155 return false
156
157 } else if got == 0 {
158 var ia any = got
159 var ib any = want
160 if isDifferentSignZero(ia, ib) {
161 t.Logf("For %T vector elements:", z)
162 t.Logf("got =%v", got)
163 t.Logf("want=%v", want)
164 if logInput != nil {
165 logInput()
166 }
167 t.Errorf("different signs of zero")
168 return false
169 }
170 }
171 return true
172 }
173
174
175
176
177
178
179
180 func CheckStringsLogInput(t *testing.T, got, want string, flakiness float64, logInput func()) bool {
181 t.Helper()
182 if got != want {
183 t.Logf("For string:")
184 t.Logf("got =%v", got)
185 t.Logf("want=%v", want)
186 if logInput != nil {
187 logInput()
188 }
189 t.Errorf("got=%v, want=%v", got, want)
190 return false
191 }
192 return true
193 }
194
195
196
197 func nOf[T any](n int, s []T) []T {
198 if len(s) >= n {
199 return s
200 }
201 r := make([]T, n)
202 for i := range r {
203 r[i] = s[i%len(s)]
204 }
205 return r
206 }
207
208 const (
209 PN22 = 1.0 / 1024 / 1024 / 4
210 PN24 = 1.0 / 1024 / 1024 / 16
211 PN53 = PN24 * PN24 / 32
212 F0 = float32(1.0 + 513*PN22/2)
213 F1 = float32(1.0 + 511*PN22*8)
214 Aeasy = float32(2046 * PN53)
215 Ahard = float32(2047 * PN53)
216 )
217
218 var zero = 0.0
219 var nzero = -zero
220 var inf = 1 / zero
221 var ninf = -1 / zero
222 var nan = math.NaN()
223 var snan32 = math.Float32frombits(0x7f800001)
224 var snan64 = math.Float64frombits(0x7ff0000000000001)
225
226
227 const N = 144
228
229 var float32s = nOf(N, []float32{float32(inf), float32(ninf), 1, float32(nan), snan32, -float32(nan), -snan32, float32(zero), 2, float32(nan), float32(zero), 3, float32(-zero), float32(1.0 / zero), float32(-1.0 / zero), 1.0 / 2, 1.0 / 4, 1.0 / 8, 1.0 / 1000, 1.0 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat32, 1 / math.MaxFloat32, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -160, -3200, -64, -4, -8, -16, -32, -64})
230 var float64s = nOf(N, []float64{inf, ninf, nan, snan64, -nan, -snan64, zero, -zero, 1 / zero, -1 / zero, 0.0001, 0.0000001, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1.0 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
231
232 var int32s = nOf(N, []int32{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
233 var uint32s = nOf(N, []uint32{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint32(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint32(0x55555), ^uint32(0x77777), ^uint32(0xccccc)})
234
235 var int64s = nOf(N, []int64{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
236 var uint64s = nOf(N, []uint64{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint64(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint64(0x55555), ^uint64(0x77777), ^uint64(0xccccc)})
237
238 var int16s = nOf(N, []int16{1, -1, 0, 2, 4, 8, 1024, 3, 5, 7, 11, 13, 3000, 5555, 7777, 11111, 32767, 32766, -32767, -32768, -11111, -4, -8, -16, -32, -64})
239 var uint16s = nOf(N, []uint16{1, 0, 2, 4, 8, 1024, 3, 5, 7, 11, 13, 3000, 5555, 7777, 11111, 32767, 32766, 32768, 65535, 45678, 56789})
240
241 var int8s = nOf(N, []int8{0, 1, 2, 3, 5, 7, 11, 22, 33, 55, 77, 121, 127, -1, -2, -3, -5, -7, -11, -77, -121, -127, -128, 4, 8, 16, 32, 64, -4, -8, -16, -32, -64})
242 var uint8s = nOf(N, []uint8{0, 1, 2, 3, 5, 7, 11, 22, 33, 55, 77, 121, 127, 128, 255, 233, 211, 177, 144, 4, 8, 16, 32, 64})
243
244 var bools = nOf(N, []bool{
245 true, false, true, true, false, false, true, true, true, false, false, false, true, true, true, true, false, false, false, false})
246
247 func Float64s() []float64 {
248 return float64s
249 }
250 func Int64s() []int64 {
251 return int64s
252 }
253 func Uint64s() []uint64 {
254 return uint64s
255 }
256
257 func Float32s() []float32 {
258 return float32s
259 }
260 func Int32s() []int32 {
261 return int32s
262 }
263 func Uint32s() []uint32 {
264 return uint32s
265 }
266
267 func Int16s() []int16 {
268 return int16s
269 }
270 func Uint16s() []uint16 {
271 return uint16s
272 }
273
274 func Int8s() []int8 {
275 return int8s
276 }
277 func Uint8s() []uint8 {
278 return uint8s
279 }
280 func Bools() []bool {
281 return bools
282 }
283
284 var s8s = [...]uint64{0, 1, 3, 7, 8, 9, 16, 9999999999}
285 var s16s = [...]uint64{0, 1, 3, 15, 16, 17, 32, 9999999999}
286 var s32s = [...]uint64{0, 1, 3, 31, 32, 33, 64, 9999999999}
287 var s64s = [...]uint64{0, 1, 3, 63, 64, 65, 128, 9999999999}
288
289 func Shift8s() []uint64 {
290 return s8s[:]
291 }
292 func Shift16s() []uint64 {
293 return s16s[:]
294 }
295 func Shift32s() []uint64 {
296 return s32s[:]
297 }
298 func Shift64s() []uint64 {
299 return s64s[:]
300 }
301
302
303
304 func ImpliedDo[T number](n int, val func(i int) T) []T {
305 s := make([]T, n)
306 for i := range s {
307 s[i] = val(i)
308 }
309 return s
310 }
311
312
313 func ImpliedBools(n int, val func(i int) bool) string {
314
315
316
317
318 var s strings.Builder
319 s.WriteString("{")
320 for i := range n {
321 if i > 0 {
322 s.WriteString(",")
323 }
324 if val(i) {
325 s.WriteString("1")
326 } else {
327 s.WriteString("0")
328 }
329 }
330 s.WriteString("}")
331 return s.String()
332 }
333
334 func forSlice[T number](t *testing.T, s []T, n int, f func(a []T) bool) {
335 t.Helper()
336 for i := 0; i < len(s)-n; i++ {
337 if !f(s[i : i+n]) {
338 return
339 }
340 }
341 }
342
343 func forSlicePair[T number](t *testing.T, s []T, n int, f func(a, b []T) bool) {
344 t.Helper()
345 for i := 0; i < len(s)-n; i++ {
346 for j := 0; j < len(s)-n; j++ {
347 if !f(s[i:i+n], s[j:j+n]) {
348 return
349 }
350 }
351 }
352 }
353
354 func forBoolSlice(t *testing.T, s []bool, n int, f func(a []bool) bool) {
355 t.Helper()
356 for i := 0; i < len(s)-n; i++ {
357 if !f(s[i : i+n]) {
358 return
359 }
360 }
361 }
362
363 func forBoolSlicePair(t *testing.T, s []bool, n int, f func(a, b []bool) bool) {
364 t.Helper()
365 for i := 0; i < len(s)-n; i++ {
366 for j := 0; j < len(s)-n; j++ {
367 if !f(s[i:i+n], s[j:j+n]) {
368 return
369 }
370 }
371 }
372 }
373
View as plain text