perf tests: Improve topology test to check all aggregation types
[linux-2.6-microblaze.git] / tools / perf / tests / llvm.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "tests.h"
6 #include "debug.h"
7
8 #ifdef HAVE_LIBBPF_SUPPORT
9 #include <bpf/libbpf.h>
10 #include <util/llvm-utils.h>
11 #include "llvm.h"
12 static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
13 {
14         struct bpf_object *obj;
15
16         obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
17         if (libbpf_get_error(obj))
18                 return TEST_FAIL;
19         bpf_object__close(obj);
20         return TEST_OK;
21 }
22
23 static struct {
24         const char *source;
25         const char *desc;
26         bool should_load_fail;
27 } bpf_source_table[__LLVM_TESTCASE_MAX] = {
28         [LLVM_TESTCASE_BASE] = {
29                 .source = test_llvm__bpf_base_prog,
30                 .desc = "Basic BPF llvm compile",
31         },
32         [LLVM_TESTCASE_KBUILD] = {
33                 .source = test_llvm__bpf_test_kbuild_prog,
34                 .desc = "kbuild searching",
35         },
36         [LLVM_TESTCASE_BPF_PROLOGUE] = {
37                 .source = test_llvm__bpf_test_prologue_prog,
38                 .desc = "Compile source for BPF prologue generation",
39         },
40         [LLVM_TESTCASE_BPF_RELOCATION] = {
41                 .source = test_llvm__bpf_test_relocation,
42                 .desc = "Compile source for BPF relocation",
43                 .should_load_fail = true,
44         },
45 };
46
47 int
48 test_llvm__fetch_bpf_obj(void **p_obj_buf,
49                          size_t *p_obj_buf_sz,
50                          enum test_llvm__testcase idx,
51                          bool force,
52                          bool *should_load_fail)
53 {
54         const char *source;
55         const char *desc;
56         const char *tmpl_old, *clang_opt_old;
57         char *tmpl_new = NULL, *clang_opt_new = NULL;
58         int err, old_verbose, ret = TEST_FAIL;
59
60         if (idx >= __LLVM_TESTCASE_MAX)
61                 return TEST_FAIL;
62
63         source = bpf_source_table[idx].source;
64         desc = bpf_source_table[idx].desc;
65         if (should_load_fail)
66                 *should_load_fail = bpf_source_table[idx].should_load_fail;
67
68         /*
69          * Skip this test if user's .perfconfig doesn't set [llvm] section
70          * and clang is not found in $PATH, and this is not perf test -v
71          */
72         if (!force && (verbose <= 0 &&
73                        !llvm_param.user_set_param &&
74                        llvm__search_clang())) {
75                 pr_debug("No clang and no verbosive, skip this test\n");
76                 return TEST_SKIP;
77         }
78
79         /*
80          * llvm is verbosity when error. Suppress all error output if
81          * not 'perf test -v'.
82          */
83         old_verbose = verbose;
84         if (verbose == 0)
85                 verbose = -1;
86
87         *p_obj_buf = NULL;
88         *p_obj_buf_sz = 0;
89
90         if (!llvm_param.clang_bpf_cmd_template)
91                 goto out;
92
93         if (!llvm_param.clang_opt)
94                 llvm_param.clang_opt = strdup("");
95
96         err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
97                        llvm_param.clang_bpf_cmd_template,
98                        old_verbose ? "" : " 2>/dev/null");
99         if (err < 0)
100                 goto out;
101         err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
102         if (err < 0)
103                 goto out;
104
105         tmpl_old = llvm_param.clang_bpf_cmd_template;
106         llvm_param.clang_bpf_cmd_template = tmpl_new;
107         clang_opt_old = llvm_param.clang_opt;
108         llvm_param.clang_opt = clang_opt_new;
109
110         err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
111
112         llvm_param.clang_bpf_cmd_template = tmpl_old;
113         llvm_param.clang_opt = clang_opt_old;
114
115         verbose = old_verbose;
116         if (err)
117                 goto out;
118
119         ret = TEST_OK;
120 out:
121         free(tmpl_new);
122         free(clang_opt_new);
123         if (ret != TEST_OK)
124                 pr_debug("Failed to compile test case: '%s'\n", desc);
125         return ret;
126 }
127
128 int test__llvm(struct test *test __maybe_unused, int subtest)
129 {
130         int ret;
131         void *obj_buf = NULL;
132         size_t obj_buf_sz = 0;
133         bool should_load_fail = false;
134
135         if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
136                 return TEST_FAIL;
137
138         ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
139                                        subtest, false, &should_load_fail);
140
141         if (ret == TEST_OK && !should_load_fail) {
142                 ret = test__bpf_parsing(obj_buf, obj_buf_sz);
143                 if (ret != TEST_OK) {
144                         pr_debug("Failed to parse test case '%s'\n",
145                                  bpf_source_table[subtest].desc);
146                 }
147         }
148         free(obj_buf);
149
150         return ret;
151 }
152
153 int test__llvm_subtest_get_nr(void)
154 {
155         return __LLVM_TESTCASE_MAX;
156 }
157
158 const char *test__llvm_subtest_get_desc(int subtest)
159 {
160         if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
161                 return NULL;
162
163         return bpf_source_table[subtest].desc;
164 }
165 #else //HAVE_LIBBPF_SUPPORT
166 int test__llvm(struct test *test __maybe_unused, int subtest __maybe_unused)
167 {
168         return TEST_SKIP;
169 }
170
171 int test__llvm_subtest_get_nr(void)
172 {
173         return 0;
174 }
175
176 const char *test__llvm_subtest_get_desc(int subtest __maybe_unused)
177 {
178         return NULL;
179 }
180 #endif // HAVE_LIBBPF_SUPPORT