summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests
diff options
context:
space:
mode:
authorMickaël Salaün <mic@digikod.net>2017-08-06 19:23:37 -0400
committerShuah Khan <shuahkh@osg.samsung.com>2017-09-05 21:21:33 -0400
commit369130b63178e0e2f863a2da2a5ad0238ded6d9d (patch)
tree84a336c9a26fdb68b45a788d5fa9371028a73278 /tools/testing/selftests
parent1f87c7c15d77350c4ab1c14d9ab8df2a1f1010d1 (diff)
selftests: Enhance kselftest_harness.h to print which assert failed
When a test process is not able to write to TH_LOG_STREAM, this step mechanism enable to print the assert number which triggered the failure. This can be enabled by setting _metadata->no_print to true at the beginning of the test sequence. Update the seccomp-bpf test to return 0 if a test succeeded. This feature is needed for the Landlock tests. Signed-off-by: Mickaël Salaün <mic@digikod.net> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Kees Cook <keescook@chromium.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Will Drewry <wad@chromium.org> Link: https://lkml.kernel.org/r/CAGXu5j+D-FP8Kt9unNOqKrQJP4DYTpmgkJxWykZyrYiVPz3Y3Q@mail.gmail.com Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Diffstat (limited to 'tools/testing/selftests')
-rw-r--r--tools/testing/selftests/kselftest_harness.h39
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c2
2 files changed, 35 insertions, 6 deletions
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index c56f72e07cd7..e81bd28bdd89 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -51,6 +51,9 @@
51#define __KSELFTEST_HARNESS_H 51#define __KSELFTEST_HARNESS_H
52 52
53#define _GNU_SOURCE 53#define _GNU_SOURCE
54#include <asm/types.h>
55#include <errno.h>
56#include <stdbool.h>
54#include <stdint.h> 57#include <stdint.h>
55#include <stdio.h> 58#include <stdio.h>
56#include <stdlib.h> 59#include <stdlib.h>
@@ -84,6 +87,14 @@
84 * E.g., #define TH_LOG_ENABLED 1 87 * E.g., #define TH_LOG_ENABLED 1
85 * 88 *
86 * If no definition is provided, logging is enabled by default. 89 * If no definition is provided, logging is enabled by default.
90 *
91 * If there is no way to print an error message for the process running the
92 * test (e.g. not allowed to write to stderr), it is still possible to get the
93 * ASSERT_* number for which the test failed. This behavior can be enabled by
94 * writing `_metadata->no_print = true;` before the check sequence that is
95 * unable to print. When an error occur, instead of printing an error message
96 * and calling `abort(3)`, the test process call `_exit(2)` with the assert
97 * number as argument, which is then printed by the parent process.
87 */ 98 */
88#define TH_LOG(fmt, ...) do { \ 99#define TH_LOG(fmt, ...) do { \
89 if (TH_LOG_ENABLED) \ 100 if (TH_LOG_ENABLED) \
@@ -555,12 +566,18 @@
555 * return while still providing an optional block to the API consumer. 566 * return while still providing an optional block to the API consumer.
556 */ 567 */
557#define OPTIONAL_HANDLER(_assert) \ 568#define OPTIONAL_HANDLER(_assert) \
558 for (; _metadata->trigger; _metadata->trigger = __bail(_assert)) 569 for (; _metadata->trigger; _metadata->trigger = \
570 __bail(_assert, _metadata->no_print, _metadata->step))
571
572#define __INC_STEP(_metadata) \
573 if (_metadata->passed && _metadata->step < 255) \
574 _metadata->step++;
559 575
560#define __EXPECT(_expected, _seen, _t, _assert) do { \ 576#define __EXPECT(_expected, _seen, _t, _assert) do { \
561 /* Avoid multiple evaluation of the cases */ \ 577 /* Avoid multiple evaluation of the cases */ \
562 __typeof__(_expected) __exp = (_expected); \ 578 __typeof__(_expected) __exp = (_expected); \
563 __typeof__(_seen) __seen = (_seen); \ 579 __typeof__(_seen) __seen = (_seen); \
580 if (_assert) __INC_STEP(_metadata); \
564 if (!(__exp _t __seen)) { \ 581 if (!(__exp _t __seen)) { \
565 unsigned long long __exp_print = (uintptr_t)__exp; \ 582 unsigned long long __exp_print = (uintptr_t)__exp; \
566 unsigned long long __seen_print = (uintptr_t)__seen; \ 583 unsigned long long __seen_print = (uintptr_t)__seen; \
@@ -576,6 +593,7 @@
576#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \ 593#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
577 const char *__exp = (_expected); \ 594 const char *__exp = (_expected); \
578 const char *__seen = (_seen); \ 595 const char *__seen = (_seen); \
596 if (_assert) __INC_STEP(_metadata); \
579 if (!(strcmp(__exp, __seen) _t 0)) { \ 597 if (!(strcmp(__exp, __seen) _t 0)) { \
580 __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \ 598 __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
581 _metadata->passed = 0; \ 599 _metadata->passed = 0; \
@@ -590,6 +608,8 @@ struct __test_metadata {
590 int termsig; 608 int termsig;
591 int passed; 609 int passed;
592 int trigger; /* extra handler after the evaluation */ 610 int trigger; /* extra handler after the evaluation */
611 __u8 step;
612 bool no_print; /* manual trigger when TH_LOG_STREAM is not available */
593 struct __test_metadata *prev, *next; 613 struct __test_metadata *prev, *next;
594}; 614};
595 615
@@ -634,10 +654,13 @@ static inline void __register_test(struct __test_metadata *t)
634 } 654 }
635} 655}
636 656
637static inline int __bail(int for_realz) 657static inline int __bail(int for_realz, bool no_print, __u8 step)
638{ 658{
639 if (for_realz) 659 if (for_realz) {
660 if (no_print)
661 _exit(step);
640 abort(); 662 abort();
663 }
641 return 0; 664 return 0;
642} 665}
643 666
@@ -655,18 +678,24 @@ void __run_test(struct __test_metadata *t)
655 t->passed = 0; 678 t->passed = 0;
656 } else if (child_pid == 0) { 679 } else if (child_pid == 0) {
657 t->fn(t); 680 t->fn(t);
658 _exit(t->passed); 681 /* return the step that failed or 0 */
682 _exit(t->passed ? 0 : t->step);
659 } else { 683 } else {
660 /* TODO(wad) add timeout support. */ 684 /* TODO(wad) add timeout support. */
661 waitpid(child_pid, &status, 0); 685 waitpid(child_pid, &status, 0);
662 if (WIFEXITED(status)) { 686 if (WIFEXITED(status)) {
663 t->passed = t->termsig == -1 ? WEXITSTATUS(status) : 0; 687 t->passed = t->termsig == -1 ? !WEXITSTATUS(status) : 0;
664 if (t->termsig != -1) { 688 if (t->termsig != -1) {
665 fprintf(TH_LOG_STREAM, 689 fprintf(TH_LOG_STREAM,
666 "%s: Test exited normally " 690 "%s: Test exited normally "
667 "instead of by signal (code: %d)\n", 691 "instead of by signal (code: %d)\n",
668 t->name, 692 t->name,
669 WEXITSTATUS(status)); 693 WEXITSTATUS(status));
694 } else if (!t->passed) {
695 fprintf(TH_LOG_STREAM,
696 "%s: Test failed at step #%d\n",
697 t->name,
698 WEXITSTATUS(status));
670 } 699 }
671 } else if (WIFSIGNALED(status)) { 700 } else if (WIFSIGNALED(status)) {
672 t->passed = 0; 701 t->passed = 0;
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 73f5ea6778ce..4d6f92a9df6b 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -107,7 +107,7 @@ TEST(mode_strict_support)
107 ASSERT_EQ(0, ret) { 107 ASSERT_EQ(0, ret) {
108 TH_LOG("Kernel does not support CONFIG_SECCOMP"); 108 TH_LOG("Kernel does not support CONFIG_SECCOMP");
109 } 109 }
110 syscall(__NR_exit, 1); 110 syscall(__NR_exit, 0);
111} 111}
112 112
113TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL) 113TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)