1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3 #include <test_progs.h> 4 #include <string.h> 5 #include <stdio.h> 6 7 #define __CHECK_STR(str, name) \ 8 do { \ 9 if (!ASSERT_HAS_SUBSTR(fix->output, (str), (name))) \ 10 goto out; \ 11 } while (0) 12 13 struct fixture { 14 char tmpfile[80]; 15 int fd; 16 char *output; 17 size_t sz; 18 char veristat[80]; 19 }; 20 21 static struct fixture *init_fixture(void) 22 { 23 struct fixture *fix = malloc(sizeof(struct fixture)); 24 25 /* for no_alu32 and cpuv4 veristat is in parent folder */ 26 if (access("./veristat", F_OK) == 0) 27 strcpy(fix->veristat, "./veristat"); 28 else if (access("../veristat", F_OK) == 0) 29 strcpy(fix->veristat, "../veristat"); 30 else 31 PRINT_FAIL("Can't find veristat binary"); 32 33 snprintf(fix->tmpfile, sizeof(fix->tmpfile), "/tmp/test_veristat.XXXXXX"); 34 fix->fd = mkstemp(fix->tmpfile); 35 fix->sz = 1000000; 36 fix->output = malloc(fix->sz); 37 return fix; 38 } 39 40 static void teardown_fixture(struct fixture *fix) 41 { 42 free(fix->output); 43 close(fix->fd); 44 remove(fix->tmpfile); 45 free(fix); 46 } 47 48 static void test_set_global_vars_succeeds(void) 49 { 50 struct fixture *fix = init_fixture(); 51 52 SYS(out, 53 "%s set_global_vars.bpf.o"\ 54 " -G \"var_s64 = 0xf000000000000001\" "\ 55 " -G \"var_u64 = 0xfedcba9876543210\" "\ 56 " -G \"var_s32 = -0x80000000\" "\ 57 " -G \"var_u32 = 0x76543210\" "\ 58 " -G \"var_s16 = -32768\" "\ 59 " -G \"var_u16 = 60652\" "\ 60 " -G \"var_s8 = -128\" "\ 61 " -G \"var_u8 = 255\" "\ 62 " -G \"var_ea = EA2\" "\ 63 " -G \"var_eb = EB2\" "\ 64 " -G \"var_ec=EC2\" "\ 65 " -G \"var_b = 1\" "\ 66 " -G \"struct1[2].struct2[1][2].u.var_u8[2]=170\" "\ 67 " -G \"union1.struct3.var_u8_l = 0xaa\" "\ 68 " -G \"union1.struct3.var_u8_h = 0xaa\" "\ 69 " -G \"arr[3]= 171\" " \ 70 " -G \"arr[EA2] =172\" " \ 71 " -G \"enum_arr[EC2]=EA3\" " \ 72 " -G \"three_d[31][7][EA2]=173\"" \ 73 " -G \"struct1[2].struct2[1][2].u.mat[5][3]=174\" " \ 74 " -G \"struct11 [ 7 ] [ 5 ] .struct2[0][1].u.mat[3][0] = 175\" " \ 75 " -vl2 > %s", fix->veristat, fix->tmpfile); 76 77 read(fix->fd, fix->output, fix->sz); 78 __CHECK_STR("_w=0xf000000000000001 ", "var_s64 = 0xf000000000000001"); 79 __CHECK_STR("_w=0xfedcba9876543210 ", "var_u64 = 0xfedcba9876543210"); 80 __CHECK_STR("_w=0x80000000 ", "var_s32 = -0x80000000"); 81 __CHECK_STR("_w=0x76543210 ", "var_u32 = 0x76543210"); 82 __CHECK_STR("_w=0x8000 ", "var_s16 = -32768"); 83 __CHECK_STR("_w=0xecec ", "var_u16 = 60652"); 84 __CHECK_STR("_w=128 ", "var_s8 = -128"); 85 __CHECK_STR("_w=255 ", "var_u8 = 255"); 86 __CHECK_STR("_w=11 ", "var_ea = EA2"); 87 __CHECK_STR("_w=12 ", "var_eb = EB2"); 88 __CHECK_STR("_w=13 ", "var_ec = EC2"); 89 __CHECK_STR("_w=1 ", "var_b = 1"); 90 __CHECK_STR("_w=170 ", "struct1[2].struct2[1][2].u.var_u8[2]=170"); 91 __CHECK_STR("_w=0xaaaa ", "union1.var_u16 = 0xaaaa"); 92 __CHECK_STR("_w=171 ", "arr[3]= 171"); 93 __CHECK_STR("_w=172 ", "arr[EA2] =172"); 94 __CHECK_STR("_w=10 ", "enum_arr[EC2]=EA3"); 95 __CHECK_STR("_w=173 ", "matrix[31][7][11]=173"); 96 __CHECK_STR("_w=174 ", "struct1[2].struct2[1][2].u.mat[5][3]=174"); 97 __CHECK_STR("_w=175 ", "struct11[7][5].struct2[0][1].u.mat[3][0]=175"); 98 99 out: 100 teardown_fixture(fix); 101 } 102 103 static void test_set_global_vars_from_file_succeeds(void) 104 { 105 struct fixture *fix = init_fixture(); 106 char input_file[80]; 107 const char *vars = "var_s16 = -32768\nvar_u16 = 60652"; 108 int fd; 109 110 snprintf(input_file, sizeof(input_file), "/tmp/veristat_input.XXXXXX"); 111 fd = mkstemp(input_file); 112 if (!ASSERT_GE(fd, 0, "valid fd")) 113 goto out; 114 115 write(fd, vars, strlen(vars)); 116 syncfs(fd); 117 SYS(out, "%s set_global_vars.bpf.o -G \"@%s\" -vl2 > %s", 118 fix->veristat, input_file, fix->tmpfile); 119 read(fix->fd, fix->output, fix->sz); 120 __CHECK_STR("_w=0x8000 ", "var_s16 = -32768"); 121 __CHECK_STR("_w=0xecec ", "var_u16 = 60652"); 122 123 out: 124 close(fd); 125 remove(input_file); 126 teardown_fixture(fix); 127 } 128 129 static void test_set_global_vars_out_of_range(void) 130 { 131 struct fixture *fix = init_fixture(); 132 133 SYS_FAIL(out, 134 "%s set_global_vars.bpf.o -G \"var_s32 = 2147483648\" -vl2 2> %s", 135 fix->veristat, fix->tmpfile); 136 137 read(fix->fd, fix->output, fix->sz); 138 __CHECK_STR("is out of range [-2147483648; 2147483647]", "out of range"); 139 140 out: 141 teardown_fixture(fix); 142 } 143 144 static void test_unsupported_ptr_array_type(void) 145 { 146 struct fixture *fix = init_fixture(); 147 148 SYS_FAIL(out, 149 "%s set_global_vars.bpf.o -G \"ptr_arr[0] = 0\" -vl2 2> %s", 150 fix->veristat, fix->tmpfile); 151 152 read(fix->fd, fix->output, fix->sz); 153 __CHECK_STR("Can't set ptr_arr[0]. Only ints and enums are supported", "ptr_arr"); 154 155 out: 156 teardown_fixture(fix); 157 } 158 159 static void test_array_out_of_bounds(void) 160 { 161 struct fixture *fix = init_fixture(); 162 163 SYS_FAIL(out, 164 "%s set_global_vars.bpf.o -G \"arr[99] = 0\" -vl2 2> %s", 165 fix->veristat, fix->tmpfile); 166 167 read(fix->fd, fix->output, fix->sz); 168 __CHECK_STR("Array index 99 is out of bounds", "arr[99]"); 169 170 out: 171 teardown_fixture(fix); 172 } 173 174 static void test_array_index_not_found(void) 175 { 176 struct fixture *fix = init_fixture(); 177 178 SYS_FAIL(out, 179 "%s set_global_vars.bpf.o -G \"arr[EG2] = 0\" -vl2 2> %s", 180 fix->veristat, fix->tmpfile); 181 182 read(fix->fd, fix->output, fix->sz); 183 __CHECK_STR("Can't resolve enum value EG2", "arr[EG2]"); 184 185 out: 186 teardown_fixture(fix); 187 } 188 189 static void test_array_index_for_non_array(void) 190 { 191 struct fixture *fix = init_fixture(); 192 193 SYS_FAIL(out, 194 "%s set_global_vars.bpf.o -G \"var_b[0] = 1\" -vl2 2> %s", 195 fix->veristat, fix->tmpfile); 196 197 pread(fix->fd, fix->output, fix->sz, 0); 198 __CHECK_STR("Array index is not expected for var_b", "var_b[0] = 1"); 199 200 SYS_FAIL(out, 201 "%s set_global_vars.bpf.o -G \"union1.struct3[0].var_u8_l=1\" -vl2 2> %s", 202 fix->veristat, fix->tmpfile); 203 204 pread(fix->fd, fix->output, fix->sz, 0); 205 __CHECK_STR("Array index is not expected for struct3", "union1.struct3[0].var_u8_l=1"); 206 207 out: 208 teardown_fixture(fix); 209 } 210 211 static void test_no_array_index_for_array(void) 212 { 213 struct fixture *fix = init_fixture(); 214 215 SYS_FAIL(out, 216 "%s set_global_vars.bpf.o -G \"arr = 1\" -vl2 2> %s", 217 fix->veristat, fix->tmpfile); 218 219 pread(fix->fd, fix->output, fix->sz, 0); 220 __CHECK_STR("Can't set arr. Only ints and enums are supported", "arr = 1"); 221 222 SYS_FAIL(out, 223 "%s set_global_vars.bpf.o -G \"struct1[0].struct2.u.var_u8[2]=1\" -vl2 2> %s", 224 fix->veristat, fix->tmpfile); 225 226 pread(fix->fd, fix->output, fix->sz, 0); 227 __CHECK_STR("Can't resolve field u for non-composite type", "struct1[0].struct2.u.var_u8[2]=1"); 228 229 out: 230 teardown_fixture(fix); 231 } 232 233 void test_veristat(void) 234 { 235 if (test__start_subtest("set_global_vars_succeeds")) 236 test_set_global_vars_succeeds(); 237 238 if (test__start_subtest("set_global_vars_out_of_range")) 239 test_set_global_vars_out_of_range(); 240 241 if (test__start_subtest("set_global_vars_from_file_succeeds")) 242 test_set_global_vars_from_file_succeeds(); 243 244 if (test__start_subtest("test_unsupported_ptr_array_type")) 245 test_unsupported_ptr_array_type(); 246 247 if (test__start_subtest("test_array_out_of_bounds")) 248 test_array_out_of_bounds(); 249 250 if (test__start_subtest("test_array_index_not_found")) 251 test_array_index_not_found(); 252 253 if (test__start_subtest("test_array_index_for_non_array")) 254 test_array_index_for_non_array(); 255 256 if (test__start_subtest("test_no_array_index_for_array")) 257 test_no_array_index_for_array(); 258 259 } 260 261 #undef __CHECK_STR 262