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