1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2945aea22SJiri Olsa /* 3945aea22SJiri Olsa * builtin-test.c 4945aea22SJiri Olsa * 5945aea22SJiri Olsa * Builtin regression testing command: ever growing number of sanity tests 6945aea22SJiri Olsa */ 7c23c2a0fSArnaldo Carvalho de Melo #include <fcntl.h> 8a43783aeSArnaldo Carvalho de Melo #include <errno.h> 90d8a5faaSJiri Olsa #include <unistd.h> 100d8a5faaSJiri Olsa #include <string.h> 11f2a39fe8SArnaldo Carvalho de Melo #include <stdlib.h> 121209b273SArnaldo Carvalho de Melo #include <sys/types.h> 131209b273SArnaldo Carvalho de Melo #include <dirent.h> 144208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 151209b273SArnaldo Carvalho de Melo #include <sys/stat.h> 16945aea22SJiri Olsa #include "builtin.h" 17a635fc51SArnaldo Carvalho de Melo #include "hist.h" 182ae82878SArnaldo Carvalho de Melo #include "intlist.h" 190a4e1ae6SJiri Olsa #include "tests.h" 20c81251e8SJiri Olsa #include "debug.h" 21c81251e8SJiri Olsa #include "color.h" 224b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 231209b273SArnaldo Carvalho de Melo #include "string2.h" 24c81251e8SJiri Olsa #include "symbol.h" 25d3280ce0SArnaldo Carvalho de Melo #include "util/rlimit.h" 26877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 273ca43b60SArnaldo Carvalho de Melo #include <linux/string.h> 281209b273SArnaldo Carvalho de Melo #include <subcmd/exec-cmd.h> 29eb7261f1SRiccardo Mancini #include <linux/zalloc.h> 30945aea22SJiri Olsa 317fa9b8fbSJiri Olsa static bool dont_fork; 327fa9b8fbSJiri Olsa 33*df225205SIan Rogers struct test *__weak arch_tests[] = { 34*df225205SIan Rogers NULL, 3531b6753fSMatt Fleming }; 3631b6753fSMatt Fleming 37*df225205SIan Rogers DEFINE_SUITE("vmlinux symtab matches kallsyms", vmlinux_matches_kallsyms); 38*df225205SIan Rogers DEFINE_SUITE("Detect openat syscall event", openat_syscall_event); 39*df225205SIan Rogers DEFINE_SUITE("Detect openat syscall event on all cpus", openat_syscall_event_on_all_cpus); 40*df225205SIan Rogers DEFINE_SUITE("Read samples using the mmap interface", basic_mmap); 41*df225205SIan Rogers DEFINE_SUITE("Test data source output", mem); 42*df225205SIan Rogers DEFINE_SUITE("Parse event definition strings", parse_events); 43*df225205SIan Rogers DEFINE_SUITE("Simple expression parser", expr); 44*df225205SIan Rogers DEFINE_SUITE("PERF_RECORD_* events & perf_sample fields", PERF_RECORD); 45*df225205SIan Rogers DEFINE_SUITE("Parse perf pmu format", pmu); 46*df225205SIan Rogers static struct test pmu_events = { 47a6c925fdSJohn Garry .desc = "PMU events", 48a6c925fdSJohn Garry .func = test__pmu_events, 4906392aaaSIan Rogers .subtest = { 5006392aaaSIan Rogers .skip_if_fail = false, 5106392aaaSIan Rogers .get_nr = test__pmu_events_subtest_get_nr, 5206392aaaSIan Rogers .get_desc = test__pmu_events_subtest_get_desc, 5306392aaaSIan Rogers .skip_reason = test__pmu_events_subtest_skip_reason, 5406392aaaSIan Rogers }, 55*df225205SIan Rogers }; 56*df225205SIan Rogers DEFINE_SUITE("DSO data read", dso_data); 57*df225205SIan Rogers DEFINE_SUITE("DSO data cache", dso_data_cache); 58*df225205SIan Rogers DEFINE_SUITE("DSO data reopen", dso_data_reopen); 59*df225205SIan Rogers DEFINE_SUITE("Roundtrip evsel->name", perf_evsel__roundtrip_name_test); 60*df225205SIan Rogers DEFINE_SUITE("Parse sched tracepoints fields", perf_evsel__tp_sched_test); 61*df225205SIan Rogers DEFINE_SUITE("syscalls:sys_enter_openat event fields", syscall_openat_tp_fields); 62*df225205SIan Rogers DEFINE_SUITE("Setup struct perf_event_attr", attr); 63*df225205SIan Rogers DEFINE_SUITE("Match and link multiple hists", hists_link); 64*df225205SIan Rogers DEFINE_SUITE("'import perf' in python", python_use); 65*df225205SIan Rogers static struct test bp_signal = { 66030910c0SArnaldo Carvalho de Melo .desc = "Breakpoint overflow signal handler", 675a6bef47SJiri Olsa .func = test__bp_signal, 68598762cfSJiri Olsa .is_supported = test__bp_signal_is_supported, 69*df225205SIan Rogers }; 70*df225205SIan Rogers static struct test bp_signal_overflow = { 71030910c0SArnaldo Carvalho de Melo .desc = "Breakpoint overflow sampling", 7206933e3aSJiri Olsa .func = test__bp_signal_overflow, 73598762cfSJiri Olsa .is_supported = test__bp_signal_is_supported, 74*df225205SIan Rogers }; 75*df225205SIan Rogers static struct test bp_accounting = { 76032db28eSJiri Olsa .desc = "Breakpoint accounting", 77032db28eSJiri Olsa .func = test__bp_accounting, 78e533eadfSLeo Yan .is_supported = test__bp_account_is_supported, 79*df225205SIan Rogers }; 80*df225205SIan Rogers static struct test wp = { 812e85d597SRavi Bangoria .desc = "Watchpoint", 822e85d597SRavi Bangoria .func = test__wp, 830e24147dSThomas Richter .is_supported = test__wp_is_supported, 842e85d597SRavi Bangoria .subtest = { 852e85d597SRavi Bangoria .skip_if_fail = false, 862e85d597SRavi Bangoria .get_nr = test__wp_subtest_get_nr, 872e85d597SRavi Bangoria .get_desc = test__wp_subtest_get_desc, 88cc3b964dSTommi Rantala .skip_reason = test__wp_subtest_skip_reason, 892e85d597SRavi Bangoria }, 90*df225205SIan Rogers }; 91*df225205SIan Rogers DEFINE_SUITE("Number of exit events of a simple workload", task_exit); 92*df225205SIan Rogers DEFINE_SUITE("Software clock events period values", sw_clock_freq); 93*df225205SIan Rogers DEFINE_SUITE("Object code reading", code_reading); 94*df225205SIan Rogers DEFINE_SUITE("Sample parsing", sample_parsing); 95*df225205SIan Rogers DEFINE_SUITE("Use a dummy software event to keep tracking", keep_tracking); 96*df225205SIan Rogers DEFINE_SUITE("Parse with no sample_id_all bit set", parse_no_sample_id_all); 97*df225205SIan Rogers DEFINE_SUITE("Filter hist entries", hists_filter); 98*df225205SIan Rogers DEFINE_SUITE("Lookup mmap thread", mmap_thread_lookup); 99*df225205SIan Rogers DEFINE_SUITE("Share thread maps", thread_maps_share); 100*df225205SIan Rogers DEFINE_SUITE("Sort output of hist entries", hists_output); 101*df225205SIan Rogers DEFINE_SUITE("Cumulate child hist entries", hists_cumulate); 102*df225205SIan Rogers DEFINE_SUITE("Track with sched_switch", switch_tracking); 103*df225205SIan Rogers DEFINE_SUITE("Filter fds with revents mask in a fdarray", fdarray__filter); 104*df225205SIan Rogers DEFINE_SUITE("Add fd to a fdarray, making it autogrow", fdarray__add); 105*df225205SIan Rogers DEFINE_SUITE("kmod_path__parse", kmod_path__parse); 106*df225205SIan Rogers DEFINE_SUITE("Thread map", thread_map); 107*df225205SIan Rogers static struct test llvm = { 108030910c0SArnaldo Carvalho de Melo .desc = "LLVM search and compile", 1099bc898c7SWang Nan .func = test__llvm, 110e8c6d500SWang Nan .subtest = { 111e8c6d500SWang Nan .skip_if_fail = true, 112e8c6d500SWang Nan .get_nr = test__llvm_subtest_get_nr, 113e8c6d500SWang Nan .get_desc = test__llvm_subtest_get_desc, 114e8c6d500SWang Nan }, 115*df225205SIan Rogers }; 116*df225205SIan Rogers DEFINE_SUITE("Session topology", session_topology); 117*df225205SIan Rogers static struct test bpf = { 118030910c0SArnaldo Carvalho de Melo .desc = "BPF filter", 119ba1fae43SWang Nan .func = test__bpf, 12077a0cf68SWang Nan .subtest = { 12177a0cf68SWang Nan .skip_if_fail = true, 12277a0cf68SWang Nan .get_nr = test__bpf_subtest_get_nr, 12377a0cf68SWang Nan .get_desc = test__bpf_subtest_get_desc, 12477a0cf68SWang Nan }, 125*df225205SIan Rogers }; 126*df225205SIan Rogers DEFINE_SUITE("Synthesize thread map", thread_map_synthesize); 127*df225205SIan Rogers DEFINE_SUITE("Remove thread map", thread_map_remove); 128*df225205SIan Rogers DEFINE_SUITE("Synthesize cpu map", cpu_map_synthesize); 129*df225205SIan Rogers DEFINE_SUITE("Synthesize stat config", synthesize_stat_config); 130*df225205SIan Rogers DEFINE_SUITE("Synthesize stat", synthesize_stat); 131*df225205SIan Rogers DEFINE_SUITE("Synthesize stat round", synthesize_stat_round); 132*df225205SIan Rogers DEFINE_SUITE("Synthesize attr update", event_update); 133*df225205SIan Rogers DEFINE_SUITE("Event times", event_times); 134*df225205SIan Rogers DEFINE_SUITE("Read backward ring buffer", backward_ring_buffer); 135*df225205SIan Rogers DEFINE_SUITE("Print cpu map", cpu_map_print); 136*df225205SIan Rogers DEFINE_SUITE("Merge cpu map", cpu_map_merge); 137*df225205SIan Rogers DEFINE_SUITE("Probe SDT events", sdt_event); 138*df225205SIan Rogers DEFINE_SUITE("is_printable_array", is_printable_array); 139*df225205SIan Rogers DEFINE_SUITE("Print bitmap", bitmap_print); 140*df225205SIan Rogers DEFINE_SUITE("perf hooks", perf_hooks); 141*df225205SIan Rogers static struct test clang = { 14200b86691SWang Nan .desc = "builtin clang support", 14300b86691SWang Nan .func = test__clang, 14400b86691SWang Nan .subtest = { 14500b86691SWang Nan .skip_if_fail = true, 14600b86691SWang Nan .get_nr = test__clang_subtest_get_nr, 14700b86691SWang Nan .get_desc = test__clang_subtest_get_desc, 14800b86691SWang Nan } 149*df225205SIan Rogers }; 150*df225205SIan Rogers DEFINE_SUITE("unit_number__scnprintf", unit_number__scnprint); 151*df225205SIan Rogers DEFINE_SUITE("mem2node", mem2node); 152*df225205SIan Rogers DEFINE_SUITE("time utils", time_utils); 153*df225205SIan Rogers DEFINE_SUITE("Test jit_write_elf", jit_write_elf); 154*df225205SIan Rogers static struct test pfm = { 15570943490SStephane Eranian .desc = "Test libpfm4 support", 15670943490SStephane Eranian .func = test__pfm, 15770943490SStephane Eranian .subtest = { 15870943490SStephane Eranian .skip_if_fail = true, 15970943490SStephane Eranian .get_nr = test__pfm_subtest_get_nr, 16070943490SStephane Eranian .get_desc = test__pfm_subtest_get_desc, 16170943490SStephane Eranian } 162*df225205SIan Rogers }; 163*df225205SIan Rogers DEFINE_SUITE("Test api io", api_io); 164*df225205SIan Rogers DEFINE_SUITE("maps__merge_in", maps__merge_in); 165*df225205SIan Rogers DEFINE_SUITE("Demangle Java", demangle_java); 166*df225205SIan Rogers DEFINE_SUITE("Demangle OCaml", demangle_ocaml); 167*df225205SIan Rogers DEFINE_SUITE("Parse and process metrics", parse_metric); 168*df225205SIan Rogers DEFINE_SUITE("PE file support", pe_file_parsing); 169*df225205SIan Rogers DEFINE_SUITE("Event expansion for cgroups", expand_cgroup_events); 170*df225205SIan Rogers static struct test perf_time_to_tsc = { 1713989bbf9SLeo Yan .desc = "Convert perf time to TSC", 1723989bbf9SLeo Yan .func = test__perf_time_to_tsc, 173248dd9b5SLeo Yan .is_supported = test__tsc_is_supported, 174*df225205SIan Rogers }; 175*df225205SIan Rogers DEFINE_SUITE("dlfilter C API", dlfilter); 176*df225205SIan Rogers 177*df225205SIan Rogers 178*df225205SIan Rogers static struct test *generic_tests[] = { 179*df225205SIan Rogers &vmlinux_matches_kallsyms, 180*df225205SIan Rogers &openat_syscall_event, 181*df225205SIan Rogers &openat_syscall_event_on_all_cpus, 182*df225205SIan Rogers &basic_mmap, 183*df225205SIan Rogers &mem, 184*df225205SIan Rogers &parse_events, 185*df225205SIan Rogers &expr, 186*df225205SIan Rogers &PERF_RECORD, 187*df225205SIan Rogers &pmu, 188*df225205SIan Rogers &pmu_events, 189*df225205SIan Rogers &dso_data, 190*df225205SIan Rogers &dso_data_cache, 191*df225205SIan Rogers &dso_data_reopen, 192*df225205SIan Rogers &perf_evsel__roundtrip_name_test, 193*df225205SIan Rogers &perf_evsel__tp_sched_test, 194*df225205SIan Rogers &syscall_openat_tp_fields, 195*df225205SIan Rogers &attr, 196*df225205SIan Rogers &hists_link, 197*df225205SIan Rogers &python_use, 198*df225205SIan Rogers &bp_signal, 199*df225205SIan Rogers &bp_signal_overflow, 200*df225205SIan Rogers &bp_accounting, 201*df225205SIan Rogers &wp, 202*df225205SIan Rogers &task_exit, 203*df225205SIan Rogers &sw_clock_freq, 204*df225205SIan Rogers &code_reading, 205*df225205SIan Rogers &sample_parsing, 206*df225205SIan Rogers &keep_tracking, 207*df225205SIan Rogers &parse_no_sample_id_all, 208*df225205SIan Rogers &hists_filter, 209*df225205SIan Rogers &mmap_thread_lookup, 210*df225205SIan Rogers &thread_maps_share, 211*df225205SIan Rogers &hists_output, 212*df225205SIan Rogers &hists_cumulate, 213*df225205SIan Rogers &switch_tracking, 214*df225205SIan Rogers &fdarray__filter, 215*df225205SIan Rogers &fdarray__add, 216*df225205SIan Rogers &kmod_path__parse, 217*df225205SIan Rogers &thread_map, 218*df225205SIan Rogers &llvm, 219*df225205SIan Rogers &session_topology, 220*df225205SIan Rogers &bpf, 221*df225205SIan Rogers &thread_map_synthesize, 222*df225205SIan Rogers &thread_map_remove, 223*df225205SIan Rogers &cpu_map_synthesize, 224*df225205SIan Rogers &synthesize_stat_config, 225*df225205SIan Rogers &synthesize_stat, 226*df225205SIan Rogers &synthesize_stat_round, 227*df225205SIan Rogers &event_update, 228*df225205SIan Rogers &event_times, 229*df225205SIan Rogers &backward_ring_buffer, 230*df225205SIan Rogers &cpu_map_print, 231*df225205SIan Rogers &cpu_map_merge, 232*df225205SIan Rogers &sdt_event, 233*df225205SIan Rogers &is_printable_array, 234*df225205SIan Rogers &bitmap_print, 235*df225205SIan Rogers &perf_hooks, 236*df225205SIan Rogers &clang, 237*df225205SIan Rogers &unit_number__scnprint, 238*df225205SIan Rogers &mem2node, 239*df225205SIan Rogers &time_utils, 240*df225205SIan Rogers &jit_write_elf, 241*df225205SIan Rogers &pfm, 242*df225205SIan Rogers &api_io, 243*df225205SIan Rogers &maps__merge_in, 244*df225205SIan Rogers &demangle_java, 245*df225205SIan Rogers &demangle_ocaml, 246*df225205SIan Rogers &parse_metric, 247*df225205SIan Rogers &pe_file_parsing, 248*df225205SIan Rogers &expand_cgroup_events, 249*df225205SIan Rogers &perf_time_to_tsc, 250*df225205SIan Rogers &dlfilter, 251*df225205SIan Rogers NULL, 252945aea22SJiri Olsa }; 253945aea22SJiri Olsa 254*df225205SIan Rogers static struct test **tests[] = { 25531b6753fSMatt Fleming generic_tests, 25631b6753fSMatt Fleming arch_tests, 25731b6753fSMatt Fleming }; 25831b6753fSMatt Fleming 259d685e6c1SJiri Olsa static bool perf_test__matches(const char *desc, int curr, int argc, const char *argv[]) 260945aea22SJiri Olsa { 261945aea22SJiri Olsa int i; 262945aea22SJiri Olsa 263945aea22SJiri Olsa if (argc == 0) 264945aea22SJiri Olsa return true; 265945aea22SJiri Olsa 266945aea22SJiri Olsa for (i = 0; i < argc; ++i) { 267945aea22SJiri Olsa char *end; 268945aea22SJiri Olsa long nr = strtoul(argv[i], &end, 10); 269945aea22SJiri Olsa 270945aea22SJiri Olsa if (*end == '\0') { 271945aea22SJiri Olsa if (nr == curr + 1) 272945aea22SJiri Olsa return true; 273945aea22SJiri Olsa continue; 274945aea22SJiri Olsa } 275945aea22SJiri Olsa 276d685e6c1SJiri Olsa if (strcasestr(desc, argv[i])) 277945aea22SJiri Olsa return true; 278945aea22SJiri Olsa } 279945aea22SJiri Olsa 280945aea22SJiri Olsa return false; 281945aea22SJiri Olsa } 282945aea22SJiri Olsa 283721a1f53SArnaldo Carvalho de Melo static int run_test(struct test *test, int subtest) 2840d8a5faaSJiri Olsa { 2857fa9b8fbSJiri Olsa int status, err = -1, child = dont_fork ? 0 : fork(); 286ba3dfff8SMasami Hiramatsu char sbuf[STRERR_BUFSIZE]; 2870d8a5faaSJiri Olsa 2880d8a5faaSJiri Olsa if (child < 0) { 289ba3dfff8SMasami Hiramatsu pr_err("failed to fork test: %s\n", 290c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, sbuf, sizeof(sbuf))); 2910d8a5faaSJiri Olsa return -1; 2920d8a5faaSJiri Olsa } 2930d8a5faaSJiri Olsa 2940d8a5faaSJiri Olsa if (!child) { 2957fa9b8fbSJiri Olsa if (!dont_fork) { 2960d8a5faaSJiri Olsa pr_debug("test child forked, pid %d\n", getpid()); 2977fa9b8fbSJiri Olsa 298bb963e16SNamhyung Kim if (verbose <= 0) { 2995bcf2fe0SWang Nan int nullfd = open("/dev/null", O_WRONLY); 3007fa9b8fbSJiri Olsa 3015bcf2fe0SWang Nan if (nullfd >= 0) { 3025bcf2fe0SWang Nan close(STDERR_FILENO); 3035bcf2fe0SWang Nan close(STDOUT_FILENO); 3045bcf2fe0SWang Nan 3055bcf2fe0SWang Nan dup2(nullfd, STDOUT_FILENO); 3065bcf2fe0SWang Nan dup2(STDOUT_FILENO, STDERR_FILENO); 3075bcf2fe0SWang Nan close(nullfd); 3085bcf2fe0SWang Nan } 309b6847d2cSArnaldo Carvalho de Melo } else { 310b6847d2cSArnaldo Carvalho de Melo signal(SIGSEGV, sighandler_dump_stack); 311b6847d2cSArnaldo Carvalho de Melo signal(SIGFPE, sighandler_dump_stack); 3125bcf2fe0SWang Nan } 3137fa9b8fbSJiri Olsa } 3145bcf2fe0SWang Nan 31581f17c90SArnaldo Carvalho de Melo err = test->func(test, subtest); 3167fa9b8fbSJiri Olsa if (!dont_fork) 3170d8a5faaSJiri Olsa exit(err); 3180d8a5faaSJiri Olsa } 3190d8a5faaSJiri Olsa 3207fa9b8fbSJiri Olsa if (!dont_fork) { 3210d8a5faaSJiri Olsa wait(&status); 3220d8a5faaSJiri Olsa 3230d8a5faaSJiri Olsa if (WIFEXITED(status)) { 324189c466fSHe Kuang err = (signed char)WEXITSTATUS(status); 3250d8a5faaSJiri Olsa pr_debug("test child finished with %d\n", err); 3260d8a5faaSJiri Olsa } else if (WIFSIGNALED(status)) { 3270d8a5faaSJiri Olsa err = -1; 3280d8a5faaSJiri Olsa pr_debug("test child interrupted\n"); 3290d8a5faaSJiri Olsa } 3307fa9b8fbSJiri Olsa } 3310d8a5faaSJiri Olsa 3320d8a5faaSJiri Olsa return err; 3330d8a5faaSJiri Olsa } 3340d8a5faaSJiri Olsa 335*df225205SIan Rogers #define for_each_test(j, k, t) \ 33631b6753fSMatt Fleming for (j = 0; j < ARRAY_SIZE(tests); j++) \ 337*df225205SIan Rogers for (k = 0, t = tests[j][k]; tests[j][k]; k++, t = tests[j][k]) 338e8210cefSMatt Fleming 339e8c6d500SWang Nan static int test_and_print(struct test *t, bool force_skip, int subtest) 340e8c6d500SWang Nan { 341e8c6d500SWang Nan int err; 342e8c6d500SWang Nan 343e8c6d500SWang Nan if (!force_skip) { 344e8c6d500SWang Nan pr_debug("\n--- start ---\n"); 345e8c6d500SWang Nan err = run_test(t, subtest); 346e8c6d500SWang Nan pr_debug("---- end ----\n"); 347e8c6d500SWang Nan } else { 348e8c6d500SWang Nan pr_debug("\n--- force skipped ---\n"); 349e8c6d500SWang Nan err = TEST_SKIP; 350e8c6d500SWang Nan } 351e8c6d500SWang Nan 352e8c6d500SWang Nan if (!t->subtest.get_nr) 353e8c6d500SWang Nan pr_debug("%s:", t->desc); 354e8c6d500SWang Nan else 355aa90f9f9SSandipan Das pr_debug("%s subtest %d:", t->desc, subtest + 1); 356e8c6d500SWang Nan 357e8c6d500SWang Nan switch (err) { 358e8c6d500SWang Nan case TEST_OK: 359e8c6d500SWang Nan pr_info(" Ok\n"); 360e8c6d500SWang Nan break; 3613b536651SIan Rogers case TEST_SKIP: { 3623b536651SIan Rogers const char *skip_reason = NULL; 3633b536651SIan Rogers if (t->subtest.skip_reason) 3643b536651SIan Rogers skip_reason = t->subtest.skip_reason(subtest); 3653b536651SIan Rogers if (skip_reason) 3663b536651SIan Rogers color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", skip_reason); 3673b536651SIan Rogers else 368e8c6d500SWang Nan color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n"); 3693b536651SIan Rogers } 370e8c6d500SWang Nan break; 371e8c6d500SWang Nan case TEST_FAIL: 372e8c6d500SWang Nan default: 373e8c6d500SWang Nan color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n"); 374e8c6d500SWang Nan break; 375e8c6d500SWang Nan } 376e8c6d500SWang Nan 377e8c6d500SWang Nan return err; 378e8c6d500SWang Nan } 379e8c6d500SWang Nan 3801209b273SArnaldo Carvalho de Melo static const char *shell_test__description(char *description, size_t size, 3811209b273SArnaldo Carvalho de Melo const char *path, const char *name) 3821209b273SArnaldo Carvalho de Melo { 3831209b273SArnaldo Carvalho de Melo FILE *fp; 3841209b273SArnaldo Carvalho de Melo char filename[PATH_MAX]; 3851209b273SArnaldo Carvalho de Melo 3861209b273SArnaldo Carvalho de Melo path__join(filename, sizeof(filename), path, name); 3871209b273SArnaldo Carvalho de Melo fp = fopen(filename, "r"); 3881209b273SArnaldo Carvalho de Melo if (!fp) 3891209b273SArnaldo Carvalho de Melo return NULL; 3901209b273SArnaldo Carvalho de Melo 3914eaf97e8SMichael Petlan /* Skip shebang */ 3924eaf97e8SMichael Petlan while (fgetc(fp) != '\n'); 3934eaf97e8SMichael Petlan 3941209b273SArnaldo Carvalho de Melo description = fgets(description, size, fp); 3951209b273SArnaldo Carvalho de Melo fclose(fp); 3961209b273SArnaldo Carvalho de Melo 3973ca43b60SArnaldo Carvalho de Melo return description ? strim(description + 1) : NULL; 3981209b273SArnaldo Carvalho de Melo } 3991209b273SArnaldo Carvalho de Melo 400da963834SRiccardo Mancini #define for_each_shell_test(entlist, nr, base, ent) \ 401da963834SRiccardo Mancini for (int __i = 0; __i < nr && (ent = entlist[__i]); __i++) \ 402db8fec58SKim Phillips if (!is_directory(base, ent) && ent->d_name[0] != '.') 4031209b273SArnaldo Carvalho de Melo 4041209b273SArnaldo Carvalho de Melo static const char *shell_tests__dir(char *path, size_t size) 4051209b273SArnaldo Carvalho de Melo { 4061209b273SArnaldo Carvalho de Melo const char *devel_dirs[] = { "./tools/perf/tests", "./tests", }; 4071209b273SArnaldo Carvalho de Melo char *exec_path; 4081209b273SArnaldo Carvalho de Melo unsigned int i; 4091209b273SArnaldo Carvalho de Melo 4101209b273SArnaldo Carvalho de Melo for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) { 4111209b273SArnaldo Carvalho de Melo struct stat st; 4121209b273SArnaldo Carvalho de Melo if (!lstat(devel_dirs[i], &st)) { 4131209b273SArnaldo Carvalho de Melo scnprintf(path, size, "%s/shell", devel_dirs[i]); 4141209b273SArnaldo Carvalho de Melo if (!lstat(devel_dirs[i], &st)) 4151209b273SArnaldo Carvalho de Melo return path; 4161209b273SArnaldo Carvalho de Melo } 4171209b273SArnaldo Carvalho de Melo } 4181209b273SArnaldo Carvalho de Melo 4191209b273SArnaldo Carvalho de Melo /* Then installed path. */ 4201209b273SArnaldo Carvalho de Melo exec_path = get_argv_exec_path(); 4211209b273SArnaldo Carvalho de Melo scnprintf(path, size, "%s/tests/shell", exec_path); 4221209b273SArnaldo Carvalho de Melo free(exec_path); 4231209b273SArnaldo Carvalho de Melo return path; 4241209b273SArnaldo Carvalho de Melo } 4251209b273SArnaldo Carvalho de Melo 4261209b273SArnaldo Carvalho de Melo static int shell_tests__max_desc_width(void) 4271209b273SArnaldo Carvalho de Melo { 428da963834SRiccardo Mancini struct dirent **entlist; 4291209b273SArnaldo Carvalho de Melo struct dirent *ent; 430eb7261f1SRiccardo Mancini int n_dirs, e; 4311209b273SArnaldo Carvalho de Melo char path_dir[PATH_MAX]; 4321209b273SArnaldo Carvalho de Melo const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); 4331209b273SArnaldo Carvalho de Melo int width = 0; 4341209b273SArnaldo Carvalho de Melo 4351209b273SArnaldo Carvalho de Melo if (path == NULL) 4361209b273SArnaldo Carvalho de Melo return -1; 4371209b273SArnaldo Carvalho de Melo 438da963834SRiccardo Mancini n_dirs = scandir(path, &entlist, NULL, alphasort); 439da963834SRiccardo Mancini if (n_dirs == -1) 4401209b273SArnaldo Carvalho de Melo return -1; 4411209b273SArnaldo Carvalho de Melo 442da963834SRiccardo Mancini for_each_shell_test(entlist, n_dirs, path, ent) { 4431209b273SArnaldo Carvalho de Melo char bf[256]; 4441209b273SArnaldo Carvalho de Melo const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name); 4451209b273SArnaldo Carvalho de Melo 4461209b273SArnaldo Carvalho de Melo if (desc) { 4471209b273SArnaldo Carvalho de Melo int len = strlen(desc); 4481209b273SArnaldo Carvalho de Melo 4491209b273SArnaldo Carvalho de Melo if (width < len) 4501209b273SArnaldo Carvalho de Melo width = len; 4511209b273SArnaldo Carvalho de Melo } 4521209b273SArnaldo Carvalho de Melo } 4531209b273SArnaldo Carvalho de Melo 454eb7261f1SRiccardo Mancini for (e = 0; e < n_dirs; e++) 455eb7261f1SRiccardo Mancini zfree(&entlist[e]); 456da963834SRiccardo Mancini free(entlist); 4571209b273SArnaldo Carvalho de Melo return width; 4581209b273SArnaldo Carvalho de Melo } 4591209b273SArnaldo Carvalho de Melo 4601209b273SArnaldo Carvalho de Melo struct shell_test { 4611209b273SArnaldo Carvalho de Melo const char *dir; 4621209b273SArnaldo Carvalho de Melo const char *file; 4631209b273SArnaldo Carvalho de Melo }; 4641209b273SArnaldo Carvalho de Melo 4651209b273SArnaldo Carvalho de Melo static int shell_test__run(struct test *test, int subdir __maybe_unused) 4661209b273SArnaldo Carvalho de Melo { 4671209b273SArnaldo Carvalho de Melo int err; 4681209b273SArnaldo Carvalho de Melo char script[PATH_MAX]; 4691209b273SArnaldo Carvalho de Melo struct shell_test *st = test->priv; 4701209b273SArnaldo Carvalho de Melo 471e3c9cfd0SIan Rogers path__join(script, sizeof(script) - 3, st->dir, st->file); 472e3c9cfd0SIan Rogers 473e3c9cfd0SIan Rogers if (verbose) 474e3c9cfd0SIan Rogers strncat(script, " -v", sizeof(script) - strlen(script) - 1); 4751209b273SArnaldo Carvalho de Melo 4761209b273SArnaldo Carvalho de Melo err = system(script); 4771209b273SArnaldo Carvalho de Melo if (!err) 4781209b273SArnaldo Carvalho de Melo return TEST_OK; 4791209b273SArnaldo Carvalho de Melo 4801209b273SArnaldo Carvalho de Melo return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL; 4811209b273SArnaldo Carvalho de Melo } 4821209b273SArnaldo Carvalho de Melo 483ebdf90a4SRiccardo Mancini static int run_shell_tests(int argc, const char *argv[], int i, int width, 484ebdf90a4SRiccardo Mancini struct intlist *skiplist) 4851209b273SArnaldo Carvalho de Melo { 486da963834SRiccardo Mancini struct dirent **entlist; 4871209b273SArnaldo Carvalho de Melo struct dirent *ent; 488eb7261f1SRiccardo Mancini int n_dirs, e; 4891209b273SArnaldo Carvalho de Melo char path_dir[PATH_MAX]; 4901209b273SArnaldo Carvalho de Melo struct shell_test st = { 4911209b273SArnaldo Carvalho de Melo .dir = shell_tests__dir(path_dir, sizeof(path_dir)), 4921209b273SArnaldo Carvalho de Melo }; 4931209b273SArnaldo Carvalho de Melo 4941209b273SArnaldo Carvalho de Melo if (st.dir == NULL) 4951209b273SArnaldo Carvalho de Melo return -1; 4961209b273SArnaldo Carvalho de Melo 497da963834SRiccardo Mancini n_dirs = scandir(st.dir, &entlist, NULL, alphasort); 498da963834SRiccardo Mancini if (n_dirs == -1) { 499b2bf6660SIan Rogers pr_err("failed to open shell test directory: %s\n", 500b2bf6660SIan Rogers st.dir); 5011209b273SArnaldo Carvalho de Melo return -1; 502b2bf6660SIan Rogers } 5031209b273SArnaldo Carvalho de Melo 504da963834SRiccardo Mancini for_each_shell_test(entlist, n_dirs, st.dir, ent) { 5051209b273SArnaldo Carvalho de Melo int curr = i++; 5061209b273SArnaldo Carvalho de Melo char desc[256]; 5071209b273SArnaldo Carvalho de Melo struct test test = { 5081209b273SArnaldo Carvalho de Melo .desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name), 5091209b273SArnaldo Carvalho de Melo .func = shell_test__run, 5101209b273SArnaldo Carvalho de Melo .priv = &st, 5111209b273SArnaldo Carvalho de Melo }; 5121209b273SArnaldo Carvalho de Melo 513d685e6c1SJiri Olsa if (!perf_test__matches(test.desc, curr, argc, argv)) 5141209b273SArnaldo Carvalho de Melo continue; 5151209b273SArnaldo Carvalho de Melo 5161209b273SArnaldo Carvalho de Melo st.file = ent->d_name; 5171209b273SArnaldo Carvalho de Melo pr_info("%2d: %-*s:", i, width, test.desc); 518ebdf90a4SRiccardo Mancini 519ebdf90a4SRiccardo Mancini if (intlist__find(skiplist, i)) { 520ebdf90a4SRiccardo Mancini color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); 521ebdf90a4SRiccardo Mancini continue; 522ebdf90a4SRiccardo Mancini } 523ebdf90a4SRiccardo Mancini 5241209b273SArnaldo Carvalho de Melo test_and_print(&test, false, -1); 5251209b273SArnaldo Carvalho de Melo } 5261209b273SArnaldo Carvalho de Melo 527eb7261f1SRiccardo Mancini for (e = 0; e < n_dirs; e++) 528eb7261f1SRiccardo Mancini zfree(&entlist[e]); 529da963834SRiccardo Mancini free(entlist); 5301209b273SArnaldo Carvalho de Melo return 0; 5311209b273SArnaldo Carvalho de Melo } 5321209b273SArnaldo Carvalho de Melo 5332ae82878SArnaldo Carvalho de Melo static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 534945aea22SJiri Olsa { 535e8210cefSMatt Fleming struct test *t; 536*df225205SIan Rogers unsigned int j, k; 537945aea22SJiri Olsa int i = 0; 5381209b273SArnaldo Carvalho de Melo int width = shell_tests__max_desc_width(); 539945aea22SJiri Olsa 540*df225205SIan Rogers for_each_test(j, k, t) { 541e8210cefSMatt Fleming int len = strlen(t->desc); 542945aea22SJiri Olsa 543945aea22SJiri Olsa if (width < len) 544945aea22SJiri Olsa width = len; 545945aea22SJiri Olsa } 546945aea22SJiri Olsa 547*df225205SIan Rogers for_each_test(j, k, t) { 548945aea22SJiri Olsa int curr = i++, err; 549d685e6c1SJiri Olsa int subi; 550945aea22SJiri Olsa 551d685e6c1SJiri Olsa if (!perf_test__matches(t->desc, curr, argc, argv)) { 552d685e6c1SJiri Olsa bool skip = true; 553d685e6c1SJiri Olsa int subn; 554d685e6c1SJiri Olsa 555d685e6c1SJiri Olsa if (!t->subtest.get_nr) 556945aea22SJiri Olsa continue; 557945aea22SJiri Olsa 558d685e6c1SJiri Olsa subn = t->subtest.get_nr(); 559d685e6c1SJiri Olsa 560d685e6c1SJiri Olsa for (subi = 0; subi < subn; subi++) { 561d685e6c1SJiri Olsa if (perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv)) 562d685e6c1SJiri Olsa skip = false; 563d685e6c1SJiri Olsa } 564d685e6c1SJiri Olsa 565d685e6c1SJiri Olsa if (skip) 566d685e6c1SJiri Olsa continue; 567d685e6c1SJiri Olsa } 568d685e6c1SJiri Olsa 569598762cfSJiri Olsa if (t->is_supported && !t->is_supported()) { 570598762cfSJiri Olsa pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc); 571598762cfSJiri Olsa continue; 572598762cfSJiri Olsa } 573598762cfSJiri Olsa 574e8210cefSMatt Fleming pr_info("%2d: %-*s:", i, width, t->desc); 5752ae82878SArnaldo Carvalho de Melo 5762ae82878SArnaldo Carvalho de Melo if (intlist__find(skiplist, i)) { 5772ae82878SArnaldo Carvalho de Melo color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); 5782ae82878SArnaldo Carvalho de Melo continue; 5792ae82878SArnaldo Carvalho de Melo } 5802ae82878SArnaldo Carvalho de Melo 581e8c6d500SWang Nan if (!t->subtest.get_nr) { 582e8c6d500SWang Nan test_and_print(t, false, -1); 583e8c6d500SWang Nan } else { 584e8c6d500SWang Nan int subn = t->subtest.get_nr(); 585e8c6d500SWang Nan /* 586e8c6d500SWang Nan * minus 2 to align with normal testcases. 587e8c6d500SWang Nan * For subtest we print additional '.x' in number. 588e8c6d500SWang Nan * for example: 589e8c6d500SWang Nan * 590e8c6d500SWang Nan * 35: Test LLVM searching and compiling : 591e8c6d500SWang Nan * 35.1: Basic BPF llvm compiling test : Ok 592e8c6d500SWang Nan */ 593e8c6d500SWang Nan int subw = width > 2 ? width - 2 : width; 594e8c6d500SWang Nan bool skip = false; 595f4c1ea5fSJiri Olsa 596e8c6d500SWang Nan if (subn <= 0) { 597e8c6d500SWang Nan color_fprintf(stderr, PERF_COLOR_YELLOW, 598e8c6d500SWang Nan " Skip (not compiled in)\n"); 599e8c6d500SWang Nan continue; 600e8c6d500SWang Nan } 601e8c6d500SWang Nan pr_info("\n"); 602e8c6d500SWang Nan 603e8c6d500SWang Nan for (subi = 0; subi < subn; subi++) { 604e8c6d500SWang Nan int len = strlen(t->subtest.get_desc(subi)); 605e8c6d500SWang Nan 606e8c6d500SWang Nan if (subw < len) 607e8c6d500SWang Nan subw = len; 608e8c6d500SWang Nan } 609e8c6d500SWang Nan 610e8c6d500SWang Nan for (subi = 0; subi < subn; subi++) { 611d685e6c1SJiri Olsa if (!perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv)) 612d685e6c1SJiri Olsa continue; 613d685e6c1SJiri Olsa 614e8c6d500SWang Nan pr_info("%2d.%1d: %-*s:", i, subi + 1, subw, 615e8c6d500SWang Nan t->subtest.get_desc(subi)); 616aa90f9f9SSandipan Das err = test_and_print(t, skip, subi); 617e8c6d500SWang Nan if (err != TEST_OK && t->subtest.skip_if_fail) 618e8c6d500SWang Nan skip = true; 619e8c6d500SWang Nan } 620f4c1ea5fSJiri Olsa } 621945aea22SJiri Olsa } 622945aea22SJiri Olsa 623ebdf90a4SRiccardo Mancini return run_shell_tests(argc, argv, i, width, skiplist); 6241209b273SArnaldo Carvalho de Melo } 6251209b273SArnaldo Carvalho de Melo 6261209b273SArnaldo Carvalho de Melo static int perf_test__list_shell(int argc, const char **argv, int i) 6271209b273SArnaldo Carvalho de Melo { 628da963834SRiccardo Mancini struct dirent **entlist; 6291209b273SArnaldo Carvalho de Melo struct dirent *ent; 630eb7261f1SRiccardo Mancini int n_dirs, e; 6311209b273SArnaldo Carvalho de Melo char path_dir[PATH_MAX]; 6321209b273SArnaldo Carvalho de Melo const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); 6331209b273SArnaldo Carvalho de Melo 6341209b273SArnaldo Carvalho de Melo if (path == NULL) 6351209b273SArnaldo Carvalho de Melo return -1; 6361209b273SArnaldo Carvalho de Melo 637da963834SRiccardo Mancini n_dirs = scandir(path, &entlist, NULL, alphasort); 638da963834SRiccardo Mancini if (n_dirs == -1) 6391209b273SArnaldo Carvalho de Melo return -1; 6401209b273SArnaldo Carvalho de Melo 641da963834SRiccardo Mancini for_each_shell_test(entlist, n_dirs, path, ent) { 6426d02acc1SArnaldo Carvalho de Melo int curr = i++; 6431209b273SArnaldo Carvalho de Melo char bf[256]; 6446d02acc1SArnaldo Carvalho de Melo struct test t = { 6456d02acc1SArnaldo Carvalho de Melo .desc = shell_test__description(bf, sizeof(bf), path, ent->d_name), 6466d02acc1SArnaldo Carvalho de Melo }; 6471209b273SArnaldo Carvalho de Melo 648d685e6c1SJiri Olsa if (!perf_test__matches(t.desc, curr, argc, argv)) 6491209b273SArnaldo Carvalho de Melo continue; 6501209b273SArnaldo Carvalho de Melo 6516d02acc1SArnaldo Carvalho de Melo pr_info("%2d: %s\n", i, t.desc); 652eb7261f1SRiccardo Mancini 6531209b273SArnaldo Carvalho de Melo } 6541209b273SArnaldo Carvalho de Melo 655eb7261f1SRiccardo Mancini for (e = 0; e < n_dirs; e++) 656eb7261f1SRiccardo Mancini zfree(&entlist[e]); 657da963834SRiccardo Mancini free(entlist); 658945aea22SJiri Olsa return 0; 659945aea22SJiri Olsa } 660945aea22SJiri Olsa 661945aea22SJiri Olsa static int perf_test__list(int argc, const char **argv) 662945aea22SJiri Olsa { 663*df225205SIan Rogers unsigned int j, k; 664e8210cefSMatt Fleming struct test *t; 665945aea22SJiri Olsa int i = 0; 666945aea22SJiri Olsa 667*df225205SIan Rogers for_each_test(j, k, t) { 6686d02acc1SArnaldo Carvalho de Melo int curr = i++; 66928765bf2SArnaldo Carvalho de Melo 670d685e6c1SJiri Olsa if (!perf_test__matches(t->desc, curr, argc, argv) || 6716d02acc1SArnaldo Carvalho de Melo (t->is_supported && !t->is_supported())) 672945aea22SJiri Olsa continue; 673945aea22SJiri Olsa 67428765bf2SArnaldo Carvalho de Melo pr_info("%2d: %s\n", i, t->desc); 675ea40b6d3SHendrik Brueckner 676ea40b6d3SHendrik Brueckner if (t->subtest.get_nr) { 677ea40b6d3SHendrik Brueckner int subn = t->subtest.get_nr(); 678ea40b6d3SHendrik Brueckner int subi; 679ea40b6d3SHendrik Brueckner 680ea40b6d3SHendrik Brueckner for (subi = 0; subi < subn; subi++) 681ea40b6d3SHendrik Brueckner pr_info("%2d:%1d: %s\n", i, subi + 1, 682ea40b6d3SHendrik Brueckner t->subtest.get_desc(subi)); 683ea40b6d3SHendrik Brueckner } 684945aea22SJiri Olsa } 685945aea22SJiri Olsa 6861209b273SArnaldo Carvalho de Melo perf_test__list_shell(argc, argv, i); 6871209b273SArnaldo Carvalho de Melo 688945aea22SJiri Olsa return 0; 689945aea22SJiri Olsa } 690945aea22SJiri Olsa 691b0ad8ea6SArnaldo Carvalho de Melo int cmd_test(int argc, const char **argv) 692945aea22SJiri Olsa { 6931f9975f1SYunlong Song const char *test_usage[] = { 694945aea22SJiri Olsa "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", 695945aea22SJiri Olsa NULL, 696945aea22SJiri Olsa }; 6972ae82878SArnaldo Carvalho de Melo const char *skip = NULL; 698945aea22SJiri Olsa const struct option test_options[] = { 6992ae82878SArnaldo Carvalho de Melo OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), 700945aea22SJiri Olsa OPT_INCR('v', "verbose", &verbose, 701945aea22SJiri Olsa "be more verbose (show symbol address, etc)"), 7027fa9b8fbSJiri Olsa OPT_BOOLEAN('F', "dont-fork", &dont_fork, 7037fa9b8fbSJiri Olsa "Do not fork for testcase"), 704945aea22SJiri Olsa OPT_END() 705945aea22SJiri Olsa }; 7061f9975f1SYunlong Song const char * const test_subcommands[] = { "list", NULL }; 7072ae82878SArnaldo Carvalho de Melo struct intlist *skiplist = NULL; 708a635fc51SArnaldo Carvalho de Melo int ret = hists__init(); 709a635fc51SArnaldo Carvalho de Melo 710a635fc51SArnaldo Carvalho de Melo if (ret < 0) 711a635fc51SArnaldo Carvalho de Melo return ret; 712945aea22SJiri Olsa 7131f9975f1SYunlong Song argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0); 714945aea22SJiri Olsa if (argc >= 1 && !strcmp(argv[0], "list")) 7156d02acc1SArnaldo Carvalho de Melo return perf_test__list(argc - 1, argv + 1); 716945aea22SJiri Olsa 717945aea22SJiri Olsa symbol_conf.priv_size = sizeof(int); 718945aea22SJiri Olsa symbol_conf.sort_by_name = true; 719945aea22SJiri Olsa symbol_conf.try_vmlinux_path = true; 720945aea22SJiri Olsa 7210a7e6d1bSNamhyung Kim if (symbol__init(NULL) < 0) 722945aea22SJiri Olsa return -1; 723945aea22SJiri Olsa 7242ae82878SArnaldo Carvalho de Melo if (skip != NULL) 7252ae82878SArnaldo Carvalho de Melo skiplist = intlist__new(skip); 726d3280ce0SArnaldo Carvalho de Melo /* 727d3280ce0SArnaldo Carvalho de Melo * Tests that create BPF maps, for instance, need more than the 64K 728d3280ce0SArnaldo Carvalho de Melo * default: 729d3280ce0SArnaldo Carvalho de Melo */ 730d3280ce0SArnaldo Carvalho de Melo rlimit__bump_memlock(); 7312ae82878SArnaldo Carvalho de Melo 7322ae82878SArnaldo Carvalho de Melo return __cmd_test(argc, argv, skiplist); 733945aea22SJiri Olsa } 734