xref: /linux/tools/tracing/rtla/tests/unit/cli_opt_callback.c (revision 92a33d5bad7485b39c7403ad1741b3b2b35a0131)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #define _GNU_SOURCE
4 #include <stdio.h>
5 #include <check.h>
6 
7 #define RTLA_ALLOW_CLI_P_H
8 #include "../../src/cli_p.h"
9 #include "cli_params_assert.h"
10 
11 #define TEST_CALLBACK(value, cb) OPT_CALLBACK('t', "test", value, "test value", "test help", cb)
12 #define TEST_LLONG_RANGE(value, lo, hi) \
13 	RTLA_OPT_CALLBACK_DATA('t', "test", value, "test value", "test help", \
14 	opt_llong_callback, LLONG_RANGE(lo, hi))
15 #define TEST_INT_RANGE(value, lo, hi) \
16 	RTLA_OPT_CALLBACK_DATA('t', "test", value, "test value", "test help", \
17 	opt_int_callback, INT_RANGE(lo, hi))
18 
19 START_TEST(test_opt_llong_callback_simple)
20 {
21 	long long test_value = 0;
22 	const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
23 
24 	ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
25 	ck_assert_int_eq(test_value, 1234567890);
26 }
27 END_TEST
28 
29 START_TEST(test_opt_llong_callback_max)
30 {
31 	long long test_value = 0;
32 	const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
33 
34 	ck_assert_int_eq(opt_llong_callback(&opt, "9223372036854775807", 0), 0);
35 	ck_assert_int_eq(test_value, 9223372036854775807LL);
36 }
37 END_TEST
38 
39 START_TEST(test_opt_llong_callback_min)
40 {
41 	long long test_value = 0;
42 	const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
43 
44 	ck_assert_int_eq(opt_llong_callback(&opt, "-9223372036854775808", 0), 0);
45 	ck_assert_int_eq(test_value, ~9223372036854775807LL);
46 }
47 END_TEST
48 
49 START_TEST(test_opt_llong_callback_unset)
50 {
51 	long long test_value = 0;
52 	const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
53 
54 	ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
55 	ck_assert_int_eq(opt_llong_callback(&opt, NULL, 1), 0);
56 	ck_assert_int_eq(test_value, 0);
57 }
58 END_TEST
59 
60 START_TEST(test_opt_llong_callback_unset_defval)
61 {
62 	long long test_value = 0;
63 	const long long default_value = 42;
64 	const struct option opt = RTLA_OPT_LLONG_DEFVAL('t', "test", &test_value, "test value",
65 							"test help", &default_value);
66 
67 	ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
68 	ck_assert_int_eq(opt_llong_callback(&opt, NULL, 1), 0);
69 	ck_assert_int_eq(test_value, default_value);
70 }
71 END_TEST
72 
73 START_TEST(test_opt_int_callback_simple)
74 {
75 	int test_value = 0;
76 	const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
77 
78 	ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
79 	ck_assert_int_eq(test_value, 1234567890);
80 }
81 END_TEST
82 
83 START_TEST(test_opt_int_callback_max)
84 {
85 	int test_value = 0;
86 	const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
87 
88 	ck_assert_int_eq(opt_int_callback(&opt, "2147483647", 0), 0);
89 	ck_assert_int_eq(test_value, 2147483647);
90 }
91 END_TEST
92 
93 START_TEST(test_opt_int_callback_min)
94 {
95 	int test_value = 0;
96 	const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
97 
98 	ck_assert_int_eq(opt_int_callback(&opt, "-2147483648", 0), 0);
99 	ck_assert_int_eq(test_value, -2147483648);
100 }
101 END_TEST
102 
103 START_TEST(test_opt_int_callback_non_numeric)
104 {
105 	int test_value = 0;
106 	const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
107 
108 	ck_assert_int_eq(opt_int_callback(&opt, "abc", 0), -1);
109 	ck_assert_int_eq(test_value, 0);
110 }
111 END_TEST
112 
113 START_TEST(test_opt_int_callback_non_numeric_suffix)
114 {
115 	int test_value = 0;
116 	const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
117 
118 	ck_assert_int_eq(opt_int_callback(&opt, "1234567890abc", 0), -1);
119 	ck_assert_int_eq(test_value, 0);
120 }
121 END_TEST
122 
123 START_TEST(test_opt_int_callback_unset)
124 {
125 	int test_value = 0;
126 	const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
127 
128 	ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
129 	ck_assert_int_eq(opt_int_callback(&opt, NULL, 1), 0);
130 	ck_assert_int_eq(test_value, 0);
131 }
132 END_TEST
133 
134 START_TEST(test_opt_int_callback_unset_defval)
135 {
136 	int test_value = 0;
137 	const struct option opt = RTLA_OPT_INT_DEFVAL('t', "test", &test_value, "test value",
138 						      "test help", 42);
139 
140 	ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
141 	ck_assert_int_eq(opt_int_callback(&opt, NULL, 1), 0);
142 	ck_assert_int_eq(test_value, 42);
143 }
144 END_TEST
145 
146 START_TEST(test_opt_llong_callback_range_in)
147 {
148 	long long test_value = 0;
149 	const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
150 
151 	ck_assert_int_eq(opt_llong_callback(&opt, "50", 0), 0);
152 	ck_assert_int_eq(test_value, 50);
153 }
154 END_TEST
155 
156 START_TEST(test_opt_llong_callback_range_below)
157 {
158 	long long test_value = 0;
159 	const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
160 
161 	assert(freopen("/dev/null", "w", stderr));
162 	ck_assert_int_eq(opt_llong_callback(&opt, "9", 0), -1);
163 }
164 END_TEST
165 
166 START_TEST(test_opt_llong_callback_range_above)
167 {
168 	long long test_value = 0;
169 	const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
170 
171 	assert(freopen("/dev/null", "w", stderr));
172 	ck_assert_int_eq(opt_llong_callback(&opt, "101", 0), -1);
173 }
174 END_TEST
175 
176 START_TEST(test_opt_llong_callback_range_boundary)
177 {
178 	long long test_value = 0;
179 	const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
180 
181 	ck_assert_int_eq(opt_llong_callback(&opt, "10", 0), 0);
182 	ck_assert_int_eq(test_value, 10);
183 	ck_assert_int_eq(opt_llong_callback(&opt, "100", 0), 0);
184 	ck_assert_int_eq(test_value, 100);
185 }
186 END_TEST
187 
188 START_TEST(test_opt_int_callback_range_in)
189 {
190 	int test_value = 0;
191 	const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
192 
193 	ck_assert_int_eq(opt_int_callback(&opt, "5000", 0), 0);
194 	ck_assert_int_eq(test_value, 5000);
195 }
196 END_TEST
197 
198 START_TEST(test_opt_int_callback_range_below)
199 {
200 	int test_value = 0;
201 	const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
202 
203 	assert(freopen("/dev/null", "w", stderr));
204 	ck_assert_int_eq(opt_int_callback(&opt, "-1", 0), -1);
205 }
206 END_TEST
207 
208 START_TEST(test_opt_int_callback_range_above)
209 {
210 	int test_value = 0;
211 	const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
212 
213 	assert(freopen("/dev/null", "w", stderr));
214 	ck_assert_int_eq(opt_int_callback(&opt, "10001", 0), -1);
215 }
216 END_TEST
217 
218 START_TEST(test_opt_int_callback_range_boundary)
219 {
220 	int test_value = 0;
221 	const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
222 
223 	ck_assert_int_eq(opt_int_callback(&opt, "0", 0), 0);
224 	ck_assert_int_eq(test_value, 0);
225 	ck_assert_int_eq(opt_int_callback(&opt, "10000", 0), 0);
226 	ck_assert_int_eq(test_value, 10000);
227 }
228 END_TEST
229 
230 START_TEST(test_opt_cpus_cb)
231 {
232 	struct common_params params = {0};
233 	const struct option opt = TEST_CALLBACK(&params, opt_cpus_cb);
234 
235 	nr_cpus = 4;
236 	ck_assert_int_eq(opt_cpus_cb(&opt, "0-3", 0), 0);
237 	ck_assert_str_eq(params.cpus, "0-3");
238 }
239 END_TEST
240 
241 START_TEST(test_opt_cpus_cb_invalid)
242 {
243 	struct common_params params = {0};
244 	const struct option opt = TEST_CALLBACK(&params, opt_cpus_cb);
245 
246 	nr_cpus = 4;
247 	assert(freopen("/dev/null", "w", stderr));
248 	opt_cpus_cb(&opt, "0-3,5", 0);
249 }
250 END_TEST
251 
252 START_TEST(test_opt_cgroup_cb)
253 {
254 	struct common_params params = {0};
255 	const struct option opt = TEST_CALLBACK(&params, opt_cgroup_cb);
256 
257 	ck_assert_int_eq(opt_cgroup_cb(&opt, "cgroup", 0), 0);
258 	ck_assert_int_eq(params.cgroup, 1);
259 	ck_assert_str_eq(params.cgroup_name, "cgroup");
260 }
261 END_TEST
262 
263 START_TEST(test_opt_cgroup_cb_equals)
264 {
265 	struct common_params params = {0};
266 	const struct option opt = TEST_CALLBACK(&params, opt_cgroup_cb);
267 
268 	ck_assert_int_eq(opt_cgroup_cb(&opt, "=cgroup", 0), 0);
269 	ck_assert_int_eq(params.cgroup, 1);
270 	ck_assert_str_eq(params.cgroup_name, "cgroup");
271 }
272 END_TEST
273 
274 START_TEST(test_opt_cgroup_cb_unset)
275 {
276 	struct common_params params = {0};
277 	const struct option opt = TEST_CALLBACK(&params, opt_cgroup_cb);
278 
279 	ck_assert_int_eq(opt_cgroup_cb(&opt, "cgroup", 0), 0);
280 	ck_assert_int_eq(opt_cgroup_cb(&opt, NULL, 1), 0);
281 	ck_assert_int_eq(params.cgroup, 0);
282 	ck_assert_ptr_null(params.cgroup_name);
283 }
284 END_TEST
285 
286 START_TEST(test_opt_duration_cb)
287 {
288 	struct common_params params = {0};
289 	const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
290 
291 	ck_assert_int_eq(opt_duration_cb(&opt, "1m", 0), 0);
292 	ck_assert_int_eq(params.duration, 60);
293 }
294 END_TEST
295 
296 START_TEST(test_opt_duration_cb_invalid)
297 {
298 	struct common_params params = {0};
299 	const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
300 
301 	assert(freopen("/dev/null", "w", stderr));
302 	opt_duration_cb(&opt, "abc", 0);
303 }
304 END_TEST
305 
306 START_TEST(test_opt_duration_cb_unset)
307 {
308 	struct common_params params = {0};
309 	const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
310 
311 	ck_assert_int_eq(opt_duration_cb(&opt, "1m", 0), 0);
312 	ck_assert_int_eq(opt_duration_cb(&opt, NULL, 1), 0);
313 	ck_assert_int_eq(params.duration, 0);
314 }
315 END_TEST
316 
317 START_TEST(test_opt_event_cb)
318 {
319 	struct trace_events *events = NULL;
320 	const struct option opt = TEST_CALLBACK(&events, opt_event_cb);
321 
322 	ck_assert_int_eq(opt_event_cb(&opt, "sched:sched_switch", 0), 0);
323 	ck_assert_str_eq(events->system, "sched");
324 	ck_assert_str_eq(events->event, "sched_switch");
325 	ck_assert_ptr_eq(events->next, NULL);
326 }
327 END_TEST
328 
329 START_TEST(test_opt_event_cb_multiple)
330 {
331 	struct trace_events *events = NULL;
332 	const struct option opt = TEST_CALLBACK(&events, opt_event_cb);
333 
334 	ck_assert_int_eq(opt_event_cb(&opt, "sched:sched_switch", 0), 0);
335 	ck_assert_int_eq(opt_event_cb(&opt, "sched:sched_wakeup", 0), 0);
336 	ck_assert_str_eq(events->system, "sched");
337 	ck_assert_str_eq(events->event, "sched_wakeup");
338 	ck_assert_str_eq(events->next->system, "sched");
339 	ck_assert_str_eq(events->next->event, "sched_switch");
340 	ck_assert_ptr_eq(events->next->next, NULL);
341 }
342 END_TEST
343 
344 START_TEST(test_opt_housekeeping_cb)
345 {
346 	struct common_params __params = {0};
347 	struct common_params *params = &__params;
348 	const struct option opt = TEST_CALLBACK(params, opt_housekeeping_cb);
349 
350 	nr_cpus = 4;
351 	ck_assert_int_eq(opt_housekeeping_cb(&opt, "0-3", 0), 0);
352 	ck_assert_int_eq(params->hk_cpus, 1);
353 	CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 2, 3);
354 }
355 END_TEST
356 
357 START_TEST(test_opt_housekeeping_cb_invalid)
358 {
359 	struct common_params params = {0};
360 	const struct option opt = TEST_CALLBACK(&params, opt_housekeeping_cb);
361 
362 	nr_cpus = 4;
363 	assert(freopen("/dev/null", "w", stderr));
364 	opt_housekeeping_cb(&opt, "0-3,5", 0);
365 }
366 END_TEST
367 
368 START_TEST(test_opt_housekeeping_cb_unset)
369 {
370 	struct common_params params = {0};
371 	const struct option opt = TEST_CALLBACK(&params, opt_housekeeping_cb);
372 
373 	nr_cpus = 4;
374 	ck_assert_int_eq(opt_housekeeping_cb(&opt, "0-3", 0), 0);
375 	ck_assert_int_eq(opt_housekeeping_cb(&opt, NULL, 1), 0);
376 	ck_assert_int_eq(params.hk_cpus, 0);
377 	ck_assert_int_eq(CPU_COUNT(&params.hk_cpu_set), 0);
378 }
379 END_TEST
380 
381 START_TEST(test_opt_priority_cb)
382 {
383 	struct common_params params = {0};
384 	const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
385 
386 	ck_assert_int_eq(opt_priority_cb(&opt, "f:95", 0), 0);
387 	ck_assert_int_eq(params.sched_param.sched_policy, SCHED_FIFO);
388 	ck_assert_int_eq(params.sched_param.sched_priority, 95);
389 }
390 END_TEST
391 
392 START_TEST(test_opt_priority_cb_invalid)
393 {
394 	struct common_params params = {0};
395 	const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
396 
397 	assert(freopen("/dev/null", "w", stderr));
398 	opt_priority_cb(&opt, "abc", 0);
399 }
400 END_TEST
401 
402 START_TEST(test_opt_priority_cb_unset)
403 {
404 	struct common_params params = {0};
405 	const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
406 
407 	ck_assert_int_eq(opt_priority_cb(&opt, "f:95", 0), 0);
408 	ck_assert_int_eq(opt_priority_cb(&opt, NULL, 1), 0);
409 	ck_assert_int_eq(params.sched_param.sched_policy, 0);
410 	ck_assert_int_eq(params.sched_param.sched_priority, 0);
411 }
412 END_TEST
413 
414 START_TEST(test_opt_trigger_cb)
415 {
416 	struct trace_events *events = trace_event_alloc("sched:sched_switch");
417 	const struct option opt = TEST_CALLBACK(&events, opt_trigger_cb);
418 
419 	ck_assert_int_eq(opt_trigger_cb(&opt, "stacktrace", 0), 0);
420 	ck_assert_str_eq(events->trigger, "stacktrace");
421 }
422 END_TEST
423 
424 START_TEST(test_opt_trigger_cb_no_event)
425 {
426 	struct trace_events *events = NULL;
427 	const struct option opt = TEST_CALLBACK(&events, opt_trigger_cb);
428 
429 	assert(freopen("/dev/null", "w", stderr));
430 	opt_trigger_cb(&opt, "stacktrace", 0);
431 }
432 END_TEST
433 
434 START_TEST(test_opt_filter_cb)
435 {
436 	struct trace_events *events = trace_event_alloc("sched:sched_switch");
437 	const struct option opt = TEST_CALLBACK(&events, opt_filter_cb);
438 
439 	ck_assert_int_eq(opt_filter_cb(&opt, "comm ~ \"rtla\"", 0), 0);
440 	ck_assert_str_eq(events->filter, "comm ~ \"rtla\"");
441 }
442 END_TEST
443 
444 START_TEST(test_opt_filter_cb_no_event)
445 {
446 	struct trace_events *events = NULL;
447 	const struct option opt = TEST_CALLBACK(&events, opt_filter_cb);
448 
449 	assert(freopen("/dev/null", "w", stderr));
450 	opt_filter_cb(&opt, "comm ~ \"rtla\"", 0);
451 }
452 END_TEST
453 
454 START_TEST(test_opt_osnoise_auto_cb)
455 {
456 	struct osnoise_params params = {0};
457 	struct osnoise_cb_data cb_data = {&params};
458 	const struct option opt = TEST_CALLBACK(&cb_data, opt_osnoise_auto_cb);
459 
460 	ck_assert_int_eq(opt_osnoise_auto_cb(&opt, "10", 0), 0);
461 	ck_assert_int_eq(params.common.stop_us, 10);
462 	ck_assert_int_eq(params.threshold, 1);
463 	ck_assert_str_eq(cb_data.trace_output, "osnoise_trace.txt");
464 }
465 END_TEST
466 
467 START_TEST(test_opt_osnoise_auto_cb_unset)
468 {
469 	struct osnoise_params params = {0};
470 	struct osnoise_cb_data cb_data = {&params};
471 	const struct option opt = TEST_CALLBACK(&cb_data, opt_osnoise_auto_cb);
472 
473 	ck_assert_int_eq(opt_osnoise_auto_cb(&opt, "10", 0), 0);
474 	ck_assert_int_eq(opt_osnoise_auto_cb(&opt, NULL, 1), 0);
475 	ck_assert_int_eq(params.common.stop_us, 0);
476 	ck_assert_int_eq(params.threshold, 0);
477 	ck_assert_ptr_null(cb_data.trace_output);
478 }
479 END_TEST
480 
481 
482 START_TEST(test_opt_osnoise_trace_output_cb)
483 {
484 	const char *trace_output = NULL;
485 	const struct option opt = TEST_CALLBACK(&trace_output, opt_osnoise_trace_output_cb);
486 
487 	ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, "trace.txt", 0), 0);
488 	ck_assert_str_eq(trace_output, "trace.txt");
489 }
490 END_TEST
491 
492 START_TEST(test_opt_osnoise_trace_output_cb_noarg)
493 {
494 	const char *trace_output = NULL;
495 	const struct option opt = TEST_CALLBACK(&trace_output, opt_osnoise_trace_output_cb);
496 
497 	ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, NULL, 0), 0);
498 	ck_assert_str_eq(trace_output, "osnoise_trace.txt");
499 }
500 END_TEST
501 
502 START_TEST(test_opt_osnoise_trace_output_cb_unset)
503 {
504 	const char *trace_output = NULL;
505 	const struct option opt = TEST_CALLBACK(&trace_output, opt_osnoise_trace_output_cb);
506 
507 	ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, "trace.txt", 0), 0);
508 	ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, NULL, 1), 0);
509 	ck_assert_ptr_null(trace_output);
510 }
511 END_TEST
512 
513 START_TEST(test_opt_osnoise_on_threshold_cb)
514 {
515 	struct actions actions = {0};
516 	const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_threshold_cb);
517 
518 	ck_assert_int_eq(opt_osnoise_on_threshold_cb(&opt, "trace", 0), 0);
519 	ck_assert_int_eq(actions.len, 1);
520 	ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
521 	ck_assert_str_eq(actions.list[0].trace_output, "osnoise_trace.txt");
522 }
523 END_TEST
524 
525 START_TEST(test_opt_osnoise_on_threshold_cb_invalid)
526 {
527 	struct actions actions = {0};
528 	const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_threshold_cb);
529 
530 	assert(freopen("/dev/null", "w", stderr));
531 	opt_osnoise_on_threshold_cb(&opt, "abc", 0);
532 }
533 END_TEST
534 
535 START_TEST(test_opt_osnoise_on_end_cb)
536 {
537 	struct actions actions = {0};
538 	const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_end_cb);
539 
540 	ck_assert_int_eq(opt_osnoise_on_end_cb(&opt, "trace", 0), 0);
541 	ck_assert_int_eq(actions.len, 1);
542 	ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
543 	ck_assert_str_eq(actions.list[0].trace_output, "osnoise_trace.txt");
544 }
545 END_TEST
546 
547 START_TEST(test_opt_osnoise_on_end_cb_invalid)
548 {
549 	struct actions actions = {0};
550 	const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_end_cb);
551 
552 	assert(freopen("/dev/null", "w", stderr));
553 	opt_osnoise_on_end_cb(&opt, "abc", 0);
554 }
555 END_TEST
556 
557 START_TEST(test_opt_timerlat_auto_cb)
558 {
559 	struct timerlat_params params = {0};
560 	struct timerlat_cb_data cb_data = {&params};
561 	const struct option opt = TEST_CALLBACK(&cb_data, opt_timerlat_auto_cb);
562 
563 	ck_assert_int_eq(opt_timerlat_auto_cb(&opt, "10", 0), 0);
564 	ck_assert_int_eq(params.common.stop_us, 10);
565 	ck_assert_int_eq(params.common.stop_total_us, 10);
566 	ck_assert_int_eq(params.print_stack, 10);
567 	ck_assert_str_eq(cb_data.trace_output, "timerlat_trace.txt");
568 }
569 END_TEST
570 
571 START_TEST(test_opt_timerlat_auto_cb_unset)
572 {
573 	struct timerlat_params params = {0};
574 	struct timerlat_cb_data cb_data = {&params};
575 	const struct option opt = TEST_CALLBACK(&cb_data, opt_timerlat_auto_cb);
576 
577 	ck_assert_int_eq(opt_timerlat_auto_cb(&opt, "10", 0), 0);
578 	ck_assert_int_eq(opt_timerlat_auto_cb(&opt, NULL, 1), 0);
579 	ck_assert_int_eq(params.common.stop_us, 0);
580 	ck_assert_int_eq(params.common.stop_total_us, 0);
581 	ck_assert_int_eq(params.print_stack, 0);
582 	ck_assert_ptr_null(cb_data.trace_output);
583 }
584 END_TEST
585 
586 
587 START_TEST(test_opt_aa_only_cb)
588 {
589 	struct timerlat_params params = {0};
590 	const struct option opt = TEST_CALLBACK(&params, opt_aa_only_cb);
591 
592 	ck_assert_int_eq(opt_aa_only_cb(&opt, "10", 0), 0);
593 	ck_assert_int_eq(params.common.stop_us, 10);
594 	ck_assert_int_eq(params.common.stop_total_us, 10);
595 	ck_assert_int_eq(params.print_stack, 10);
596 	ck_assert_int_eq(params.common.aa_only, 1);
597 }
598 END_TEST
599 
600 START_TEST(test_opt_aa_only_cb_unset)
601 {
602 	struct timerlat_params params = {0};
603 	const struct option opt = TEST_CALLBACK(&params, opt_aa_only_cb);
604 
605 	ck_assert_int_eq(opt_aa_only_cb(&opt, "10", 0), 0);
606 	ck_assert_int_eq(opt_aa_only_cb(&opt, NULL, 1), 0);
607 	ck_assert_int_eq(params.common.stop_us, 0);
608 	ck_assert_int_eq(params.common.stop_total_us, 0);
609 	ck_assert_int_eq(params.print_stack, 0);
610 	ck_assert_int_eq(params.common.aa_only, 0);
611 }
612 END_TEST
613 
614 START_TEST(test_opt_timerlat_trace_output_cb)
615 {
616 	const char *trace_output = NULL;
617 	const struct option opt = TEST_CALLBACK(&trace_output, opt_timerlat_trace_output_cb);
618 
619 	ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, "trace.txt", 0), 0);
620 	ck_assert_str_eq(trace_output, "trace.txt");
621 }
622 END_TEST
623 
624 START_TEST(test_opt_timerlat_trace_output_cb_noarg)
625 {
626 	const char *trace_output = NULL;
627 	const struct option opt = TEST_CALLBACK(&trace_output, opt_timerlat_trace_output_cb);
628 
629 	ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, NULL, 0), 0);
630 	ck_assert_str_eq(trace_output, "timerlat_trace.txt");
631 }
632 END_TEST
633 
634 START_TEST(test_opt_timerlat_trace_output_cb_unset)
635 {
636 	const char *trace_output = NULL;
637 	const struct option opt = TEST_CALLBACK(&trace_output, opt_timerlat_trace_output_cb);
638 
639 	ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, "trace.txt", 0), 0);
640 	ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, NULL, 1), 0);
641 	ck_assert_ptr_null(trace_output);
642 }
643 END_TEST
644 
645 START_TEST(test_opt_timerlat_on_threshold_cb)
646 {
647 	struct actions actions = {0};
648 	const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_threshold_cb);
649 
650 	ck_assert_int_eq(opt_timerlat_on_threshold_cb(&opt, "trace", 0), 0);
651 	ck_assert_int_eq(actions.len, 1);
652 	ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
653 	ck_assert_str_eq(actions.list[0].trace_output, "timerlat_trace.txt");
654 }
655 END_TEST
656 
657 START_TEST(test_opt_timerlat_on_threshold_cb_invalid)
658 {
659 	struct actions actions = {0};
660 	const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_threshold_cb);
661 
662 	assert(freopen("/dev/null", "w", stderr));
663 	opt_timerlat_on_threshold_cb(&opt, "abc", 0);
664 }
665 END_TEST
666 
667 START_TEST(test_opt_timerlat_on_end_cb)
668 {
669 	struct actions actions = {0};
670 	const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_end_cb);
671 
672 	ck_assert_int_eq(opt_timerlat_on_end_cb(&opt, "trace", 0), 0);
673 	ck_assert_int_eq(actions.len, 1);
674 	ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
675 	ck_assert_str_eq(actions.list[0].trace_output, "timerlat_trace.txt");
676 }
677 END_TEST
678 
679 START_TEST(test_opt_timerlat_on_end_cb_invalid)
680 {
681 	struct actions actions = {0};
682 	const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_end_cb);
683 
684 	assert(freopen("/dev/null", "w", stderr));
685 	opt_timerlat_on_end_cb(&opt, "abc", 0);
686 }
687 END_TEST
688 
689 START_TEST(test_opt_user_threads_cb)
690 {
691 	struct timerlat_params params = {0};
692 	const struct option opt = TEST_CALLBACK(&params, opt_user_threads_cb);
693 
694 	ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 0), 0);
695 	ck_assert_int_eq(params.common.user_workload, 1);
696 	ck_assert_int_eq(params.common.user_data, 1);
697 }
698 END_TEST
699 
700 START_TEST(test_opt_user_threads_cb_unset)
701 {
702 	struct timerlat_params params = {0};
703 	const struct option opt = TEST_CALLBACK(&params, opt_user_threads_cb);
704 
705 	ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 0), 0);
706 	ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 1), 0);
707 	ck_assert_int_eq(params.common.user_workload, 0);
708 	ck_assert_int_eq(params.common.user_data, 0);
709 }
710 END_TEST
711 
712 START_TEST(test_opt_nano_cb)
713 {
714 	struct timerlat_params params = {0};
715 	const struct option opt = TEST_CALLBACK(&params, opt_nano_cb);
716 
717 	ck_assert_int_eq(opt_nano_cb(&opt, NULL, 0), 0);
718 	ck_assert_int_eq(params.common.output_divisor, 1);
719 }
720 END_TEST
721 
722 START_TEST(test_opt_nano_cb_unset)
723 {
724 	struct timerlat_params params = {0};
725 	const struct option opt = TEST_CALLBACK(&params, opt_nano_cb);
726 
727 	ck_assert_int_eq(opt_nano_cb(&opt, NULL, 0), 0);
728 	ck_assert_int_eq(opt_nano_cb(&opt, NULL, 1), 0);
729 	ck_assert_int_eq(params.common.output_divisor, default_output_divisor);
730 }
731 END_TEST
732 
733 START_TEST(test_opt_timerlat_align_cb)
734 {
735 	struct timerlat_params params = {0};
736 	const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
737 		"test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
738 
739 	ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
740 	ck_assert(params.timerlat_align);
741 	ck_assert_int_eq(params.timerlat_align_us, 500);
742 }
743 END_TEST
744 
745 START_TEST(test_opt_timerlat_align_cb_invalid)
746 {
747 	struct timerlat_params params = {0};
748 	const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
749 		"test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
750 
751 	assert(freopen("/dev/null", "w", stderr));
752 	ck_assert_int_eq(opt_timerlat_align_cb(&opt, "-1", 0), -1);
753 }
754 END_TEST
755 
756 START_TEST(test_opt_timerlat_align_cb_unset)
757 {
758 	struct timerlat_params params = {0};
759 	const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
760 		"test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
761 
762 	ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
763 	ck_assert_int_eq(opt_timerlat_align_cb(&opt, NULL, 1), 0);
764 	ck_assert_int_eq(params.timerlat_align, 0);
765 	ck_assert_int_eq(params.timerlat_align_us, 0);
766 }
767 END_TEST
768 
769 START_TEST(test_opt_stack_format_cb)
770 {
771 	int stack_format = 0;
772 	const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
773 
774 	ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
775 	ck_assert_int_eq(stack_format, STACK_FORMAT_FULL);
776 }
777 END_TEST
778 
779 START_TEST(test_opt_stack_format_cb_invalid)
780 {
781 	int stack_format = 0;
782 	const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
783 
784 	assert(freopen("/dev/null", "w", stderr));
785 	opt_stack_format_cb(&opt, "abc", 0);
786 }
787 END_TEST
788 
789 START_TEST(test_opt_stack_format_cb_unset)
790 {
791 	int stack_format = 0;
792 	const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
793 
794 	ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
795 	ck_assert_int_eq(opt_stack_format_cb(&opt, NULL, 1), 0);
796 	ck_assert_int_eq(stack_format, default_stack_format);
797 }
798 END_TEST
799 
800 
801 Suite *cli_opt_callback_suite(void)
802 {
803 	Suite *s = suite_create("cli_opt_callback");
804 	TCase *tc;
805 
806 	tc = tcase_create("common");
807 	tcase_add_test(tc, test_opt_llong_callback_simple);
808 	tcase_add_test(tc, test_opt_llong_callback_max);
809 	tcase_add_test(tc, test_opt_llong_callback_min);
810 	tcase_add_test(tc, test_opt_llong_callback_unset);
811 	tcase_add_test(tc, test_opt_llong_callback_unset_defval);
812 	tcase_add_test(tc, test_opt_llong_callback_range_in);
813 	tcase_add_test(tc, test_opt_llong_callback_range_below);
814 	tcase_add_test(tc, test_opt_llong_callback_range_above);
815 	tcase_add_test(tc, test_opt_llong_callback_range_boundary);
816 	tcase_add_test(tc, test_opt_int_callback_simple);
817 	tcase_add_test(tc, test_opt_int_callback_max);
818 	tcase_add_test(tc, test_opt_int_callback_min);
819 	tcase_add_test(tc, test_opt_int_callback_non_numeric);
820 	tcase_add_test(tc, test_opt_int_callback_non_numeric_suffix);
821 	tcase_add_test(tc, test_opt_int_callback_unset);
822 	tcase_add_test(tc, test_opt_int_callback_unset_defval);
823 	tcase_add_test(tc, test_opt_int_callback_range_in);
824 	tcase_add_test(tc, test_opt_int_callback_range_below);
825 	tcase_add_test(tc, test_opt_int_callback_range_above);
826 	tcase_add_test(tc, test_opt_int_callback_range_boundary);
827 	tcase_add_test(tc, test_opt_cpus_cb);
828 	tcase_add_exit_test(tc, test_opt_cpus_cb_invalid, EXIT_FAILURE);
829 	tcase_add_test(tc, test_opt_cgroup_cb);
830 	tcase_add_test(tc, test_opt_cgroup_cb_equals);
831 	tcase_add_test(tc, test_opt_cgroup_cb_unset);
832 	tcase_add_test(tc, test_opt_duration_cb);
833 	tcase_add_test(tc, test_opt_duration_cb_unset);
834 	tcase_add_exit_test(tc, test_opt_duration_cb_invalid, EXIT_FAILURE);
835 	tcase_add_test(tc, test_opt_event_cb);
836 	tcase_add_test(tc, test_opt_event_cb_multiple);
837 	tcase_add_test(tc, test_opt_housekeeping_cb);
838 	tcase_add_exit_test(tc, test_opt_housekeeping_cb_invalid, EXIT_FAILURE);
839 	tcase_add_test(tc, test_opt_housekeeping_cb_unset);
840 	tcase_add_test(tc, test_opt_priority_cb);
841 	tcase_add_exit_test(tc, test_opt_priority_cb_invalid, EXIT_FAILURE);
842 	tcase_add_test(tc, test_opt_priority_cb_unset);
843 	tcase_add_test(tc, test_opt_trigger_cb);
844 	tcase_add_exit_test(tc, test_opt_trigger_cb_no_event, EXIT_FAILURE);
845 	tcase_add_test(tc, test_opt_filter_cb);
846 	tcase_add_exit_test(tc, test_opt_filter_cb_no_event, EXIT_FAILURE);
847 	suite_add_tcase(s, tc);
848 
849 	tc = tcase_create("osnoise");
850 	tcase_add_test(tc, test_opt_osnoise_auto_cb);
851 	tcase_add_test(tc, test_opt_osnoise_auto_cb_unset);
852 	tcase_add_test(tc, test_opt_osnoise_trace_output_cb);
853 	tcase_add_test(tc, test_opt_osnoise_trace_output_cb_noarg);
854 	tcase_add_test(tc, test_opt_osnoise_trace_output_cb_unset);
855 	tcase_add_test(tc, test_opt_osnoise_on_threshold_cb);
856 	tcase_add_exit_test(tc, test_opt_osnoise_on_threshold_cb_invalid, EXIT_FAILURE);
857 	tcase_add_test(tc, test_opt_osnoise_on_end_cb);
858 	tcase_add_exit_test(tc, test_opt_osnoise_on_end_cb_invalid, EXIT_FAILURE);
859 	suite_add_tcase(s, tc);
860 
861 	tc = tcase_create("timerlat");
862 	tcase_add_test(tc, test_opt_timerlat_auto_cb);
863 	tcase_add_test(tc, test_opt_timerlat_auto_cb_unset);
864 	tcase_add_test(tc, test_opt_aa_only_cb);
865 	tcase_add_test(tc, test_opt_aa_only_cb_unset);
866 	tcase_add_test(tc, test_opt_timerlat_trace_output_cb);
867 	tcase_add_test(tc, test_opt_timerlat_trace_output_cb_noarg);
868 	tcase_add_test(tc, test_opt_timerlat_trace_output_cb_unset);
869 	tcase_add_test(tc, test_opt_timerlat_on_threshold_cb);
870 	tcase_add_exit_test(tc, test_opt_timerlat_on_threshold_cb_invalid, EXIT_FAILURE);
871 	tcase_add_test(tc, test_opt_timerlat_on_end_cb);
872 	tcase_add_exit_test(tc, test_opt_timerlat_on_end_cb_invalid, EXIT_FAILURE);
873 	tcase_add_test(tc, test_opt_user_threads_cb);
874 	tcase_add_test(tc, test_opt_user_threads_cb_unset);
875 	tcase_add_test(tc, test_opt_nano_cb);
876 	tcase_add_test(tc, test_opt_nano_cb_unset);
877 	tcase_add_test(tc, test_opt_stack_format_cb);
878 	tcase_add_exit_test(tc, test_opt_stack_format_cb_invalid, EXIT_FAILURE);
879 	tcase_add_test(tc, test_opt_stack_format_cb_unset);
880 	tcase_add_test(tc, test_opt_timerlat_align_cb);
881 	tcase_add_test(tc, test_opt_timerlat_align_cb_invalid);
882 	tcase_add_test(tc, test_opt_timerlat_align_cb_unset);
883 	suite_add_tcase(s, tc);
884 
885 	return s;
886 }
887