vppinfra: widen the scope of test_vector_funcs
[vpp.git] / src / vppinfra / test / test.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4
5 #include <vppinfra/format.h>
6 #include <vppinfra/test/test.h>
7 #include <vppinfra/error.h>
8
9 test_main_t test_main;
10
11 int
12 test_march_supported (clib_march_variant_type_t type)
13 {
14 #define _(s, n)                                                               \
15   if (CLIB_MARCH_VARIANT_TYPE_##s == type)                                    \
16     return clib_cpu_march_priority_##s ();
17   foreach_march_variant
18 #undef _
19     return 0;
20 }
21
22 clib_error_t *
23 test_funct (test_main_t *tm)
24 {
25   for (int i = 0; i < CLIB_MARCH_TYPE_N_VARIANTS; i++)
26     {
27       test_registration_t *r = tm->registrations[i];
28
29       if (r == 0 || test_march_supported (i) < 0)
30         continue;
31
32       fformat (stdout, "\nMultiarch Variant: %U\n", format_march_variant, i);
33       fformat (stdout,
34                "-------------------------------------------------------\n");
35       while (r)
36         {
37           clib_error_t *err;
38           if (tm->filter && strstr (r->name, (char *) tm->filter) == 0)
39             goto next;
40           err = (r->fn) (0);
41           fformat (stdout, "%-50s %s\n", r->name, err ? "FAIL" : "PASS");
42           if (err)
43             {
44               clib_error_report (err);
45               fformat (stdout, "\n");
46             }
47         next:
48           r = r->next;
49         }
50     }
51
52   fformat (stdout, "\n");
53   return 0;
54 }
55
56 #if 0
57 static u8 *
58 format_test_perf_bundle_core_power (u8 *s, va_list *args)
59 {
60   test_perf_event_bundle_t __clib_unused *b =
61     va_arg (*args, test_perf_event_bundle_t *);
62   test_perf_t __clib_unused *tp = va_arg (*args, test_perf_t *);
63   u64 *data = va_arg (*args, u64 *);
64
65   if (data)
66     s = format (s, "%7.1f %%", (f64) 100 * data[1] / data[0]);
67   else
68     s = format (s, "%9s", "Level 0");
69
70   if (data)
71     s = format (s, "%8.1f %%", (f64) 100 * data[2] / data[0]);
72   else
73     s = format (s, "%9s", "Level 1");
74
75   if (data)
76     s = format (s, "%7.1f %%", (f64) 100 * data[3] / data[0]);
77   else
78     s = format (s, "%9s", "Level 2");
79
80   return s;
81 }
82
83 #ifdef __x86_64__
84 #define PERF_INTEL_CODE(event, umask) ((event) | (umask) << 8)
85   ,
86   {
87     .name = "core-power",
88     .desc =
89       "Core cycles where the core was running under specific turbo schedule.",
90     .type = PERF_TYPE_RAW,
91     .config[0] = PERF_INTEL_CODE (0x3c, 0x00),
92     .config[1] = PERF_INTEL_CODE (0x28, 0x07),
93     .config[2] = PERF_INTEL_CODE (0x28, 0x18),
94     .config[3] = PERF_INTEL_CODE (0x28, 0x20),
95     .config[4] = PERF_INTEL_CODE (0x28, 0x40),
96     .n_events = 5,
97     .format_fn = format_test_perf_bundle_core_power,
98   }
99 #endif
100 };
101 #endif
102
103 #ifdef __linux__
104 clib_error_t *
105 test_perf (test_main_t *tm)
106 {
107   clib_error_t *err = 0;
108   clib_perfmon_ctx_t _ctx, *ctx = &_ctx;
109
110   if ((err = clib_perfmon_init_by_bundle_name (
111          ctx, "%s", tm->bundle ? (char *) tm->bundle : "default")))
112     return err;
113
114   fformat (stdout, "Warming up...\n");
115   clib_perfmon_warmup (ctx);
116
117   for (int i = 0; i < CLIB_MARCH_TYPE_N_VARIANTS; i++)
118     {
119       test_registration_t *r = tm->registrations[i];
120
121       if (r == 0 || test_march_supported (i) < 0)
122         continue;
123
124       fformat (stdout, "\nMultiarch Variant: %U\n", format_march_variant, i);
125       fformat (stdout,
126                "-------------------------------------------------------\n");
127       while (r)
128         {
129           if (r->perf_tests)
130             {
131               test_perf_t *pt = r->perf_tests;
132               if (tm->filter && strstr (r->name, (char *) tm->filter) == 0)
133                 goto next;
134
135               clib_perfmon_capture_group (ctx, "%s", r->name);
136               do
137                 {
138                   for (int i = 0; i < tm->repeat; i++)
139                     {
140                       pt->fd = ctx->group_fd;
141                       clib_perfmon_reset (ctx);
142                       pt->fn (pt);
143                       clib_perfmon_capture (ctx, pt->n_ops, "%0s", pt->name);
144                     }
145                 }
146               while ((++pt)->fn);
147             }
148         next:
149           r = r->next;
150         }
151       fformat (stdout, "%U\n", format_perfmon_bundle, ctx);
152       clib_perfmon_clear (ctx);
153     }
154
155   clib_perfmon_free (ctx);
156   return err;
157 }
158 #endif
159
160 int
161 main (int argc, char *argv[])
162 {
163   test_main_t *tm = &test_main;
164   unformat_input_t _i = {}, *i = &_i;
165   clib_mem_init (0, 64ULL << 20);
166   clib_error_t *err;
167   int perf = 0;
168
169   /* defaults */
170   tm->repeat = 3;
171
172   unformat_init_command_line (i, argv);
173
174   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
175     {
176       if (unformat (i, "perf"))
177         perf = 1;
178       else if (unformat (i, "filter %s", &tm->filter))
179         ;
180       else if (unformat (i, "bundle %s", &tm->bundle))
181         ;
182       else if (unformat (i, "repeat %d", &tm->repeat))
183         ;
184       else
185         {
186           clib_warning ("unknown input '%U'", format_unformat_error, i);
187           exit (1);
188         }
189     }
190
191   if (perf)
192     err = test_perf (tm);
193   else
194     err = test_funct (tm);
195
196   if (err)
197     {
198       clib_error_report (err);
199       fformat (stderr, "\n");
200       return 1;
201     }
202   return 0;
203 }
204
205 void *
206 test_mem_alloc (uword size)
207 {
208   void *rv;
209   size = round_pow2 (size, CLIB_CACHE_LINE_BYTES);
210   rv = clib_mem_alloc_aligned (size, CLIB_CACHE_LINE_BYTES);
211   clib_memset_u8 (rv, 0, size);
212   return rv;
213 }
214
215 void *
216 test_mem_alloc_and_fill_inc_u8 (uword size, u8 start, u8 mask)
217 {
218   u8 *rv;
219   mask = mask ? mask : 0xff;
220   size = round_pow2 (size, CLIB_CACHE_LINE_BYTES);
221   rv = clib_mem_alloc_aligned (size, CLIB_CACHE_LINE_BYTES);
222   for (uword i = 0; i < size; i++)
223     rv[i] = ((u8) i + start) & mask;
224   return rv;
225 }
226
227 void *
228 test_mem_alloc_and_splat (uword elt_size, uword n_elts, void *elt)
229 {
230   u8 *rv, *e;
231   uword data_size = elt_size * n_elts;
232   uword alloc_size = round_pow2 (data_size, CLIB_CACHE_LINE_BYTES);
233   e = rv = clib_mem_alloc_aligned (alloc_size, CLIB_CACHE_LINE_BYTES);
234   while (e - rv < data_size)
235     {
236       clib_memcpy_fast (e, elt, elt_size);
237       e += elt_size;
238     }
239
240   if (data_size < alloc_size)
241     clib_memset_u8 (e, 0, alloc_size - data_size);
242   return rv;
243 }
244
245 void
246 test_mem_free (void *p)
247 {
248   clib_mem_free (p);
249 }