1 // SPDX-License-Identifier: GPL-2.0 2 3 #define _GNU_SOURCE 4 #include <check.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <sched.h> 8 #include <limits.h> 9 #include <unistd.h> 10 #include <sys/sysinfo.h> 11 12 #include <linux/container_of.h> 13 14 #include "cli_params_assert.h" 15 #include "../../src/cli.h" 16 17 #define PARSE_ARGS(...) char *argv[] = { __VA_ARGS__, NULL };\ 18 int argc = sizeof(argv) / sizeof(char *) - 1;\ 19 struct common_params *params =\ 20 timerlat_top_parse_args(argc, argv);\ 21 struct timerlat_params *tlat_params __maybe_unused =\ 22 to_timerlat_params(params) 23 24 /* Tracing Options */ 25 26 START_TEST(test_irq_short) 27 { 28 PARSE_ARGS("timerlat", "top", "-i", "20"); 29 30 ck_assert_int_eq(params->stop_us, 20); 31 } 32 END_TEST 33 34 START_TEST(test_irq_long) 35 { 36 PARSE_ARGS("timerlat", "top", "--irq", "20"); 37 38 ck_assert_int_eq(params->stop_us, 20); 39 } 40 END_TEST 41 42 START_TEST(test_period_short) 43 { 44 PARSE_ARGS("timerlat", "top", "-p", "200"); 45 46 ck_assert_int_eq(tlat_params->timerlat_period_us, 200); 47 } 48 END_TEST 49 50 START_TEST(test_period_long) 51 { 52 PARSE_ARGS("timerlat", "top", "--period", "200"); 53 54 ck_assert_int_eq(tlat_params->timerlat_period_us, 200); 55 } 56 END_TEST 57 58 START_TEST(test_period_unset_short) 59 { 60 PARSE_ARGS("timerlat", "top", "-p", "200", "--no-period"); 61 62 ck_assert_int_eq(tlat_params->timerlat_period_us, 0); 63 } 64 END_TEST 65 66 START_TEST(test_period_unset_long) 67 { 68 PARSE_ARGS("timerlat", "top", "--period", "200", "--no-period"); 69 70 ck_assert_int_eq(tlat_params->timerlat_period_us, 0); 71 } 72 END_TEST 73 74 START_TEST(test_stack_short) 75 { 76 PARSE_ARGS("timerlat", "top", "-s", "20"); 77 78 ck_assert_int_eq(tlat_params->print_stack, 20); 79 } 80 END_TEST 81 82 START_TEST(test_stack_long) 83 { 84 PARSE_ARGS("timerlat", "top", "--stack", "20"); 85 86 ck_assert_int_eq(tlat_params->print_stack, 20); 87 } 88 END_TEST 89 90 START_TEST(test_thread_short) 91 { 92 PARSE_ARGS("timerlat", "top", "-T", "20"); 93 94 ck_assert_int_eq(params->stop_total_us, 20); 95 } 96 END_TEST 97 98 START_TEST(test_thread_long) 99 { 100 PARSE_ARGS("timerlat", "top", "--thread", "20"); 101 102 ck_assert_int_eq(params->stop_total_us, 20); 103 } 104 END_TEST 105 106 /* Event Configuration */ 107 108 START_TEST(test_event_short) 109 { 110 PARSE_ARGS("timerlat", "top", "-e", "system:event"); 111 112 CLI_ASSERT_SINGLE_EVENT("system", "event"); 113 } 114 END_TEST 115 116 START_TEST(test_event_long) 117 { 118 PARSE_ARGS("timerlat", "top", "--event", "system:event"); 119 120 CLI_ASSERT_SINGLE_EVENT("system", "event"); 121 } 122 END_TEST 123 124 START_TEST(test_filter) 125 { 126 PARSE_ARGS("timerlat", "top", "-e", "system:event", "--filter", "filter"); 127 128 CLI_ASSERT_SINGLE_FILTER("filter"); 129 } 130 END_TEST 131 132 START_TEST(test_trigger) 133 { 134 PARSE_ARGS("timerlat", "top", "-e", "system:event", "--trigger", "trigger"); 135 136 CLI_ASSERT_SINGLE_TRIGGER("trigger"); 137 } 138 END_TEST 139 140 START_TEST(test_trace_short_noarg) 141 { 142 PARSE_ARGS("timerlat", "top", "-t"); 143 144 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 145 "timerlat_trace.txt"); 146 } 147 END_TEST 148 149 START_TEST(test_trace_short_followarg) 150 { 151 PARSE_ARGS("timerlat", "top", "-t", "-d", "20"); 152 153 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 154 "timerlat_trace.txt"); 155 ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */ 156 } 157 END_TEST 158 159 START_TEST(test_trace_short_space) 160 { 161 PARSE_ARGS("timerlat", "top", "-t", "tracefile"); 162 163 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 164 "tracefile"); 165 } 166 END_TEST 167 168 START_TEST(test_trace_short_equals) 169 { 170 PARSE_ARGS("timerlat", "top", "-t=tracefile"); 171 172 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 173 "tracefile"); 174 } 175 END_TEST 176 177 START_TEST(test_trace_long_noarg) 178 { 179 PARSE_ARGS("timerlat", "top", "--trace"); 180 181 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 182 "timerlat_trace.txt"); 183 } 184 END_TEST 185 186 START_TEST(test_trace_long_followarg) 187 { 188 PARSE_ARGS("timerlat", "top", "--trace", "-d", "20"); 189 190 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 191 "timerlat_trace.txt"); 192 ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */ 193 } 194 END_TEST 195 196 START_TEST(test_trace_long_space) 197 { 198 PARSE_ARGS("timerlat", "top", "--trace", "tracefile"); 199 200 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 201 "tracefile"); 202 } 203 END_TEST 204 205 START_TEST(test_trace_long_equals) 206 { 207 PARSE_ARGS("timerlat", "top", "--trace=tracefile"); 208 209 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 210 "tracefile"); 211 } 212 END_TEST 213 214 /* CPU Configuration */ 215 216 START_TEST(test_cpus_short) 217 { 218 nr_cpus = 4; 219 220 PARSE_ARGS("timerlat", "top", "-c", "0-1,3"); 221 222 ck_assert_str_eq(params->cpus, "0-1,3"); 223 CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3); 224 } 225 END_TEST 226 227 START_TEST(test_cpus_long) 228 { 229 nr_cpus = 4; 230 231 PARSE_ARGS("timerlat", "top", "--cpus", "0-1,3"); 232 233 ck_assert_str_eq(params->cpus, "0-1,3"); 234 CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3); 235 } 236 END_TEST 237 238 START_TEST(test_housekeeping_short) 239 { 240 nr_cpus = 4; 241 242 PARSE_ARGS("timerlat", "top", "-H", "0-1,3"); 243 244 CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3); 245 } 246 END_TEST 247 248 START_TEST(test_housekeeping_long) 249 { 250 nr_cpus = 4; 251 252 PARSE_ARGS("timerlat", "top", "--house-keeping", "0-1,3"); 253 254 CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3); 255 } 256 END_TEST 257 258 /* Thread Configuration */ 259 260 START_TEST(test_cgroup_short_noarg) 261 { 262 PARSE_ARGS("timerlat", "top", "-C"); 263 264 ck_assert(params->cgroup); 265 ck_assert_ptr_null(params->cgroup_name); 266 } 267 END_TEST 268 269 START_TEST(test_cgroup_short_space) 270 { 271 PARSE_ARGS("timerlat", "top", "-C", "cgroup"); 272 273 ck_assert(params->cgroup); 274 ck_assert_str_eq(params->cgroup_name, "cgroup"); 275 } 276 END_TEST 277 278 START_TEST(test_cgroup_short_equals) 279 { 280 PARSE_ARGS("timerlat", "top", "-C=cgroup"); 281 282 ck_assert(params->cgroup); 283 ck_assert_str_eq(params->cgroup_name, "cgroup"); 284 } 285 END_TEST 286 287 START_TEST(test_cgroup_long_noarg) 288 { 289 PARSE_ARGS("timerlat", "top", "--cgroup"); 290 291 ck_assert(params->cgroup); 292 ck_assert_ptr_null(params->cgroup_name); 293 } 294 END_TEST 295 296 START_TEST(test_cgroup_long_space) 297 { 298 PARSE_ARGS("timerlat", "top", "--cgroup", "cgroup"); 299 300 ck_assert(params->cgroup); 301 ck_assert_str_eq(params->cgroup_name, "cgroup"); 302 } 303 END_TEST 304 305 START_TEST(test_cgroup_long_equals) 306 { 307 PARSE_ARGS("timerlat", "top", "--cgroup=cgroup"); 308 309 ck_assert(params->cgroup); 310 ck_assert_str_eq(params->cgroup_name, "cgroup"); 311 } 312 END_TEST 313 314 START_TEST(test_kernel_threads_short) 315 { 316 PARSE_ARGS("timerlat", "top", "-k"); 317 318 ck_assert(params->kernel_workload); 319 ck_assert(!params->user_workload); 320 ck_assert(!params->user_data); 321 } 322 END_TEST 323 324 START_TEST(test_kernel_threads_long) 325 { 326 PARSE_ARGS("timerlat", "top", "--kernel-threads"); 327 328 ck_assert(params->kernel_workload); 329 ck_assert(!params->user_workload); 330 ck_assert(!params->user_data); 331 } 332 END_TEST 333 334 START_TEST(test_priority_short) 335 { 336 PARSE_ARGS("timerlat", "top", "-P", "f:95"); 337 338 ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO); 339 ck_assert_int_eq(params->sched_param.sched_priority, 95); 340 } 341 END_TEST 342 343 START_TEST(test_priority_long) 344 { 345 PARSE_ARGS("timerlat", "top", "--priority", "f:95"); 346 347 ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO); 348 ck_assert_int_eq(params->sched_param.sched_priority, 95); 349 } 350 END_TEST 351 352 START_TEST(test_user_load_short) 353 { 354 PARSE_ARGS("timerlat", "top", "-U"); 355 356 ck_assert(!params->kernel_workload); 357 ck_assert(!params->user_workload); 358 ck_assert(params->user_data); 359 } 360 END_TEST 361 362 START_TEST(test_user_load_long) 363 { 364 PARSE_ARGS("timerlat", "top", "--user-load"); 365 366 ck_assert(!params->kernel_workload); 367 ck_assert(!params->user_workload); 368 ck_assert(params->user_data); 369 } 370 END_TEST 371 372 START_TEST(test_user_threads_short) 373 { 374 PARSE_ARGS("timerlat", "top", "-u"); 375 376 ck_assert(!params->kernel_workload); 377 ck_assert(params->user_workload); 378 ck_assert(params->user_data); 379 } 380 END_TEST 381 382 START_TEST(test_user_threads_long) 383 { 384 PARSE_ARGS("timerlat", "top", "--user-threads"); 385 386 ck_assert(!params->kernel_workload); 387 ck_assert(params->user_workload); 388 ck_assert(params->user_data); 389 } 390 END_TEST 391 392 START_TEST(test_aligned_short) 393 { 394 PARSE_ARGS("timerlat", "top", "-A", "500"); 395 396 ck_assert(tlat_params->timerlat_align); 397 ck_assert_int_eq(tlat_params->timerlat_align_us, 500); 398 } 399 END_TEST 400 401 START_TEST(test_aligned_long) 402 { 403 PARSE_ARGS("timerlat", "top", "--aligned", "500"); 404 405 ck_assert(tlat_params->timerlat_align); 406 ck_assert_int_eq(tlat_params->timerlat_align_us, 500); 407 } 408 END_TEST 409 410 /* Output */ 411 412 START_TEST(test_nano_short) 413 { 414 PARSE_ARGS("timerlat", "top", "-n"); 415 416 ck_assert_int_eq(params->output_divisor, 1); 417 } 418 END_TEST 419 420 START_TEST(test_nano_long) 421 { 422 PARSE_ARGS("timerlat", "top", "--nano"); 423 424 ck_assert_int_eq(params->output_divisor, 1); 425 } 426 END_TEST 427 428 START_TEST(test_quiet_short) 429 { 430 PARSE_ARGS("timerlat", "top", "-q"); 431 432 ck_assert(params->quiet); 433 } 434 END_TEST 435 436 START_TEST(test_quiet_long) 437 { 438 PARSE_ARGS("timerlat", "top", "--quiet"); 439 440 ck_assert(params->quiet); 441 } 442 END_TEST 443 444 /* System Tuning */ 445 446 START_TEST(test_deepest_idle_state) 447 { 448 PARSE_ARGS("timerlat", "top", "--deepest-idle-state", "1"); 449 450 ck_assert_int_eq(tlat_params->deepest_idle_state, 1); 451 } 452 END_TEST 453 454 START_TEST(test_dma_latency) 455 { 456 PARSE_ARGS("timerlat", "top", "--dma-latency", "10"); 457 458 ck_assert_int_eq(tlat_params->dma_latency, 10); 459 } 460 END_TEST 461 462 START_TEST(test_trace_buffer_size) 463 { 464 PARSE_ARGS("timerlat", "top", "--trace-buffer-size", "200"); 465 466 ck_assert_int_eq(params->buffer_size, 200); 467 } 468 END_TEST 469 470 START_TEST(test_warm_up) 471 { 472 PARSE_ARGS("timerlat", "top", "--warm-up", "5"); 473 474 ck_assert_int_eq(params->warmup, 5); 475 } 476 END_TEST 477 478 /* Auto Analysis and Actions */ 479 480 START_TEST(test_auto) 481 { 482 PARSE_ARGS("timerlat", "top", "-a", "20"); 483 484 CLI_TIMERLAT_ASSERT_AUTO(20); 485 } 486 END_TEST 487 488 START_TEST(test_aa_only) 489 { 490 PARSE_ARGS("timerlat", "top", "--aa-only", "20"); 491 492 CLI_TIMERLAT_ASSERT_AA_ONLY(20); 493 } 494 END_TEST 495 496 START_TEST(test_bpf_action) 497 { 498 PARSE_ARGS("timerlat", "top", "--bpf-action", "program"); 499 500 ck_assert_str_eq(tlat_params->bpf_action_program, "program"); 501 } 502 END_TEST 503 504 START_TEST(test_dump_tasks) 505 { 506 PARSE_ARGS("timerlat", "top", "--dump-tasks"); 507 508 ck_assert(tlat_params->dump_tasks); 509 } 510 END_TEST 511 512 START_TEST(test_no_aa) 513 { 514 PARSE_ARGS("timerlat", "top", "--no-aa"); 515 516 ck_assert(tlat_params->no_aa); 517 } 518 END_TEST 519 520 START_TEST(test_on_end) 521 { 522 PARSE_ARGS("timerlat", "top", "--on-end", "trace"); 523 524 CLI_ASSERT_SINGLE_ACTION(end_actions, ACTION_TRACE_OUTPUT, trace_output, str, 525 "timerlat_trace.txt"); 526 } 527 END_TEST 528 529 START_TEST(test_on_threshold) 530 { 531 PARSE_ARGS("timerlat", "top", "--on-threshold", "trace"); 532 533 CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str, 534 "timerlat_trace.txt"); 535 } 536 END_TEST 537 538 START_TEST(test_stack_format) 539 { 540 PARSE_ARGS("timerlat", "top", "--stack-format", "truncate"); 541 542 ck_assert_int_eq(tlat_params->stack_format, STACK_FORMAT_TRUNCATE); 543 } 544 END_TEST 545 546 /* General */ 547 548 START_TEST(test_debug_short) 549 { 550 PARSE_ARGS("timerlat", "top", "-D"); 551 552 ck_assert(config_debug); 553 } 554 END_TEST 555 556 START_TEST(test_debug_long) 557 { 558 PARSE_ARGS("timerlat", "top", "--debug"); 559 560 ck_assert(config_debug); 561 } 562 END_TEST 563 564 START_TEST(test_duration_short) 565 { 566 PARSE_ARGS("timerlat", "top", "-d", "1m"); 567 568 ck_assert_int_eq(params->duration, 60); 569 } 570 END_TEST 571 572 START_TEST(test_duration_long) 573 { 574 PARSE_ARGS("timerlat", "top", "--duration", "1m"); 575 576 ck_assert_int_eq(params->duration, 60); 577 } 578 END_TEST 579 580 Suite *timerlat_top_cli_suite(void) 581 { 582 Suite *s = suite_create("timerlat_top_cli"); 583 TCase *tc; 584 585 tc = tcase_create("tracing_options"); 586 tcase_add_test(tc, test_irq_short); 587 tcase_add_test(tc, test_irq_long); 588 tcase_add_test(tc, test_period_short); 589 tcase_add_test(tc, test_period_long); 590 tcase_add_test(tc, test_period_unset_short); 591 tcase_add_test(tc, test_period_unset_long); 592 tcase_add_test(tc, test_stack_short); 593 tcase_add_test(tc, test_stack_long); 594 tcase_add_test(tc, test_thread_short); 595 tcase_add_test(tc, test_thread_long); 596 tcase_add_test(tc, test_trace_short_noarg); 597 tcase_add_test(tc, test_trace_short_followarg); 598 tcase_add_test(tc, test_trace_short_space); 599 tcase_add_test(tc, test_trace_short_equals); 600 tcase_add_test(tc, test_trace_long_noarg); 601 tcase_add_test(tc, test_trace_long_followarg); 602 tcase_add_test(tc, test_trace_long_space); 603 tcase_add_test(tc, test_trace_long_equals); 604 suite_add_tcase(s, tc); 605 606 tc = tcase_create("event_configuration"); 607 tcase_add_test(tc, test_event_short); 608 tcase_add_test(tc, test_event_long); 609 tcase_add_test(tc, test_filter); 610 tcase_add_test(tc, test_trigger); 611 suite_add_tcase(s, tc); 612 613 tc = tcase_create("cpu_configuration"); 614 tcase_add_test(tc, test_cpus_short); 615 tcase_add_test(tc, test_cpus_long); 616 tcase_add_test(tc, test_housekeeping_short); 617 tcase_add_test(tc, test_housekeeping_long); 618 suite_add_tcase(s, tc); 619 620 tc = tcase_create("thread_configuration"); 621 tcase_add_test(tc, test_cgroup_short_noarg); 622 tcase_add_test(tc, test_cgroup_short_space); 623 tcase_add_test(tc, test_cgroup_short_equals); 624 tcase_add_test(tc, test_cgroup_long_noarg); 625 tcase_add_test(tc, test_cgroup_long_space); 626 tcase_add_test(tc, test_cgroup_long_equals); 627 tcase_add_test(tc, test_kernel_threads_short); 628 tcase_add_test(tc, test_kernel_threads_long); 629 tcase_add_test(tc, test_priority_short); 630 tcase_add_test(tc, test_priority_long); 631 tcase_add_test(tc, test_user_load_short); 632 tcase_add_test(tc, test_user_load_long); 633 tcase_add_test(tc, test_user_threads_short); 634 tcase_add_test(tc, test_user_threads_long); 635 tcase_add_test(tc, test_aligned_short); 636 tcase_add_test(tc, test_aligned_long); 637 suite_add_tcase(s, tc); 638 639 tc = tcase_create("output"); 640 tcase_add_test(tc, test_nano_short); 641 tcase_add_test(tc, test_nano_long); 642 tcase_add_test(tc, test_quiet_short); 643 tcase_add_test(tc, test_quiet_long); 644 suite_add_tcase(s, tc); 645 646 tc = tcase_create("system_tuning"); 647 tcase_add_test(tc, test_deepest_idle_state); 648 tcase_add_test(tc, test_dma_latency); 649 tcase_add_test(tc, test_trace_buffer_size); 650 tcase_add_test(tc, test_warm_up); 651 suite_add_tcase(s, tc); 652 653 tc = tcase_create("aa_actions"); 654 tcase_add_test(tc, test_auto); 655 tcase_add_test(tc, test_aa_only); 656 tcase_add_test(tc, test_bpf_action); 657 tcase_add_test(tc, test_dump_tasks); 658 tcase_add_test(tc, test_no_aa); 659 tcase_add_test(tc, test_on_end); 660 tcase_add_test(tc, test_on_threshold); 661 tcase_add_test(tc, test_stack_format); 662 suite_add_tcase(s, tc); 663 664 tc = tcase_create("general"); 665 tcase_add_test(tc, test_debug_short); 666 tcase_add_test(tc, test_debug_long); 667 tcase_add_test(tc, test_duration_short); 668 tcase_add_test(tc, test_duration_long); 669 suite_add_tcase(s, tc); 670 671 return s; 672 } 673