core_extern.c (5678B)
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (c) 2019 Facebook */ 3 4#include <test_progs.h> 5#include <sys/mman.h> 6#include <sys/utsname.h> 7#include <linux/version.h> 8#include "test_core_extern.skel.h" 9 10static uint32_t get_kernel_version(void) 11{ 12 uint32_t major, minor, patch; 13 struct utsname info; 14 15 uname(&info); 16 if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3) 17 return 0; 18 return KERNEL_VERSION(major, minor, patch); 19} 20 21#define CFG "CONFIG_BPF_SYSCALL=n\n" 22 23static struct test_case { 24 const char *name; 25 const char *cfg; 26 bool fails; 27 struct test_core_extern__data data; 28} test_cases[] = { 29 { .name = "default search path", .data = { .bpf_syscall = true } }, 30 { 31 .name = "custom values", 32 .cfg = "CONFIG_BPF_SYSCALL=n\n" 33 "CONFIG_TRISTATE=m\n" 34 "CONFIG_BOOL=y\n" 35 "CONFIG_CHAR=100\n" 36 "CONFIG_USHORT=30000\n" 37 "CONFIG_INT=123456\n" 38 "CONFIG_ULONG=0xDEADBEEFC0DE\n" 39 "CONFIG_STR=\"abracad\"\n" 40 "CONFIG_MISSING=0", 41 .data = { 42 .bpf_syscall = false, 43 .tristate_val = TRI_MODULE, 44 .bool_val = true, 45 .char_val = 100, 46 .ushort_val = 30000, 47 .int_val = 123456, 48 .ulong_val = 0xDEADBEEFC0DE, 49 .str_val = "abracad", 50 }, 51 }, 52 /* TRISTATE */ 53 { .name = "tristate (y)", .cfg = CFG"CONFIG_TRISTATE=y\n", 54 .data = { .tristate_val = TRI_YES } }, 55 { .name = "tristate (n)", .cfg = CFG"CONFIG_TRISTATE=n\n", 56 .data = { .tristate_val = TRI_NO } }, 57 { .name = "tristate (m)", .cfg = CFG"CONFIG_TRISTATE=m\n", 58 .data = { .tristate_val = TRI_MODULE } }, 59 { .name = "tristate (int)", .fails = 1, .cfg = CFG"CONFIG_TRISTATE=1" }, 60 { .name = "tristate (bad)", .fails = 1, .cfg = CFG"CONFIG_TRISTATE=M" }, 61 /* BOOL */ 62 { .name = "bool (y)", .cfg = CFG"CONFIG_BOOL=y\n", 63 .data = { .bool_val = true } }, 64 { .name = "bool (n)", .cfg = CFG"CONFIG_BOOL=n\n", 65 .data = { .bool_val = false } }, 66 { .name = "bool (tristate)", .fails = 1, .cfg = CFG"CONFIG_BOOL=m" }, 67 { .name = "bool (int)", .fails = 1, .cfg = CFG"CONFIG_BOOL=1" }, 68 /* CHAR */ 69 { .name = "char (tristate)", .cfg = CFG"CONFIG_CHAR=m\n", 70 .data = { .char_val = 'm' } }, 71 { .name = "char (bad)", .fails = 1, .cfg = CFG"CONFIG_CHAR=q\n" }, 72 { .name = "char (empty)", .fails = 1, .cfg = CFG"CONFIG_CHAR=\n" }, 73 { .name = "char (str)", .fails = 1, .cfg = CFG"CONFIG_CHAR=\"y\"\n" }, 74 /* STRING */ 75 { .name = "str (empty)", .cfg = CFG"CONFIG_STR=\"\"\n", 76 .data = { .str_val = "\0\0\0\0\0\0\0" } }, 77 { .name = "str (padded)", .cfg = CFG"CONFIG_STR=\"abra\"\n", 78 .data = { .str_val = "abra\0\0\0" } }, 79 { .name = "str (too long)", .cfg = CFG"CONFIG_STR=\"abracada\"\n", 80 .data = { .str_val = "abracad" } }, 81 { .name = "str (no value)", .fails = 1, .cfg = CFG"CONFIG_STR=\n" }, 82 { .name = "str (bad value)", .fails = 1, .cfg = CFG"CONFIG_STR=bla\n" }, 83 /* INTEGERS */ 84 { 85 .name = "integer forms", 86 .cfg = CFG 87 "CONFIG_CHAR=0xA\n" 88 "CONFIG_USHORT=0462\n" 89 "CONFIG_INT=-100\n" 90 "CONFIG_ULONG=+1000000000000", 91 .data = { 92 .char_val = 0xA, 93 .ushort_val = 0462, 94 .int_val = -100, 95 .ulong_val = 1000000000000, 96 }, 97 }, 98 { .name = "int (bad)", .fails = 1, .cfg = CFG"CONFIG_INT=abc" }, 99 { .name = "int (str)", .fails = 1, .cfg = CFG"CONFIG_INT=\"abc\"" }, 100 { .name = "int (empty)", .fails = 1, .cfg = CFG"CONFIG_INT=" }, 101 { .name = "int (mixed)", .fails = 1, .cfg = CFG"CONFIG_INT=123abc" }, 102 { .name = "int (max)", .cfg = CFG"CONFIG_INT=2147483647", 103 .data = { .int_val = 2147483647 } }, 104 { .name = "int (min)", .cfg = CFG"CONFIG_INT=-2147483648", 105 .data = { .int_val = -2147483648 } }, 106 { .name = "int (max+1)", .fails = 1, .cfg = CFG"CONFIG_INT=2147483648" }, 107 { .name = "int (min-1)", .fails = 1, .cfg = CFG"CONFIG_INT=-2147483649" }, 108 { .name = "ushort (max)", .cfg = CFG"CONFIG_USHORT=65535", 109 .data = { .ushort_val = 65535 } }, 110 { .name = "ushort (min)", .cfg = CFG"CONFIG_USHORT=0", 111 .data = { .ushort_val = 0 } }, 112 { .name = "ushort (max+1)", .fails = 1, .cfg = CFG"CONFIG_USHORT=65536" }, 113 { .name = "ushort (min-1)", .fails = 1, .cfg = CFG"CONFIG_USHORT=-1" }, 114 { .name = "u64 (max)", .cfg = CFG"CONFIG_ULONG=0xffffffffffffffff", 115 .data = { .ulong_val = 0xffffffffffffffff } }, 116 { .name = "u64 (min)", .cfg = CFG"CONFIG_ULONG=0", 117 .data = { .ulong_val = 0 } }, 118 { .name = "u64 (max+1)", .fails = 1, .cfg = CFG"CONFIG_ULONG=0x10000000000000000" }, 119}; 120 121void test_core_extern(void) 122{ 123 const uint32_t kern_ver = get_kernel_version(); 124 int err, duration = 0, i, j; 125 struct test_core_extern *skel = NULL; 126 uint64_t *got, *exp; 127 int n = sizeof(*skel->data) / sizeof(uint64_t); 128 129 for (i = 0; i < ARRAY_SIZE(test_cases); i++) { 130 struct test_case *t = &test_cases[i]; 131 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts, 132 .kconfig = t->cfg, 133 ); 134 135 if (!test__start_subtest(t->name)) 136 continue; 137 138 skel = test_core_extern__open_opts(&opts); 139 if (CHECK(!skel, "skel_open", "skeleton open failed\n")) 140 goto cleanup; 141 err = test_core_extern__load(skel); 142 if (t->fails) { 143 CHECK(!err, "skel_load", 144 "shouldn't succeed open/load of skeleton\n"); 145 goto cleanup; 146 } else if (CHECK(err, "skel_load", 147 "failed to open/load skeleton\n")) { 148 goto cleanup; 149 } 150 err = test_core_extern__attach(skel); 151 if (CHECK(err, "attach_raw_tp", "failed attach: %d\n", err)) 152 goto cleanup; 153 154 usleep(1); 155 156 t->data.kern_ver = kern_ver; 157 t->data.missing_val = 0xDEADC0DE; 158 got = (uint64_t *)skel->data; 159 exp = (uint64_t *)&t->data; 160 for (j = 0; j < n; j++) { 161 CHECK(got[j] != exp[j], "check_res", 162 "result #%d: expected %llx, but got %llx\n", 163 j, (__u64)exp[j], (__u64)got[j]); 164 } 165cleanup: 166 test_core_extern__destroy(skel); 167 skel = NULL; 168 } 169}