linux/tools/perf/tests/builtin-test.c
<<
>>
Prefs
   1/*
   2 * builtin-test.c
   3 *
   4 * Builtin regression testing command: ever growing number of sanity tests
   5 */
   6#include <unistd.h>
   7#include <string.h>
   8#include "builtin.h"
   9#include "hist.h"
  10#include "intlist.h"
  11#include "tests.h"
  12#include "debug.h"
  13#include "color.h"
  14#include "parse-options.h"
  15#include "symbol.h"
  16
  17static struct test {
  18        const char *desc;
  19        int (*func)(void);
  20} tests[] = {
  21        {
  22                .desc = "vmlinux symtab matches kallsyms",
  23                .func = test__vmlinux_matches_kallsyms,
  24        },
  25        {
  26                .desc = "detect open syscall event",
  27                .func = test__open_syscall_event,
  28        },
  29        {
  30                .desc = "detect open syscall event on all cpus",
  31                .func = test__open_syscall_event_on_all_cpus,
  32        },
  33        {
  34                .desc = "read samples using the mmap interface",
  35                .func = test__basic_mmap,
  36        },
  37        {
  38                .desc = "parse events tests",
  39                .func = test__parse_events,
  40        },
  41#if defined(__x86_64__) || defined(__i386__)
  42        {
  43                .desc = "x86 rdpmc test",
  44                .func = test__rdpmc,
  45        },
  46#endif
  47        {
  48                .desc = "Validate PERF_RECORD_* events & perf_sample fields",
  49                .func = test__PERF_RECORD,
  50        },
  51        {
  52                .desc = "Test perf pmu format parsing",
  53                .func = test__pmu,
  54        },
  55        {
  56                .desc = "Test dso data read",
  57                .func = test__dso_data,
  58        },
  59        {
  60                .desc = "Test dso data cache",
  61                .func = test__dso_data_cache,
  62        },
  63        {
  64                .desc = "Test dso data reopen",
  65                .func = test__dso_data_reopen,
  66        },
  67        {
  68                .desc = "roundtrip evsel->name check",
  69                .func = test__perf_evsel__roundtrip_name_test,
  70        },
  71        {
  72                .desc = "Check parsing of sched tracepoints fields",
  73                .func = test__perf_evsel__tp_sched_test,
  74        },
  75        {
  76                .desc = "Generate and check syscalls:sys_enter_open event fields",
  77                .func = test__syscall_open_tp_fields,
  78        },
  79        {
  80                .desc = "struct perf_event_attr setup",
  81                .func = test__attr,
  82        },
  83        {
  84                .desc = "Test matching and linking multiple hists",
  85                .func = test__hists_link,
  86        },
  87        {
  88                .desc = "Try 'import perf' in python, checking link problems",
  89                .func = test__python_use,
  90        },
  91        {
  92                .desc = "Test breakpoint overflow signal handler",
  93                .func = test__bp_signal,
  94        },
  95        {
  96                .desc = "Test breakpoint overflow sampling",
  97                .func = test__bp_signal_overflow,
  98        },
  99        {
 100                .desc = "Test number of exit event of a simple workload",
 101                .func = test__task_exit,
 102        },
 103        {
 104                .desc = "Test software clock events have valid period values",
 105                .func = test__sw_clock_freq,
 106        },
 107#if defined(__x86_64__) || defined(__i386__)
 108        {
 109                .desc = "Test converting perf time to TSC",
 110                .func = test__perf_time_to_tsc,
 111        },
 112#endif
 113        {
 114                .desc = "Test object code reading",
 115                .func = test__code_reading,
 116        },
 117        {
 118                .desc = "Test sample parsing",
 119                .func = test__sample_parsing,
 120        },
 121        {
 122                .desc = "Test using a dummy software event to keep tracking",
 123                .func = test__keep_tracking,
 124        },
 125        {
 126                .desc = "Test parsing with no sample_id_all bit set",
 127                .func = test__parse_no_sample_id_all,
 128        },
 129#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 130#ifdef HAVE_DWARF_UNWIND_SUPPORT
 131        {
 132                .desc = "Test dwarf unwind",
 133                .func = test__dwarf_unwind,
 134        },
 135#endif
 136#endif
 137        {
 138                .desc = "Test filtering hist entries",
 139                .func = test__hists_filter,
 140        },
 141        {
 142                .desc = "Test mmap thread lookup",
 143                .func = test__mmap_thread_lookup,
 144        },
 145        {
 146                .desc = "Test thread mg sharing",
 147                .func = test__thread_mg_share,
 148        },
 149        {
 150                .desc = "Test output sorting of hist entries",
 151                .func = test__hists_output,
 152        },
 153        {
 154                .desc = "Test cumulation of child hist entries",
 155                .func = test__hists_cumulate,
 156        },
 157        {
 158                .desc = "Test tracking with sched_switch",
 159                .func = test__switch_tracking,
 160        },
 161        {
 162                .desc = "Filter fds with revents mask in a fdarray",
 163                .func = test__fdarray__filter,
 164        },
 165        {
 166                .desc = "Add fd to a fdarray, making it autogrow",
 167                .func = test__fdarray__add,
 168        },
 169        {
 170                .func = NULL,
 171        },
 172};
 173
 174static bool perf_test__matches(int curr, int argc, const char *argv[])
 175{
 176        int i;
 177
 178        if (argc == 0)
 179                return true;
 180
 181        for (i = 0; i < argc; ++i) {
 182                char *end;
 183                long nr = strtoul(argv[i], &end, 10);
 184
 185                if (*end == '\0') {
 186                        if (nr == curr + 1)
 187                                return true;
 188                        continue;
 189                }
 190
 191                if (strstr(tests[curr].desc, argv[i]))
 192                        return true;
 193        }
 194
 195        return false;
 196}
 197
 198static int run_test(struct test *test)
 199{
 200        int status, err = -1, child = fork();
 201        char sbuf[STRERR_BUFSIZE];
 202
 203        if (child < 0) {
 204                pr_err("failed to fork test: %s\n",
 205                        strerror_r(errno, sbuf, sizeof(sbuf)));
 206                return -1;
 207        }
 208
 209        if (!child) {
 210                pr_debug("test child forked, pid %d\n", getpid());
 211                err = test->func();
 212                exit(err);
 213        }
 214
 215        wait(&status);
 216
 217        if (WIFEXITED(status)) {
 218                err = WEXITSTATUS(status);
 219                pr_debug("test child finished with %d\n", err);
 220        } else if (WIFSIGNALED(status)) {
 221                err = -1;
 222                pr_debug("test child interrupted\n");
 223        }
 224
 225        return err;
 226}
 227
 228static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
 229{
 230        int i = 0;
 231        int width = 0;
 232
 233        while (tests[i].func) {
 234                int len = strlen(tests[i].desc);
 235
 236                if (width < len)
 237                        width = len;
 238                ++i;
 239        }
 240
 241        i = 0;
 242        while (tests[i].func) {
 243                int curr = i++, err;
 244
 245                if (!perf_test__matches(curr, argc, argv))
 246                        continue;
 247
 248                pr_info("%2d: %-*s:", i, width, tests[curr].desc);
 249
 250                if (intlist__find(skiplist, i)) {
 251                        color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
 252                        continue;
 253                }
 254
 255                pr_debug("\n--- start ---\n");
 256                err = run_test(&tests[curr]);
 257                pr_debug("---- end ----\n%s:", tests[curr].desc);
 258
 259                switch (err) {
 260                case TEST_OK:
 261                        pr_info(" Ok\n");
 262                        break;
 263                case TEST_SKIP:
 264                        color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
 265                        break;
 266                case TEST_FAIL:
 267                default:
 268                        color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
 269                        break;
 270                }
 271        }
 272
 273        return 0;
 274}
 275
 276static int perf_test__list(int argc, const char **argv)
 277{
 278        int i = 0;
 279
 280        while (tests[i].func) {
 281                int curr = i++;
 282
 283                if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
 284                        continue;
 285
 286                pr_info("%2d: %s\n", i, tests[curr].desc);
 287        }
 288
 289        return 0;
 290}
 291
 292int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
 293{
 294        const char * const test_usage[] = {
 295        "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
 296        NULL,
 297        };
 298        const char *skip = NULL;
 299        const struct option test_options[] = {
 300        OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
 301        OPT_INCR('v', "verbose", &verbose,
 302                    "be more verbose (show symbol address, etc)"),
 303        OPT_END()
 304        };
 305        struct intlist *skiplist = NULL;
 306        int ret = hists__init();
 307
 308        if (ret < 0)
 309                return ret;
 310
 311        argc = parse_options(argc, argv, test_options, test_usage, 0);
 312        if (argc >= 1 && !strcmp(argv[0], "list"))
 313                return perf_test__list(argc, argv);
 314
 315        symbol_conf.priv_size = sizeof(int);
 316        symbol_conf.sort_by_name = true;
 317        symbol_conf.try_vmlinux_path = true;
 318
 319        if (symbol__init(NULL) < 0)
 320                return -1;
 321
 322        if (skip != NULL)
 323                skiplist = intlist__new(skip);
 324
 325        return __cmd_test(argc, argv, skiplist);
 326}
 327