1
2
3
4
5#include <getopt.h>
6#include <inttypes.h>
7#include <stdio.h>
8#include <string.h>
9#include <stdbool.h>
10
11#include <rte_eal.h>
12#include <rte_common.h>
13#include <rte_string_fns.h>
14#include <rte_cycles.h>
15#include <rte_lcore.h>
16
17#include "main.h"
18
19
20
21#define MAX_CMDLINE_TESTCASES 8
22
23static const char tc_sep = ',';
24
25
26static struct test_params {
27 struct test_command *test_to_run[MAX_CMDLINE_TESTCASES];
28 unsigned int num_tests;
29 unsigned int num_ops;
30 unsigned int burst_sz;
31 unsigned int num_lcores;
32 double snr;
33 unsigned int iter_max;
34 char test_vector_filename[PATH_MAX];
35 bool init_device;
36} test_params;
37
38static struct test_commands_list commands_list =
39 TAILQ_HEAD_INITIALIZER(commands_list);
40
41void
42add_test_command(struct test_command *t)
43{
44 TAILQ_INSERT_TAIL(&commands_list, t, next);
45}
46
47int
48unit_test_suite_runner(struct unit_test_suite *suite)
49{
50 int test_result = TEST_SUCCESS;
51 unsigned int total = 0, skipped = 0, succeeded = 0, failed = 0;
52 uint64_t start, end;
53
54 printf("\n===========================================================\n");
55 printf("Starting Test Suite : %s\n", suite->suite_name);
56
57 start = rte_rdtsc_precise();
58
59 if (suite->setup) {
60 test_result = suite->setup();
61 if (test_result == TEST_FAILED) {
62 printf(" + Test suite setup %s failed!\n",
63 suite->suite_name);
64 printf(" + ------------------------------------------------------- +\n");
65 return 1;
66 }
67 if (test_result == TEST_SKIPPED) {
68 printf(" + Test suite setup %s skipped!\n",
69 suite->suite_name);
70 printf(" + ------------------------------------------------------- +\n");
71 return 0;
72 }
73 }
74
75 while (suite->unit_test_cases[total].testcase) {
76 if (suite->unit_test_cases[total].setup)
77 test_result = suite->unit_test_cases[total].setup();
78
79 if (test_result == TEST_SUCCESS)
80 test_result = suite->unit_test_cases[total].testcase();
81
82 if (suite->unit_test_cases[total].teardown)
83 suite->unit_test_cases[total].teardown();
84
85 if (test_result == TEST_SUCCESS) {
86 succeeded++;
87 printf("TestCase [%2d] : %s passed\n", total,
88 suite->unit_test_cases[total].name);
89 } else if (test_result == TEST_SKIPPED) {
90 skipped++;
91 printf("TestCase [%2d] : %s skipped\n", total,
92 suite->unit_test_cases[total].name);
93 } else {
94 failed++;
95 printf("TestCase [%2d] : %s failed\n", total,
96 suite->unit_test_cases[total].name);
97 }
98
99 total++;
100 }
101
102
103 if (suite->teardown)
104 suite->teardown();
105
106 end = rte_rdtsc_precise();
107
108 printf(" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\n");
109 printf(" + Test Suite Summary : %s\n", suite->suite_name);
110 printf(" + Tests Total : %2d\n", total);
111 printf(" + Tests Skipped : %2d\n", skipped);
112 printf(" + Tests Passed : %2d\n", succeeded);
113 printf(" + Tests Failed : %2d\n", failed);
114 printf(" + Tests Lasted : %lg ms\n",
115 ((end - start) * 1000) / (double)rte_get_tsc_hz());
116 printf(" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\n");
117
118 return (failed > 0) ? 1 : 0;
119}
120
121const char *
122get_vector_filename(void)
123{
124 return test_params.test_vector_filename;
125}
126
127unsigned int
128get_num_ops(void)
129{
130 return test_params.num_ops;
131}
132
133unsigned int
134get_burst_sz(void)
135{
136 return test_params.burst_sz;
137}
138
139unsigned int
140get_num_lcores(void)
141{
142 return test_params.num_lcores;
143}
144
145double
146get_snr(void)
147{
148 return test_params.snr;
149}
150
151unsigned int
152get_iter_max(void)
153{
154 return test_params.iter_max;
155}
156
157bool
158get_init_device(void)
159{
160 return test_params.init_device;
161}
162
163static void
164print_usage(const char *prog_name)
165{
166 struct test_command *t;
167
168 printf("***Usage: %s [EAL params] [-- [-n/--num-ops NUM_OPS]\n"
169 "\t[-b/--burst-size BURST_SIZE]\n"
170 "\t[-v/--test-vector VECTOR_FILE]\n"
171 "\t[-c/--test-cases TEST_CASE[,TEST_CASE,...]]]\n",
172 prog_name);
173
174 printf("Available testcases: ");
175 TAILQ_FOREACH(t, &commands_list, next)
176 printf("%s ", t->command);
177 printf("\n");
178}
179
180static int
181parse_args(int argc, char **argv, struct test_params *tp)
182{
183 int opt, option_index;
184 unsigned int num_tests = 0;
185 bool test_cases_present = false;
186 bool test_vector_present = false;
187 struct test_command *t;
188 char *tokens[MAX_CMDLINE_TESTCASES];
189 int tc, ret;
190
191 static struct option lgopts[] = {
192 { "num-ops", 1, 0, 'n' },
193 { "burst-size", 1, 0, 'b' },
194 { "test-cases", 1, 0, 'c' },
195 { "test-vector", 1, 0, 'v' },
196 { "lcores", 1, 0, 'l' },
197 { "snr", 1, 0, 's' },
198 { "iter_max", 6, 0, 't' },
199 { "init-device", 0, 0, 'i'},
200 { "help", 0, 0, 'h' },
201 { NULL, 0, 0, 0 }
202 };
203 tp->iter_max = DEFAULT_ITER;
204
205 while ((opt = getopt_long(argc, argv, "hin:b:c:v:l:s:t:", lgopts,
206 &option_index)) != EOF)
207 switch (opt) {
208 case 'n':
209 TEST_ASSERT(strlen(optarg) > 0,
210 "Num of operations is not provided");
211 tp->num_ops = strtol(optarg, NULL, 10);
212 break;
213 case 'b':
214 TEST_ASSERT(strlen(optarg) > 0,
215 "Burst size is not provided");
216 tp->burst_sz = strtol(optarg, NULL, 10);
217 TEST_ASSERT(tp->burst_sz <= MAX_BURST,
218 "Burst size mustn't be greater than %u",
219 MAX_BURST);
220 break;
221 case 'c':
222 TEST_ASSERT(test_cases_present == false,
223 "Test cases provided more than once");
224 test_cases_present = true;
225
226 ret = rte_strsplit(optarg, strlen(optarg),
227 tokens, MAX_CMDLINE_TESTCASES, tc_sep);
228
229 TEST_ASSERT(ret <= MAX_CMDLINE_TESTCASES,
230 "Too many test cases (max=%d)",
231 MAX_CMDLINE_TESTCASES);
232
233 for (tc = 0; tc < ret; ++tc) {
234
235 TAILQ_FOREACH(t, &commands_list, next)
236 if (!strcmp(tokens[tc], t->command))
237 tp->test_to_run[num_tests] = t;
238
239 TEST_ASSERT(tp->test_to_run[num_tests] != NULL,
240 "Unknown test case: %s",
241 tokens[tc]);
242 ++num_tests;
243 }
244 break;
245 case 'v':
246 TEST_ASSERT(test_vector_present == false,
247 "Test vector provided more than once");
248 test_vector_present = true;
249
250 TEST_ASSERT(strlen(optarg) > 0,
251 "Config file name is null");
252
253 snprintf(tp->test_vector_filename,
254 sizeof(tp->test_vector_filename),
255 "%s", optarg);
256 break;
257 case 's':
258 TEST_ASSERT(strlen(optarg) > 0,
259 "SNR is not provided");
260 tp->snr = strtod(optarg, NULL);
261 break;
262 case 't':
263 TEST_ASSERT(strlen(optarg) > 0,
264 "Iter_max is not provided");
265 tp->iter_max = strtol(optarg, NULL, 10);
266 break;
267 case 'l':
268 TEST_ASSERT(strlen(optarg) > 0,
269 "Num of lcores is not provided");
270 tp->num_lcores = strtol(optarg, NULL, 10);
271 TEST_ASSERT(tp->num_lcores <= RTE_MAX_LCORE,
272 "Num of lcores mustn't be greater than %u",
273 RTE_MAX_LCORE);
274 break;
275 case 'i':
276
277 tp->init_device = true;
278 break;
279 case 'h':
280 print_usage(argv[0]);
281 return 0;
282 default:
283 printf("ERROR: Unknown option: -%c\n", opt);
284 return -1;
285 }
286
287 if (tp->num_ops == 0) {
288 printf(
289 "WARNING: Num of operations was not provided or was set 0. Set to default (%u)\n",
290 DEFAULT_OPS);
291 tp->num_ops = DEFAULT_OPS;
292 }
293 if (tp->burst_sz == 0) {
294 printf(
295 "WARNING: Burst size was not provided or was set 0. Set to default (%u)\n",
296 DEFAULT_BURST);
297 tp->burst_sz = DEFAULT_BURST;
298 }
299 if (tp->num_lcores == 0) {
300 printf(
301 "WARNING: Num of lcores was not provided or was set 0. Set to value from RTE config (%u)\n",
302 rte_lcore_count());
303 tp->num_lcores = rte_lcore_count();
304 }
305
306 TEST_ASSERT(tp->burst_sz <= tp->num_ops,
307 "Burst size (%u) mustn't be greater than num ops (%u)",
308 tp->burst_sz, tp->num_ops);
309
310 tp->num_tests = num_tests;
311 return 0;
312}
313
314static int
315run_all_tests(void)
316{
317 int ret = TEST_SUCCESS;
318 struct test_command *t;
319
320 TAILQ_FOREACH(t, &commands_list, next)
321 ret |= (int) t->callback();
322
323 return ret;
324}
325
326static int
327run_parsed_tests(struct test_params *tp)
328{
329 int ret = TEST_SUCCESS;
330 unsigned int i;
331
332 for (i = 0; i < tp->num_tests; ++i)
333 ret |= (int) tp->test_to_run[i]->callback();
334
335 return ret;
336}
337
338int
339main(int argc, char **argv)
340{
341 int ret;
342
343
344 ret = rte_eal_init(argc, argv);
345 if (ret < 0)
346 return 1;
347 argc -= ret;
348 argv += ret;
349
350
351 ret = parse_args(argc, argv, &test_params);
352 if (ret < 0) {
353 print_usage(argv[0]);
354 return 1;
355 }
356
357
358 if (test_params.num_tests == 0)
359 return run_all_tests();
360 else
361 return run_parsed_tests(&test_params);
362}
363