aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-20 22:02:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-20 22:02:17 -0400
commit6b2edf27fe26c73cd67b6bf5ffb23dce882e1455 (patch)
tree8d489d55fc5ab4d662abd6fa8fa47a0cc46af4af /tools/testing
parent7140ad3898dd119d993aff76a8752570c4f23871 (diff)
parent01675e9503c4e20c5ce9aebdfe6a9cf2ae4991e0 (diff)
Merge tag 'linux-kselftest-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull Kselftest update from Shuah Khan: - add cgroup core selftests - fix compile warnings in android ion test - fix to bugs in exclude and skip paths in vDSO test - remove obsolete config options - add missing .gitignore file * tag 'linux-kselftest-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: selftests/ftrace: Fix kprobe string testcase to not probe notrace function selftests: mount: remove no longer needed config option selftests: cgroup: add gitignore file Add cgroup core selftests selftests: vDSO - fix to return KSFT_SKIP when test couldn't be run selftests: vDSO - fix to exclude x86 test on non-x86 platforms selftests/android: initialize heap_type to avoid compiling warning
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/android/ion/ionapp_export.c1
-rw-r--r--tools/testing/selftests/cgroup/.gitignore1
-rw-r--r--tools/testing/selftests/cgroup/Makefile2
-rw-r--r--tools/testing/selftests/cgroup/cgroup_util.c8
-rw-r--r--tools/testing/selftests/cgroup/cgroup_util.h1
-rw-r--r--tools/testing/selftests/cgroup/test_core.c395
-rw-r--r--tools/testing/selftests/mount/config1
-rw-r--r--tools/testing/selftests/vDSO/Makefile13
-rw-r--r--tools/testing/selftests/vDSO/vdso_test.c7
9 files changed, 422 insertions, 7 deletions
diff --git a/tools/testing/selftests/android/ion/ionapp_export.c b/tools/testing/selftests/android/ion/ionapp_export.c
index a944e72621a9..b5fa0a2dc968 100644
--- a/tools/testing/selftests/android/ion/ionapp_export.c
+++ b/tools/testing/selftests/android/ion/ionapp_export.c
@@ -51,6 +51,7 @@ int main(int argc, char *argv[])
51 51
52 heap_size = 0; 52 heap_size = 0;
53 flags = 0; 53 flags = 0;
54 heap_type = ION_HEAP_TYPE_SYSTEM;
54 55
55 while ((opt = getopt(argc, argv, "hi:s:")) != -1) { 56 while ((opt = getopt(argc, argv, "hi:s:")) != -1) {
56 switch (opt) { 57 switch (opt) {
diff --git a/tools/testing/selftests/cgroup/.gitignore b/tools/testing/selftests/cgroup/.gitignore
new file mode 100644
index 000000000000..95eb3a53c381
--- /dev/null
+++ b/tools/testing/selftests/cgroup/.gitignore
@@ -0,0 +1 @@
test_memcontrol
diff --git a/tools/testing/selftests/cgroup/Makefile b/tools/testing/selftests/cgroup/Makefile
index f7a31392eb2f..23fbaa4a9630 100644
--- a/tools/testing/selftests/cgroup/Makefile
+++ b/tools/testing/selftests/cgroup/Makefile
@@ -4,7 +4,9 @@ CFLAGS += -Wall
4all: 4all:
5 5
6TEST_GEN_PROGS = test_memcontrol 6TEST_GEN_PROGS = test_memcontrol
7TEST_GEN_PROGS += test_core
7 8
8include ../lib.mk 9include ../lib.mk
9 10
10$(OUTPUT)/test_memcontrol: cgroup_util.c 11$(OUTPUT)/test_memcontrol: cgroup_util.c
12$(OUTPUT)/test_core: cgroup_util.c
diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c
index 1e9e3c470561..1c5d2b2a583b 100644
--- a/tools/testing/selftests/cgroup/cgroup_util.c
+++ b/tools/testing/selftests/cgroup/cgroup_util.c
@@ -229,6 +229,14 @@ retry:
229 return ret; 229 return ret;
230} 230}
231 231
232int cg_enter_current(const char *cgroup)
233{
234 char pidbuf[64];
235
236 snprintf(pidbuf, sizeof(pidbuf), "%d", getpid());
237 return cg_write(cgroup, "cgroup.procs", pidbuf);
238}
239
232int cg_run(const char *cgroup, 240int cg_run(const char *cgroup,
233 int (*fn)(const char *cgroup, void *arg), 241 int (*fn)(const char *cgroup, void *arg),
234 void *arg) 242 void *arg)
diff --git a/tools/testing/selftests/cgroup/cgroup_util.h b/tools/testing/selftests/cgroup/cgroup_util.h
index fe82a297d4e0..1ff6f9f1abdc 100644
--- a/tools/testing/selftests/cgroup/cgroup_util.h
+++ b/tools/testing/selftests/cgroup/cgroup_util.h
@@ -32,6 +32,7 @@ extern int cg_write(const char *cgroup, const char *control, char *buf);
32extern int cg_run(const char *cgroup, 32extern int cg_run(const char *cgroup,
33 int (*fn)(const char *cgroup, void *arg), 33 int (*fn)(const char *cgroup, void *arg),
34 void *arg); 34 void *arg);
35extern int cg_enter_current(const char *cgroup);
35extern int cg_run_nowait(const char *cgroup, 36extern int cg_run_nowait(const char *cgroup,
36 int (*fn)(const char *cgroup, void *arg), 37 int (*fn)(const char *cgroup, void *arg),
37 void *arg); 38 void *arg);
diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
new file mode 100644
index 000000000000..be59f9c34ea2
--- /dev/null
+++ b/tools/testing/selftests/cgroup/test_core.c
@@ -0,0 +1,395 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#include <linux/limits.h>
4#include <sys/types.h>
5#include <unistd.h>
6#include <stdio.h>
7#include <errno.h>
8
9#include "../kselftest.h"
10#include "cgroup_util.h"
11
12/*
13 * A(0) - B(0) - C(1)
14 * \ D(0)
15 *
16 * A, B and C's "populated" fields would be 1 while D's 0.
17 * test that after the one process in C is moved to root,
18 * A,B and C's "populated" fields would flip to "0" and file
19 * modified events will be generated on the
20 * "cgroup.events" files of both cgroups.
21 */
22static int test_cgcore_populated(const char *root)
23{
24 int ret = KSFT_FAIL;
25 char *cg_test_a = NULL, *cg_test_b = NULL;
26 char *cg_test_c = NULL, *cg_test_d = NULL;
27
28 cg_test_a = cg_name(root, "cg_test_a");
29 cg_test_b = cg_name(root, "cg_test_a/cg_test_b");
30 cg_test_c = cg_name(root, "cg_test_a/cg_test_b/cg_test_c");
31 cg_test_d = cg_name(root, "cg_test_a/cg_test_b/cg_test_d");
32
33 if (!cg_test_a || !cg_test_b || !cg_test_c || !cg_test_d)
34 goto cleanup;
35
36 if (cg_create(cg_test_a))
37 goto cleanup;
38
39 if (cg_create(cg_test_b))
40 goto cleanup;
41
42 if (cg_create(cg_test_c))
43 goto cleanup;
44
45 if (cg_create(cg_test_d))
46 goto cleanup;
47
48 if (cg_enter_current(cg_test_c))
49 goto cleanup;
50
51 if (cg_read_strcmp(cg_test_a, "cgroup.events", "populated 1\n"))
52 goto cleanup;
53
54 if (cg_read_strcmp(cg_test_b, "cgroup.events", "populated 1\n"))
55 goto cleanup;
56
57 if (cg_read_strcmp(cg_test_c, "cgroup.events", "populated 1\n"))
58 goto cleanup;
59
60 if (cg_read_strcmp(cg_test_d, "cgroup.events", "populated 0\n"))
61 goto cleanup;
62
63 if (cg_enter_current(root))
64 goto cleanup;
65
66 if (cg_read_strcmp(cg_test_a, "cgroup.events", "populated 0\n"))
67 goto cleanup;
68
69 if (cg_read_strcmp(cg_test_b, "cgroup.events", "populated 0\n"))
70 goto cleanup;
71
72 if (cg_read_strcmp(cg_test_c, "cgroup.events", "populated 0\n"))
73 goto cleanup;
74
75 if (cg_read_strcmp(cg_test_d, "cgroup.events", "populated 0\n"))
76 goto cleanup;
77
78 ret = KSFT_PASS;
79
80cleanup:
81 if (cg_test_d)
82 cg_destroy(cg_test_d);
83 if (cg_test_c)
84 cg_destroy(cg_test_c);
85 if (cg_test_b)
86 cg_destroy(cg_test_b);
87 if (cg_test_a)
88 cg_destroy(cg_test_a);
89 free(cg_test_d);
90 free(cg_test_c);
91 free(cg_test_b);
92 free(cg_test_a);
93 return ret;
94}
95
96/*
97 * A (domain threaded) - B (threaded) - C (domain)
98 *
99 * test that C can't be used until it is turned into a
100 * threaded cgroup. "cgroup.type" file will report "domain (invalid)" in
101 * these cases. Operations which fail due to invalid topology use
102 * EOPNOTSUPP as the errno.
103 */
104static int test_cgcore_invalid_domain(const char *root)
105{
106 int ret = KSFT_FAIL;
107 char *grandparent = NULL, *parent = NULL, *child = NULL;
108
109 grandparent = cg_name(root, "cg_test_grandparent");
110 parent = cg_name(root, "cg_test_grandparent/cg_test_parent");
111 child = cg_name(root, "cg_test_grandparent/cg_test_parent/cg_test_child");
112 if (!parent || !child || !grandparent)
113 goto cleanup;
114
115 if (cg_create(grandparent))
116 goto cleanup;
117
118 if (cg_create(parent))
119 goto cleanup;
120
121 if (cg_create(child))
122 goto cleanup;
123
124 if (cg_write(parent, "cgroup.type", "threaded"))
125 goto cleanup;
126
127 if (cg_read_strcmp(child, "cgroup.type", "domain invalid\n"))
128 goto cleanup;
129
130 if (!cg_enter_current(child))
131 goto cleanup;
132
133 if (errno != EOPNOTSUPP)
134 goto cleanup;
135
136 ret = KSFT_PASS;
137
138cleanup:
139 cg_enter_current(root);
140 if (child)
141 cg_destroy(child);
142 if (parent)
143 cg_destroy(parent);
144 if (grandparent)
145 cg_destroy(grandparent);
146 free(child);
147 free(parent);
148 free(grandparent);
149 return ret;
150}
151
152/*
153 * Test that when a child becomes threaded
154 * the parent type becomes domain threaded.
155 */
156static int test_cgcore_parent_becomes_threaded(const char *root)
157{
158 int ret = KSFT_FAIL;
159 char *parent = NULL, *child = NULL;
160
161 parent = cg_name(root, "cg_test_parent");
162 child = cg_name(root, "cg_test_parent/cg_test_child");
163 if (!parent || !child)
164 goto cleanup;
165
166 if (cg_create(parent))
167 goto cleanup;
168
169 if (cg_create(child))
170 goto cleanup;
171
172 if (cg_write(child, "cgroup.type", "threaded"))
173 goto cleanup;
174
175 if (cg_read_strcmp(parent, "cgroup.type", "domain threaded\n"))
176 goto cleanup;
177
178 ret = KSFT_PASS;
179
180cleanup:
181 if (child)
182 cg_destroy(child);
183 if (parent)
184 cg_destroy(parent);
185 free(child);
186 free(parent);
187 return ret;
188
189}
190
191/*
192 * Test that there's no internal process constrain on threaded cgroups.
193 * You can add threads/processes on a parent with a controller enabled.
194 */
195static int test_cgcore_no_internal_process_constraint_on_threads(const char *root)
196{
197 int ret = KSFT_FAIL;
198 char *parent = NULL, *child = NULL;
199
200 if (cg_read_strstr(root, "cgroup.controllers", "cpu") ||
201 cg_read_strstr(root, "cgroup.subtree_control", "cpu")) {
202 ret = KSFT_SKIP;
203 goto cleanup;
204 }
205
206 parent = cg_name(root, "cg_test_parent");
207 child = cg_name(root, "cg_test_parent/cg_test_child");
208 if (!parent || !child)
209 goto cleanup;
210
211 if (cg_create(parent))
212 goto cleanup;
213
214 if (cg_create(child))
215 goto cleanup;
216
217 if (cg_write(parent, "cgroup.type", "threaded"))
218 goto cleanup;
219
220 if (cg_write(child, "cgroup.type", "threaded"))
221 goto cleanup;
222
223 if (cg_write(parent, "cgroup.subtree_control", "+cpu"))
224 goto cleanup;
225
226 if (cg_enter_current(parent))
227 goto cleanup;
228
229 ret = KSFT_PASS;
230
231cleanup:
232 cg_enter_current(root);
233 cg_enter_current(root);
234 if (child)
235 cg_destroy(child);
236 if (parent)
237 cg_destroy(parent);
238 free(child);
239 free(parent);
240 return ret;
241}
242
243/*
244 * Test that you can't enable a controller on a child if it's not enabled
245 * on the parent.
246 */
247static int test_cgcore_top_down_constraint_enable(const char *root)
248{
249 int ret = KSFT_FAIL;
250 char *parent = NULL, *child = NULL;
251
252 parent = cg_name(root, "cg_test_parent");
253 child = cg_name(root, "cg_test_parent/cg_test_child");
254 if (!parent || !child)
255 goto cleanup;
256
257 if (cg_create(parent))
258 goto cleanup;
259
260 if (cg_create(child))
261 goto cleanup;
262
263 if (!cg_write(child, "cgroup.subtree_control", "+memory"))
264 goto cleanup;
265
266 ret = KSFT_PASS;
267
268cleanup:
269 if (child)
270 cg_destroy(child);
271 if (parent)
272 cg_destroy(parent);
273 free(child);
274 free(parent);
275 return ret;
276}
277
278/*
279 * Test that you can't disable a controller on a parent
280 * if it's enabled in a child.
281 */
282static int test_cgcore_top_down_constraint_disable(const char *root)
283{
284 int ret = KSFT_FAIL;
285 char *parent = NULL, *child = NULL;
286
287 parent = cg_name(root, "cg_test_parent");
288 child = cg_name(root, "cg_test_parent/cg_test_child");
289 if (!parent || !child)
290 goto cleanup;
291
292 if (cg_create(parent))
293 goto cleanup;
294
295 if (cg_create(child))
296 goto cleanup;
297
298 if (cg_write(parent, "cgroup.subtree_control", "+memory"))
299 goto cleanup;
300
301 if (cg_write(child, "cgroup.subtree_control", "+memory"))
302 goto cleanup;
303
304 if (!cg_write(parent, "cgroup.subtree_control", "-memory"))
305 goto cleanup;
306
307 ret = KSFT_PASS;
308
309cleanup:
310 if (child)
311 cg_destroy(child);
312 if (parent)
313 cg_destroy(parent);
314 free(child);
315 free(parent);
316 return ret;
317}
318
319/*
320 * Test internal process constraint.
321 * You can't add a pid to a domain parent if a controller is enabled.
322 */
323static int test_cgcore_internal_process_constraint(const char *root)
324{
325 int ret = KSFT_FAIL;
326 char *parent = NULL, *child = NULL;
327
328 parent = cg_name(root, "cg_test_parent");
329 child = cg_name(root, "cg_test_parent/cg_test_child");
330 if (!parent || !child)
331 goto cleanup;
332
333 if (cg_create(parent))
334 goto cleanup;
335
336 if (cg_create(child))
337 goto cleanup;
338
339 if (cg_write(parent, "cgroup.subtree_control", "+memory"))
340 goto cleanup;
341
342 if (!cg_enter_current(parent))
343 goto cleanup;
344
345 ret = KSFT_PASS;
346
347cleanup:
348 if (child)
349 cg_destroy(child);
350 if (parent)
351 cg_destroy(parent);
352 free(child);
353 free(parent);
354 return ret;
355}
356
357#define T(x) { x, #x }
358struct corecg_test {
359 int (*fn)(const char *root);
360 const char *name;
361} tests[] = {
362 T(test_cgcore_internal_process_constraint),
363 T(test_cgcore_top_down_constraint_enable),
364 T(test_cgcore_top_down_constraint_disable),
365 T(test_cgcore_no_internal_process_constraint_on_threads),
366 T(test_cgcore_parent_becomes_threaded),
367 T(test_cgcore_invalid_domain),
368 T(test_cgcore_populated),
369};
370#undef T
371
372int main(int argc, char *argv[])
373{
374 char root[PATH_MAX];
375 int i, ret = EXIT_SUCCESS;
376
377 if (cg_find_unified_root(root, sizeof(root)))
378 ksft_exit_skip("cgroup v2 isn't mounted\n");
379 for (i = 0; i < ARRAY_SIZE(tests); i++) {
380 switch (tests[i].fn(root)) {
381 case KSFT_PASS:
382 ksft_test_result_pass("%s\n", tests[i].name);
383 break;
384 case KSFT_SKIP:
385 ksft_test_result_skip("%s\n", tests[i].name);
386 break;
387 default:
388 ret = EXIT_FAILURE;
389 ksft_test_result_fail("%s\n", tests[i].name);
390 break;
391 }
392 }
393
394 return ret;
395}
diff --git a/tools/testing/selftests/mount/config b/tools/testing/selftests/mount/config
index b5d881e48548..416bd53ce982 100644
--- a/tools/testing/selftests/mount/config
+++ b/tools/testing/selftests/mount/config
@@ -1,2 +1 @@
1CONFIG_USER_NS=y CONFIG_USER_NS=y
2CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile
index f5d7a7851e21..9e03d61f52fd 100644
--- a/tools/testing/selftests/vDSO/Makefile
+++ b/tools/testing/selftests/vDSO/Makefile
@@ -1,6 +1,14 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2include ../lib.mk 2include ../lib.mk
3 3
4uname_M := $(shell uname -m 2>/dev/null || echo not)
5ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
6
7TEST_GEN_PROGS := $(OUTPUT)/vdso_test
8ifeq ($(ARCH),x86)
9TEST_GEN_PROGS += $(OUTPUT)/vdso_standalone_test_x86
10endif
11
4ifndef CROSS_COMPILE 12ifndef CROSS_COMPILE
5CFLAGS := -std=gnu99 13CFLAGS := -std=gnu99
6CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector 14CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
@@ -8,14 +16,11 @@ ifeq ($(CONFIG_X86_32),y)
8LDLIBS += -lgcc_s 16LDLIBS += -lgcc_s
9endif 17endif
10 18
11TEST_PROGS := $(OUTPUT)/vdso_test $(OUTPUT)/vdso_standalone_test_x86 19all: $(TEST_GEN_PROGS)
12
13all: $(TEST_PROGS)
14$(OUTPUT)/vdso_test: parse_vdso.c vdso_test.c 20$(OUTPUT)/vdso_test: parse_vdso.c vdso_test.c
15$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c 21$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c
16 $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \ 22 $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \
17 vdso_standalone_test_x86.c parse_vdso.c \ 23 vdso_standalone_test_x86.c parse_vdso.c \
18 -o $@ 24 -o $@
19 25
20EXTRA_CLEAN := $(TEST_PROGS)
21endif 26endif
diff --git a/tools/testing/selftests/vDSO/vdso_test.c b/tools/testing/selftests/vDSO/vdso_test.c
index 2df26bd0099c..eda53f833d8e 100644
--- a/tools/testing/selftests/vDSO/vdso_test.c
+++ b/tools/testing/selftests/vDSO/vdso_test.c
@@ -15,6 +15,8 @@
15#include <sys/auxv.h> 15#include <sys/auxv.h>
16#include <sys/time.h> 16#include <sys/time.h>
17 17
18#include "../kselftest.h"
19
18extern void *vdso_sym(const char *version, const char *name); 20extern void *vdso_sym(const char *version, const char *name);
19extern void vdso_init_from_sysinfo_ehdr(uintptr_t base); 21extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
20extern void vdso_init_from_auxv(void *auxv); 22extern void vdso_init_from_auxv(void *auxv);
@@ -37,7 +39,7 @@ int main(int argc, char **argv)
37 unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR); 39 unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
38 if (!sysinfo_ehdr) { 40 if (!sysinfo_ehdr) {
39 printf("AT_SYSINFO_EHDR is not present!\n"); 41 printf("AT_SYSINFO_EHDR is not present!\n");
40 return 0; 42 return KSFT_SKIP;
41 } 43 }
42 44
43 vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR)); 45 vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
@@ -48,7 +50,7 @@ int main(int argc, char **argv)
48 50
49 if (!gtod) { 51 if (!gtod) {
50 printf("Could not find %s\n", name); 52 printf("Could not find %s\n", name);
51 return 1; 53 return KSFT_SKIP;
52 } 54 }
53 55
54 struct timeval tv; 56 struct timeval tv;
@@ -59,6 +61,7 @@ int main(int argc, char **argv)
59 (long long)tv.tv_sec, (long long)tv.tv_usec); 61 (long long)tv.tv_sec, (long long)tv.tv_usec);
60 } else { 62 } else {
61 printf("%s failed\n", name); 63 printf("%s failed\n", name);
64 return KSFT_FAIL;
62 } 65 }
63 66
64 return 0; 67 return 0;