]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/app/test-bbdev/main.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / dpdk / app / test-bbdev / main.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
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 /* Defines how many testcases can be specified as cmdline args */
20 #define MAX_CMDLINE_TESTCASES 8
21
22 static const char tc_sep = ',';
23
24 static struct test_params {
25 struct test_command *test_to_run[MAX_CMDLINE_TESTCASES];
26 unsigned int num_tests;
27 unsigned int num_ops;
28 unsigned int burst_sz;
29 unsigned int num_lcores;
30 char test_vector_filename[PATH_MAX];
31 } test_params;
32
33 static struct test_commands_list commands_list =
34 TAILQ_HEAD_INITIALIZER(commands_list);
35
36 void
37 add_test_command(struct test_command *t)
38 {
39 TAILQ_INSERT_TAIL(&commands_list, t, next);
40 }
41
42 int
43 unit_test_suite_runner(struct unit_test_suite *suite)
44 {
45 int test_result = TEST_SUCCESS;
46 unsigned int total = 0, skipped = 0, succeeded = 0, failed = 0;
47 uint64_t start, end;
48
49 printf(
50 "\n + ------------------------------------------------------- +\n");
51 printf(" + Starting Test Suite : %s\n", suite->suite_name);
52
53 start = rte_rdtsc_precise();
54
55 if (suite->setup) {
56 test_result = suite->setup();
57 if (test_result == TEST_FAILED) {
58 printf(" + Test suite setup %s failed!\n",
59 suite->suite_name);
60 printf(
61 " + ------------------------------------------------------- +\n");
62 return 1;
63 }
64 if (test_result == TEST_SKIPPED) {
65 printf(" + Test suite setup %s skipped!\n",
66 suite->suite_name);
67 printf(
68 " + ------------------------------------------------------- +\n");
69 return 0;
70 }
71 }
72
73 while (suite->unit_test_cases[total].testcase) {
74 if (suite->unit_test_cases[total].setup)
75 test_result = suite->unit_test_cases[total].setup();
76
77 if (test_result == TEST_SUCCESS)
78 test_result = suite->unit_test_cases[total].testcase();
79
80 if (suite->unit_test_cases[total].teardown)
81 suite->unit_test_cases[total].teardown();
82
83 if (test_result == TEST_SUCCESS) {
84 succeeded++;
85 printf(" + TestCase [%2d] : %s passed\n", total,
86 suite->unit_test_cases[total].name);
87 } else if (test_result == TEST_SKIPPED) {
88 skipped++;
89 printf(" + TestCase [%2d] : %s skipped\n", total,
90 suite->unit_test_cases[total].name);
91 } else {
92 failed++;
93 printf(" + TestCase [%2d] : %s failed\n", total,
94 suite->unit_test_cases[total].name);
95 }
96
97 total++;
98 }
99
100 /* Run test suite teardown */
101 if (suite->teardown)
102 suite->teardown();
103
104 end = rte_rdtsc_precise();
105
106 printf(" + ------------------------------------------------------- +\n");
107 printf(" + Test Suite Summary : %s\n", suite->suite_name);
108 printf(" + Tests Total : %2d\n", total);
109 printf(" + Tests Skipped : %2d\n", skipped);
110 printf(" + Tests Passed : %2d\n", succeeded);
111 printf(" + Tests Failed : %2d\n", failed);
112 printf(" + Tests Lasted : %lg ms\n",
113 ((end - start) * 1000) / (double)rte_get_tsc_hz());
114 printf(" + ------------------------------------------------------- +\n");
115
116 return (failed > 0) ? 1 : 0;
117 }
118
119 const char *
120 get_vector_filename(void)
121 {
122 return test_params.test_vector_filename;
123 }
124
125 unsigned int
126 get_num_ops(void)
127 {
128 return test_params.num_ops;
129 }
130
131 unsigned int
132 get_burst_sz(void)
133 {
134 return test_params.burst_sz;
135 }
136
137 unsigned int
138 get_num_lcores(void)
139 {
140 return test_params.num_lcores;
141 }
142
143 static void
144 print_usage(const char *prog_name)
145 {
146 struct test_command *t;
147
148 printf("Usage: %s [EAL params] [-- [-n/--num-ops NUM_OPS]\n"
149 "\t[-b/--burst-size BURST_SIZE]\n"
150 "\t[-v/--test-vector VECTOR_FILE]\n"
151 "\t[-c/--test-cases TEST_CASE[,TEST_CASE,...]]]\n",
152 prog_name);
153
154 printf("Available testcases: ");
155 TAILQ_FOREACH(t, &commands_list, next)
156 printf("%s ", t->command);
157 printf("\n");
158 }
159
160 static int
161 parse_args(int argc, char **argv, struct test_params *tp)
162 {
163 int opt, option_index;
164 unsigned int num_tests = 0;
165 bool test_cases_present = false;
166 bool test_vector_present = false;
167 struct test_command *t;
168 char *tokens[MAX_CMDLINE_TESTCASES];
169 int tc, ret;
170
171 static struct option lgopts[] = {
172 { "num-ops", 1, 0, 'n' },
173 { "burst-size", 1, 0, 'b' },
174 { "test-cases", 1, 0, 'c' },
175 { "test-vector", 1, 0, 'v' },
176 { "lcores", 1, 0, 'l' },
177 { "help", 0, 0, 'h' },
178 { NULL, 0, 0, 0 }
179 };
180
181 while ((opt = getopt_long(argc, argv, "hn:b:c:v:l:", lgopts,
182 &option_index)) != EOF)
183 switch (opt) {
184 case 'n':
185 TEST_ASSERT(strlen(optarg) > 0,
186 "Num of operations is not provided");
187 tp->num_ops = strtol(optarg, NULL, 10);
188 break;
189 case 'b':
190 TEST_ASSERT(strlen(optarg) > 0,
191 "Burst size is not provided");
192 tp->burst_sz = strtol(optarg, NULL, 10);
193 TEST_ASSERT(tp->burst_sz <= MAX_BURST,
194 "Burst size mustn't be greater than %u",
195 MAX_BURST);
196 break;
197 case 'c':
198 TEST_ASSERT(test_cases_present == false,
199 "Test cases provided more than once");
200 test_cases_present = true;
201
202 ret = rte_strsplit(optarg, strlen(optarg),
203 tokens, MAX_CMDLINE_TESTCASES, tc_sep);
204
205 TEST_ASSERT(ret <= MAX_CMDLINE_TESTCASES,
206 "Too many test cases (max=%d)",
207 MAX_CMDLINE_TESTCASES);
208
209 for (tc = 0; tc < ret; ++tc) {
210 /* Find matching test case */
211 TAILQ_FOREACH(t, &commands_list, next)
212 if (!strcmp(tokens[tc], t->command))
213 tp->test_to_run[num_tests] = t;
214
215 TEST_ASSERT(tp->test_to_run[num_tests] != NULL,
216 "Unknown test case: %s",
217 tokens[tc]);
218 ++num_tests;
219 }
220 break;
221 case 'v':
222 TEST_ASSERT(test_vector_present == false,
223 "Test vector provided more than once");
224 test_vector_present = true;
225
226 TEST_ASSERT(strlen(optarg) > 0,
227 "Config file name is null");
228
229 strlcpy(tp->test_vector_filename, optarg,
230 sizeof(tp->test_vector_filename));
231 break;
232 case 'l':
233 TEST_ASSERT(strlen(optarg) > 0,
234 "Num of lcores is not provided");
235 tp->num_lcores = strtol(optarg, NULL, 10);
236 TEST_ASSERT(tp->num_lcores <= RTE_MAX_LCORE,
237 "Num of lcores mustn't be greater than %u",
238 RTE_MAX_LCORE);
239 break;
240 case 'h':
241 print_usage(argv[0]);
242 return 0;
243 default:
244 printf("ERROR: Unknown option: -%c\n", opt);
245 return -1;
246 }
247
248 if (tp->num_ops == 0) {
249 printf(
250 "WARNING: Num of operations was not provided or was set 0. Set to default (%u)\n",
251 DEFAULT_OPS);
252 tp->num_ops = DEFAULT_OPS;
253 }
254 if (tp->burst_sz == 0) {
255 printf(
256 "WARNING: Burst size was not provided or was set 0. Set to default (%u)\n",
257 DEFAULT_BURST);
258 tp->burst_sz = DEFAULT_BURST;
259 }
260 if (tp->num_lcores == 0) {
261 printf(
262 "WARNING: Num of lcores was not provided or was set 0. Set to value from RTE config (%u)\n",
263 rte_lcore_count());
264 tp->num_lcores = rte_lcore_count();
265 }
266
267 TEST_ASSERT(tp->burst_sz <= tp->num_ops,
268 "Burst size (%u) mustn't be greater than num ops (%u)",
269 tp->burst_sz, tp->num_ops);
270
271 tp->num_tests = num_tests;
272 return 0;
273 }
274
275 static int
276 run_all_tests(void)
277 {
278 int ret = TEST_SUCCESS;
279 struct test_command *t;
280
281 TAILQ_FOREACH(t, &commands_list, next)
282 ret |= t->callback();
283
284 return ret;
285 }
286
287 static int
288 run_parsed_tests(struct test_params *tp)
289 {
290 int ret = TEST_SUCCESS;
291 unsigned int i;
292
293 for (i = 0; i < tp->num_tests; ++i)
294 ret |= tp->test_to_run[i]->callback();
295
296 return ret;
297 }
298
299 int
300 main(int argc, char **argv)
301 {
302 int ret;
303
304 /* Init EAL */
305 ret = rte_eal_init(argc, argv);
306 if (ret < 0)
307 return 1;
308 argc -= ret;
309 argv += ret;
310
311 /* Parse application arguments (after the EAL ones) */
312 ret = parse_args(argc, argv, &test_params);
313 if (ret < 0) {
314 print_usage(argv[0]);
315 return 1;
316 }
317
318 /* If no argument provided - run all tests */
319 if (test_params.num_tests == 0)
320 return run_all_tests();
321 else
322 return run_parsed_tests(&test_params);
323 }