1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <limits.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 #include "debug.h" 12 #include "tests.h" 13 #include <api/io.h> 14 #include <linux/kernel.h> 15 #include <linux/zalloc.h> 16 17 #define TEMPL "/tmp/perf-test-XXXXXX" 18 19 #define EXPECT_EQUAL(val, expected) \ 20 do { \ 21 if (val != expected) { \ 22 pr_debug("%s:%d: %d != %d\n", \ 23 __FILE__, __LINE__, val, expected); \ 24 ret = -1; \ 25 } \ 26 } while (0) 27 28 #define EXPECT_EQUAL64(val, expected) \ 29 do { \ 30 if (val != expected) { \ 31 pr_debug("%s:%d: %lld != %lld\n", \ 32 __FILE__, __LINE__, val, expected); \ 33 ret = -1; \ 34 } \ 35 } while (0) 36 37 static int make_test_file(char path[PATH_MAX], const char *contents) 38 { 39 ssize_t contents_len = strlen(contents); 40 int fd; 41 42 strcpy(path, TEMPL); 43 fd = mkstemp(path); 44 if (fd < 0) { 45 pr_debug("mkstemp failed"); 46 return -1; 47 } 48 if (write(fd, contents, contents_len) < contents_len) { 49 pr_debug("short write"); 50 close(fd); 51 unlink(path); 52 return -1; 53 } 54 close(fd); 55 return 0; 56 } 57 58 static int setup_test(char path[PATH_MAX], const char *contents, 59 size_t buf_size, struct io *io) 60 { 61 if (make_test_file(path, contents)) 62 return -1; 63 64 io->fd = open(path, O_RDONLY); 65 if (io->fd < 0) { 66 pr_debug("Failed to open '%s'\n", path); 67 unlink(path); 68 return -1; 69 } 70 io->buf = malloc(buf_size); 71 if (io->buf == NULL) { 72 pr_debug("Failed to allocate memory"); 73 close(io->fd); 74 unlink(path); 75 return -1; 76 } 77 io__init(io, io->fd, io->buf, buf_size); 78 return 0; 79 } 80 81 static void cleanup_test(char path[PATH_MAX], struct io *io) 82 { 83 zfree(&io->buf); 84 close(io->fd); 85 unlink(path); 86 } 87 88 static int do_test_get_char(const char *test_string, size_t buf_size) 89 { 90 char path[PATH_MAX]; 91 struct io io; 92 int ch, ret = 0; 93 size_t i; 94 95 if (setup_test(path, test_string, buf_size, &io)) 96 return -1; 97 98 for (i = 0; i < strlen(test_string); i++) { 99 ch = io__get_char(&io); 100 101 EXPECT_EQUAL(ch, test_string[i]); 102 EXPECT_EQUAL(io.eof, false); 103 } 104 ch = io__get_char(&io); 105 EXPECT_EQUAL(ch, -1); 106 EXPECT_EQUAL(io.eof, true); 107 108 cleanup_test(path, &io); 109 return ret; 110 } 111 112 static int test_get_char(void) 113 { 114 int i, ret = 0; 115 size_t j; 116 117 static const char *const test_strings[] = { 118 "12345678abcdef90", 119 "a\nb\nc\nd\n", 120 "\a\b\t\v\f\r", 121 }; 122 for (i = 0; i <= 10; i++) { 123 for (j = 0; j < ARRAY_SIZE(test_strings); j++) { 124 if (do_test_get_char(test_strings[j], 1 << i)) 125 ret = -1; 126 } 127 } 128 return ret; 129 } 130 131 static int do_test_get_hex(const char *test_string, 132 __u64 val1, int ch1, 133 __u64 val2, int ch2, 134 __u64 val3, int ch3, 135 bool end_eof) 136 { 137 char path[PATH_MAX]; 138 struct io io; 139 int ch, ret = 0; 140 __u64 hex; 141 142 if (setup_test(path, test_string, 4, &io)) 143 return -1; 144 145 ch = io__get_hex(&io, &hex); 146 EXPECT_EQUAL64(hex, val1); 147 EXPECT_EQUAL(ch, ch1); 148 149 ch = io__get_hex(&io, &hex); 150 EXPECT_EQUAL64(hex, val2); 151 EXPECT_EQUAL(ch, ch2); 152 153 ch = io__get_hex(&io, &hex); 154 EXPECT_EQUAL64(hex, val3); 155 EXPECT_EQUAL(ch, ch3); 156 157 EXPECT_EQUAL(io.eof, end_eof); 158 159 cleanup_test(path, &io); 160 return ret; 161 } 162 163 static int test_get_hex(void) 164 { 165 int ret = 0; 166 167 if (do_test_get_hex("12345678abcdef90", 168 0x12345678abcdef90, -1, 169 0, -1, 170 0, -1, 171 true)) 172 ret = -1; 173 174 if (do_test_get_hex("1\n2\n3\n", 175 1, '\n', 176 2, '\n', 177 3, '\n', 178 false)) 179 ret = -1; 180 181 if (do_test_get_hex("12345678ABCDEF90;a;b", 182 0x12345678abcdef90, ';', 183 0xa, ';', 184 0xb, -1, 185 true)) 186 ret = -1; 187 188 if (do_test_get_hex("0x1x2x", 189 0, 'x', 190 1, 'x', 191 2, 'x', 192 false)) 193 ret = -1; 194 195 if (do_test_get_hex("x1x", 196 0, -2, 197 1, 'x', 198 0, -1, 199 true)) 200 ret = -1; 201 202 if (do_test_get_hex("10000000000000000000000000000abcdefgh99i", 203 0xabcdef, 'g', 204 0, -2, 205 0x99, 'i', 206 false)) 207 ret = -1; 208 209 return ret; 210 } 211 212 static int do_test_get_dec(const char *test_string, 213 __u64 val1, int ch1, 214 __u64 val2, int ch2, 215 __u64 val3, int ch3, 216 bool end_eof) 217 { 218 char path[PATH_MAX]; 219 struct io io; 220 int ch, ret = 0; 221 __u64 dec; 222 223 if (setup_test(path, test_string, 4, &io)) 224 return -1; 225 226 ch = io__get_dec(&io, &dec); 227 EXPECT_EQUAL64(dec, val1); 228 EXPECT_EQUAL(ch, ch1); 229 230 ch = io__get_dec(&io, &dec); 231 EXPECT_EQUAL64(dec, val2); 232 EXPECT_EQUAL(ch, ch2); 233 234 ch = io__get_dec(&io, &dec); 235 EXPECT_EQUAL64(dec, val3); 236 EXPECT_EQUAL(ch, ch3); 237 238 EXPECT_EQUAL(io.eof, end_eof); 239 240 cleanup_test(path, &io); 241 return ret; 242 } 243 244 static int test_get_dec(void) 245 { 246 int ret = 0; 247 248 if (do_test_get_dec("12345678abcdef90", 249 12345678, 'a', 250 0, -2, 251 0, -2, 252 false)) 253 ret = -1; 254 255 if (do_test_get_dec("1\n2\n3\n", 256 1, '\n', 257 2, '\n', 258 3, '\n', 259 false)) 260 ret = -1; 261 262 if (do_test_get_dec("12345678;1;2", 263 12345678, ';', 264 1, ';', 265 2, -1, 266 true)) 267 ret = -1; 268 269 if (do_test_get_dec("0x1x2x", 270 0, 'x', 271 1, 'x', 272 2, 'x', 273 false)) 274 ret = -1; 275 276 if (do_test_get_dec("x1x", 277 0, -2, 278 1, 'x', 279 0, -1, 280 true)) 281 ret = -1; 282 283 if (do_test_get_dec("10000000000000000000000000000000000000000000000000000000000123456789ab99c", 284 123456789, 'a', 285 0, -2, 286 99, 'c', 287 false)) 288 ret = -1; 289 290 return ret; 291 } 292 293 static int test_get_line(void) 294 { 295 char path[PATH_MAX]; 296 struct io io; 297 char test_string[1024]; 298 char *line = NULL; 299 size_t i, line_len = 0; 300 size_t buf_size = 128; 301 int ret = 0; 302 303 for (i = 0; i < 512; i++) 304 test_string[i] = 'a'; 305 test_string[512] = '\n'; 306 for (i = 513; i < 1023; i++) 307 test_string[i] = 'b'; 308 test_string[1023] = '\0'; 309 310 if (setup_test(path, test_string, buf_size, &io)) 311 return -1; 312 313 EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 513); 314 EXPECT_EQUAL((int)strlen(line), 513); 315 for (i = 0; i < 512; i++) 316 EXPECT_EQUAL(line[i], 'a'); 317 EXPECT_EQUAL(line[512], '\n'); 318 EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 510); 319 for (i = 0; i < 510; i++) 320 EXPECT_EQUAL(line[i], 'b'); 321 322 free(line); 323 cleanup_test(path, &io); 324 return ret; 325 } 326 327 static int test__api_io(struct test_suite *test __maybe_unused, 328 int subtest __maybe_unused) 329 { 330 int ret = 0; 331 332 if (test_get_char()) 333 ret = TEST_FAIL; 334 if (test_get_hex()) 335 ret = TEST_FAIL; 336 if (test_get_dec()) 337 ret = TEST_FAIL; 338 if (test_get_line()) 339 ret = TEST_FAIL; 340 return ret; 341 } 342 343 DEFINE_SUITE("Test api io", api_io); 344