bpf: allow self-xor operation
[dpdk.git] / app / test / test_common.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <inttypes.h>
7 #include <string.h>
8 #include <math.h>
9 #include <rte_common.h>
10 #include <rte_hexdump.h>
11 #include <rte_pause.h>
12
13 #include "test.h"
14
15 #define MAX_NUM 1 << 20
16
17 #define FAIL(x)\
18         {printf(x "() test failed!\n");\
19         return -1;}
20
21 /* this is really a sanity check */
22 static int
23 test_macros(int __rte_unused unused_parm)
24 {
25 #define SMALLER 0x1000U
26 #define BIGGER 0x2000U
27 #define PTR_DIFF BIGGER - SMALLER
28 #define FAIL_MACRO(x)\
29         {printf(#x "() test failed!\n");\
30         return -1;}
31
32         uintptr_t unused = 0;
33         unsigned int smaller = SMALLER, bigger  = BIGGER;
34
35         RTE_SET_USED(unused);
36
37         RTE_SWAP(smaller, bigger);
38         if (smaller != BIGGER && bigger != SMALLER)
39                 FAIL_MACRO(RTE_SWAP);
40         if ((uintptr_t)RTE_PTR_ADD(SMALLER, PTR_DIFF) != BIGGER)
41                 FAIL_MACRO(RTE_PTR_ADD);
42         if ((uintptr_t)RTE_PTR_SUB(BIGGER, PTR_DIFF) != SMALLER)
43                 FAIL_MACRO(RTE_PTR_SUB);
44         if (RTE_PTR_DIFF(BIGGER, SMALLER) != PTR_DIFF)
45                 FAIL_MACRO(RTE_PTR_DIFF);
46         if (RTE_MAX(SMALLER, BIGGER) != BIGGER)
47                 FAIL_MACRO(RTE_MAX);
48         if (RTE_MIN(SMALLER, BIGGER) != SMALLER)
49                 FAIL_MACRO(RTE_MIN);
50
51         if (strncmp(RTE_STR(test), "test", sizeof("test")))
52                 FAIL_MACRO(RTE_STR);
53
54         return 0;
55 }
56
57 static int
58 test_bsf(void)
59 {
60         uint32_t shift, pos;
61
62         /* safe versions should be able to handle 0 */
63         if (rte_bsf32_safe(0, &pos) != 0)
64                 FAIL("rte_bsf32_safe");
65         if (rte_bsf64_safe(0, &pos) != 0)
66                 FAIL("rte_bsf64_safe");
67
68         for (shift = 0; shift < 63; shift++) {
69                 uint32_t val32;
70                 uint64_t val64;
71
72                 val64 = 1ULL << shift;
73                 if ((uint32_t)rte_bsf64(val64) != shift)
74                         FAIL("rte_bsf64");
75                 if (rte_bsf64_safe(val64, &pos) != 1)
76                         FAIL("rte_bsf64_safe");
77                 if (pos != shift)
78                         FAIL("rte_bsf64_safe");
79
80                 if (shift > 31)
81                         continue;
82
83                 val32 = 1U << shift;
84                 if ((uint32_t)rte_bsf32(val32) != shift)
85                         FAIL("rte_bsf32");
86                 if (rte_bsf32_safe(val32, &pos) != 1)
87                         FAIL("rte_bsf32_safe");
88                 if (pos != shift)
89                         FAIL("rte_bsf32_safe");
90         }
91
92         return 0;
93 }
94
95 static int
96 test_misc(void)
97 {
98         char memdump[] = "memdump_test";
99
100         rte_memdump(stdout, "test", memdump, sizeof(memdump));
101         rte_hexdump(stdout, "test", memdump, sizeof(memdump));
102
103         rte_pause();
104
105         return 0;
106 }
107
108 static int
109 test_align(void)
110 {
111 #define FAIL_ALIGN(x, i, p)\
112         {printf(x "() test failed: %u %u\n", i, p);\
113         return -1;}
114 #define FAIL_ALIGN64(x, j, q)\
115         {printf(x "() test failed: %"PRIu64" %"PRIu64"\n", j, q);\
116         return -1; }
117 #define ERROR_FLOOR(res, i, pow) \
118                 (res % pow) ||                                          /* check if not aligned */ \
119                 ((res / pow) != (i / pow))              /* check if correct alignment */
120 #define ERROR_CEIL(res, i, pow) \
121                 (res % pow) ||                                          /* check if not aligned */ \
122                         ((i % pow) == 0 ?                               /* check if ceiling is invoked */ \
123                         val / pow != i / pow :                  /* if aligned */ \
124                         val / pow != (i / pow) + 1)             /* if not aligned, hence +1 */
125
126         uint32_t i, p, val;
127         uint64_t j, q;
128
129         for (i = 1, p = 1; i <= MAX_NUM; i ++) {
130                 if (rte_align32pow2(i) != p)
131                         FAIL_ALIGN("rte_align32pow2", i, p);
132                 if (i == p)
133                         p <<= 1;
134         }
135
136         for (i = 1, p = 1; i <= MAX_NUM; i++) {
137                 if (rte_align32prevpow2(i) != p)
138                         FAIL_ALIGN("rte_align32prevpow2", i, p);
139                 if (rte_is_power_of_2(i + 1))
140                         p = i + 1;
141         }
142
143         for (j = 1, q = 1; j <= MAX_NUM ; j++) {
144                 if (rte_align64pow2(j) != q)
145                         FAIL_ALIGN64("rte_align64pow2", j, q);
146                 if (j == q)
147                         q <<= 1;
148         }
149
150         for (j = 1, q = 1; j <= MAX_NUM ; j++) {
151                 if (rte_align64prevpow2(j) != q)
152                         FAIL_ALIGN64("rte_align64prevpow2", j, q);
153                 if (rte_is_power_of_2(j + 1))
154                         q = j + 1;
155         }
156
157         for (p = 2; p <= MAX_NUM; p <<= 1) {
158
159                 if (!rte_is_power_of_2(p))
160                         FAIL("rte_is_power_of_2");
161
162                 for (i = 1; i <= MAX_NUM; i++) {
163                         /* align floor */
164                         if (RTE_ALIGN_FLOOR((uintptr_t)i, p) % p)
165                                 FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p);
166
167                         val = RTE_PTR_ALIGN_FLOOR((uintptr_t) i, p);
168                         if (ERROR_FLOOR(val, i, p))
169                                 FAIL_ALIGN("RTE_PTR_ALIGN_FLOOR", i, p);
170
171                         val = RTE_ALIGN_FLOOR(i, p);
172                         if (ERROR_FLOOR(val, i, p))
173                                 FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p);
174
175                         /* align ceiling */
176                         val = RTE_PTR_ALIGN((uintptr_t) i, p);
177                         if (ERROR_CEIL(val, i, p))
178                                 FAIL_ALIGN("RTE_PTR_ALIGN", i, p);
179
180                         val = RTE_ALIGN(i, p);
181                         if (ERROR_CEIL(val, i, p))
182                                 FAIL_ALIGN("RTE_ALIGN", i, p);
183
184                         val = RTE_ALIGN_CEIL(i, p);
185                         if (ERROR_CEIL(val, i, p))
186                                 FAIL_ALIGN("RTE_ALIGN_CEIL", i, p);
187
188                         val = RTE_PTR_ALIGN_CEIL((uintptr_t)i, p);
189                         if (ERROR_CEIL(val, i, p))
190                                 FAIL_ALIGN("RTE_PTR_ALIGN_CEIL", i, p);
191
192                         /* by this point we know that val is aligned to p */
193                         if (!rte_is_aligned((void*)(uintptr_t) val, p))
194                                 FAIL("rte_is_aligned");
195                 }
196         }
197
198         for (p = 1; p <= MAX_NUM / 2; p++) {
199                 for (i = 1; i <= MAX_NUM / 2; i++) {
200                         val = RTE_ALIGN_MUL_CEIL(i, p);
201                         if (val % p != 0 || val < i)
202                                 FAIL_ALIGN("RTE_ALIGN_MUL_CEIL", i, p);
203                         val = RTE_ALIGN_MUL_FLOOR(i, p);
204                         if (val % p != 0 || val > i)
205                                 FAIL_ALIGN("RTE_ALIGN_MUL_FLOOR", i, p);
206                         val = RTE_ALIGN_MUL_NEAR(i, p);
207                         if (val % p != 0 || ((val != RTE_ALIGN_MUL_CEIL(i, p))
208                                 & (val != RTE_ALIGN_MUL_FLOOR(i, p))))
209                                 FAIL_ALIGN("RTE_ALIGN_MUL_NEAR", i, p);
210                 }
211         }
212
213         return 0;
214 }
215
216 static int
217 test_log2(void)
218 {
219         uint32_t i, base, compare;
220         const uint32_t max = 0x10000;
221         const uint32_t step = 1;
222
223         compare = rte_log2_u32(0);
224         if (compare != 0) {
225                 printf("Wrong rte_log2_u32(0) val %x, expected 0\n", compare);
226                 return TEST_FAILED;
227         }
228
229         compare = rte_log2_u64(0);
230         if (compare != 0) {
231                 printf("Wrong rte_log2_u64(0) val %x, expected 0\n", compare);
232                 return TEST_FAILED;
233         }
234
235         for (i = 1; i < max; i = i + step) {
236                 uint64_t i64;
237
238                 /* extend range for 64-bit */
239                 i64 = (uint64_t)i << 32;
240                 base = (uint32_t)ceilf(log2(i64));
241                 compare = rte_log2_u64(i64);
242                 if (base != compare) {
243                         printf("Wrong rte_log2_u64(%" PRIx64 ") val %x, expected %x\n",
244                                 i64, compare, base);
245                         return TEST_FAILED;
246                 }
247
248                 base = (uint32_t)ceilf(log2((uint32_t)i));
249                 compare = rte_log2_u32((uint32_t)i);
250                 if (base != compare) {
251                         printf("Wrong rte_log2_u32(%x) val %x, expected %x\n",
252                                 i, compare, base);
253                         return TEST_FAILED;
254                 }
255                 compare = rte_log2_u64((uint64_t)i);
256                 if (base != compare) {
257                         printf("Wrong rte_log2_u64(%x) val %x, expected %x\n",
258                                 i, compare, base);
259                         return TEST_FAILED;
260                 }
261         }
262         return 0;
263 }
264
265 static int
266 test_fls(void)
267 {
268         struct fls_test_vector {
269                 uint32_t arg;
270                 int rc;
271         };
272         int expected, rc;
273         uint32_t i, arg;
274
275         const struct fls_test_vector test[] = {
276                 {0x0, 0},
277                 {0x1, 1},
278                 {0x4000, 15},
279                 {0x80000000, 32},
280         };
281
282         for (i = 0; i < RTE_DIM(test); i++) {
283                 uint64_t arg64;
284
285                 arg = test[i].arg;
286                 rc = rte_fls_u32(arg);
287                 expected = test[i].rc;
288                 if (rc != expected) {
289                         printf("Wrong rte_fls_u32(0x%x) rc=%d, expected=%d\n",
290                                 arg, rc, expected);
291                         return TEST_FAILED;
292                 }
293                 /* 64-bit version */
294                 arg = test[i].arg;
295                 rc = rte_fls_u64(arg);
296                 expected = test[i].rc;
297                 if (rc != expected) {
298                         printf("Wrong rte_fls_u64(0x%x) rc=%d, expected=%d\n",
299                                 arg, rc, expected);
300                         return TEST_FAILED;
301                 }
302                 /* 64-bit version shifted by 32 bits */
303                 arg64 = (uint64_t)test[i].arg << 32;
304                 rc = rte_fls_u64(arg64);
305                 /* don't shift zero */
306                 expected = test[i].rc == 0 ? 0 : test[i].rc + 32;
307                 if (rc != expected) {
308                         printf("Wrong rte_fls_u64(0x%" PRIx64 ") rc=%d, expected=%d\n",
309                                 arg64, rc, expected);
310                         return TEST_FAILED;
311                 }
312         }
313
314         return 0;
315 }
316
317 static int
318 test_common(void)
319 {
320         int ret = 0;
321         ret |= test_align();
322         ret |= test_macros(0);
323         ret |= test_misc();
324         ret |= test_bsf();
325         ret |= test_log2();
326         ret |= test_fls();
327
328         return ret;
329 }
330
331 REGISTER_TEST_COMMAND(common_autotest, test_common);