1 /* 2 * linux and CPU test 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #define _GNU_SOURCE 20 #include <stdarg.h> 21 #include <stdlib.h> 22 #include <stdio.h> 23 #include <unistd.h> 24 #include <fcntl.h> 25 #include <inttypes.h> 26 #include <string.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/wait.h> 30 #include <errno.h> 31 #include <utime.h> 32 #include <time.h> 33 #include <sys/time.h> 34 #include <sys/resource.h> 35 #include <sys/uio.h> 36 #include <sys/socket.h> 37 #include <netinet/in.h> 38 #include <arpa/inet.h> 39 #include <sched.h> 40 #include <dirent.h> 41 #include <setjmp.h> 42 #include <sys/shm.h> 43 #include <assert.h> 44 45 #define STACK_SIZE 16384 46 47 static void error1(const char *filename, int line, const char *fmt, ...) 48 { 49 va_list ap; 50 va_start(ap, fmt); 51 fprintf(stderr, "%s:%d: ", filename, line); 52 vfprintf(stderr, fmt, ap); 53 fprintf(stderr, "\n"); 54 va_end(ap); 55 exit(1); 56 } 57 58 static int __chk_error(const char *filename, int line, int ret) 59 { 60 if (ret < 0) { 61 error1(filename, line, "%m (ret=%d, errno=%d/%s)", 62 ret, errno, strerror(errno)); 63 } 64 return ret; 65 } 66 67 #define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__) 68 69 #define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret)) 70 71 /*******************************************************/ 72 73 #define FILE_BUF_SIZE 300 74 75 static void test_file(void) 76 { 77 int fd, i, len, ret; 78 uint8_t buf[FILE_BUF_SIZE]; 79 uint8_t buf2[FILE_BUF_SIZE]; 80 uint8_t buf3[FILE_BUF_SIZE]; 81 char cur_dir[1024]; 82 struct stat st; 83 struct utimbuf tbuf; 84 struct iovec vecs[2]; 85 DIR *dir; 86 struct dirent64 *de; 87 /* TODO: make common tempdir creation for tcg tests */ 88 char template[] = "/tmp/linux-test-XXXXXX"; 89 char *tmpdir = mkdtemp(template); 90 91 assert(tmpdir); 92 93 if (getcwd(cur_dir, sizeof(cur_dir)) == NULL) 94 error("getcwd"); 95 96 chk_error(chdir(tmpdir)); 97 98 /* open/read/write/close/readv/writev/lseek */ 99 100 fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644)); 101 for(i=0;i < FILE_BUF_SIZE; i++) 102 buf[i] = i; 103 len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2)); 104 if (len != (FILE_BUF_SIZE / 2)) 105 error("write"); 106 vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2); 107 vecs[0].iov_len = 16; 108 vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16; 109 vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16; 110 len = chk_error(writev(fd, vecs, 2)); 111 if (len != (FILE_BUF_SIZE / 2)) 112 error("writev"); 113 chk_error(close(fd)); 114 115 chk_error(rename("file1", "file2")); 116 117 fd = chk_error(open("file2", O_RDONLY)); 118 119 len = chk_error(read(fd, buf2, FILE_BUF_SIZE)); 120 if (len != FILE_BUF_SIZE) 121 error("read"); 122 if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0) 123 error("memcmp"); 124 125 #define FOFFSET 16 126 ret = chk_error(lseek(fd, FOFFSET, SEEK_SET)); 127 if (ret != 16) 128 error("lseek"); 129 vecs[0].iov_base = buf3; 130 vecs[0].iov_len = 32; 131 vecs[1].iov_base = buf3 + 32; 132 vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32; 133 len = chk_error(readv(fd, vecs, 2)); 134 if (len != FILE_BUF_SIZE - FOFFSET) 135 error("readv"); 136 if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0) 137 error("memcmp"); 138 139 chk_error(close(fd)); 140 141 /* access */ 142 chk_error(access("file2", R_OK)); 143 144 /* stat/chmod/utime/truncate */ 145 146 chk_error(chmod("file2", 0600)); 147 tbuf.actime = 1001; 148 tbuf.modtime = 1000; 149 chk_error(truncate("file2", 100)); 150 chk_error(utime("file2", &tbuf)); 151 chk_error(stat("file2", &st)); 152 if (st.st_size != 100) 153 error("stat size"); 154 if (!S_ISREG(st.st_mode)) 155 error("stat mode"); 156 if ((st.st_mode & 0777) != 0600) 157 error("stat mode2"); 158 /* 159 * Only check mtime, not atime: other processes such as 160 * virus scanners might race with this test program and get 161 * in and update the atime, causing random failures. 162 */ 163 if (st.st_mtime != 1000) { 164 error("stat time"); 165 } 166 167 chk_error(stat(tmpdir, &st)); 168 if (!S_ISDIR(st.st_mode)) 169 error("stat mode"); 170 171 /* fstat */ 172 fd = chk_error(open("file2", O_RDWR)); 173 chk_error(ftruncate(fd, 50)); 174 chk_error(fstat(fd, &st)); 175 chk_error(close(fd)); 176 177 if (st.st_size != 50) 178 error("stat size"); 179 if (!S_ISREG(st.st_mode)) 180 error("stat mode"); 181 182 /* symlink/lstat */ 183 chk_error(symlink("file2", "file3")); 184 chk_error(lstat("file3", &st)); 185 if (!S_ISLNK(st.st_mode)) 186 error("stat mode"); 187 188 /* getdents */ 189 dir = opendir(tmpdir); 190 if (!dir) 191 error("opendir"); 192 len = 0; 193 for(;;) { 194 de = readdir64(dir); 195 if (!de) 196 break; 197 if (strcmp(de->d_name, ".") != 0 && 198 strcmp(de->d_name, "..") != 0 && 199 strcmp(de->d_name, "file2") != 0 && 200 strcmp(de->d_name, "file3") != 0) 201 error("readdir"); 202 len++; 203 } 204 closedir(dir); 205 if (len != 4) 206 error("readdir"); 207 208 chk_error(unlink("file3")); 209 chk_error(unlink("file2")); 210 chk_error(chdir(cur_dir)); 211 chk_error(rmdir(tmpdir)); 212 } 213 214 static void test_fork(void) 215 { 216 int pid, status; 217 218 pid = chk_error(fork()); 219 if (pid == 0) { 220 /* child */ 221 sleep(2); 222 exit(2); 223 } 224 chk_error(waitpid(pid, &status, 0)); 225 if (!WIFEXITED(status) || WEXITSTATUS(status) != 2) 226 error("waitpid status=0x%x", status); 227 } 228 229 static void test_time(void) 230 { 231 struct timeval tv, tv2; 232 struct timespec ts, rem; 233 struct rusage rusg1, rusg2; 234 int ti, i; 235 236 chk_error(gettimeofday(&tv, NULL)); 237 rem.tv_sec = 1; 238 ts.tv_sec = 0; 239 ts.tv_nsec = 20 * 1000000; 240 chk_error(nanosleep(&ts, &rem)); 241 if (rem.tv_sec != 1) 242 error("nanosleep"); 243 chk_error(gettimeofday(&tv2, NULL)); 244 ti = tv2.tv_sec - tv.tv_sec; 245 if (ti >= 2) 246 error("gettimeofday"); 247 248 chk_error(getrusage(RUSAGE_SELF, &rusg1)); 249 for(i = 0;i < 10000; i++); 250 chk_error(getrusage(RUSAGE_SELF, &rusg2)); 251 if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 || 252 (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0) 253 error("getrusage"); 254 } 255 256 static int server_socket(void) 257 { 258 int val, fd; 259 struct sockaddr_in sockaddr = {}; 260 261 /* server socket */ 262 fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); 263 264 val = 1; 265 chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))); 266 267 sockaddr.sin_family = AF_INET; 268 sockaddr.sin_port = htons(0); /* choose random ephemeral port) */ 269 sockaddr.sin_addr.s_addr = 0; 270 chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); 271 chk_error(listen(fd, 1)); 272 return fd; 273 274 } 275 276 static int client_socket(uint16_t port) 277 { 278 int fd; 279 struct sockaddr_in sockaddr = {}; 280 281 /* server socket */ 282 fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); 283 sockaddr.sin_family = AF_INET; 284 sockaddr.sin_port = htons(port); 285 inet_aton("127.0.0.1", &sockaddr.sin_addr); 286 chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); 287 return fd; 288 } 289 290 static const char socket_msg[] = "hello socket\n"; 291 292 static void test_socket(void) 293 { 294 int server_fd, client_fd, fd, pid, ret, val; 295 struct sockaddr_in sockaddr; 296 struct sockaddr_in server_addr; 297 socklen_t len, socklen; 298 uint16_t server_port; 299 char buf[512]; 300 301 server_fd = server_socket(); 302 /* find out what port we got */ 303 socklen = sizeof(server_addr); 304 ret = getsockname(server_fd, (struct sockaddr *)&server_addr, &socklen); 305 chk_error(ret); 306 server_port = ntohs(server_addr.sin_port); 307 308 /* test a few socket options */ 309 len = sizeof(val); 310 chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len)); 311 if (val != SOCK_STREAM) 312 error("getsockopt"); 313 314 pid = chk_error(fork()); 315 if (pid == 0) { 316 client_fd = client_socket(server_port); 317 send(client_fd, socket_msg, sizeof(socket_msg), 0); 318 close(client_fd); 319 exit(0); 320 } 321 len = sizeof(sockaddr); 322 fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len)); 323 324 ret = chk_error(recv(fd, buf, sizeof(buf), 0)); 325 if (ret != sizeof(socket_msg)) 326 error("recv"); 327 if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0) 328 error("socket_msg"); 329 chk_error(close(fd)); 330 chk_error(close(server_fd)); 331 } 332 333 #define WCOUNT_MAX 512 334 335 static void test_pipe(void) 336 { 337 fd_set rfds, wfds; 338 int fds[2], fd_max, ret; 339 uint8_t ch; 340 int wcount, rcount; 341 342 chk_error(pipe(fds)); 343 chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK)); 344 chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK)); 345 wcount = 0; 346 rcount = 0; 347 for(;;) { 348 FD_ZERO(&rfds); 349 fd_max = fds[0]; 350 FD_SET(fds[0], &rfds); 351 352 FD_ZERO(&wfds); 353 FD_SET(fds[1], &wfds); 354 if (fds[1] > fd_max) 355 fd_max = fds[1]; 356 357 ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL)); 358 if (ret > 0) { 359 if (FD_ISSET(fds[0], &rfds)) { 360 chk_error(read(fds[0], &ch, 1)); 361 rcount++; 362 if (rcount >= WCOUNT_MAX) { 363 break; 364 } 365 } 366 if (FD_ISSET(fds[1], &wfds)) { 367 ch = 'a'; 368 chk_error(write(fds[1], &ch, 1)); 369 wcount++; 370 if (wcount >= WCOUNT_MAX) { 371 break; 372 } 373 } 374 } 375 } 376 chk_error(close(fds[0])); 377 chk_error(close(fds[1])); 378 } 379 380 static int thread1_res; 381 static int thread2_res; 382 383 static int thread1_func(void *arg) 384 { 385 int i; 386 for(i=0;i<5;i++) { 387 thread1_res++; 388 usleep(10 * 1000); 389 } 390 return 0; 391 } 392 393 static int thread2_func(void *arg) 394 { 395 int i; 396 for(i=0;i<6;i++) { 397 thread2_res++; 398 usleep(10 * 1000); 399 } 400 return 0; 401 } 402 403 static void wait_for_child(pid_t pid) 404 { 405 int status; 406 chk_error(waitpid(pid, &status, 0)); 407 } 408 409 /* For test_clone we must match the clone flags used by glibc, see 410 * CLONE_THREAD_FLAGS in the QEMU source code. 411 */ 412 static void test_clone(void) 413 { 414 uint8_t *stack1, *stack2; 415 pid_t pid1, pid2; 416 417 stack1 = malloc(STACK_SIZE); 418 pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE, 419 CLONE_VM | CLONE_FS | CLONE_FILES | 420 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM, 421 "hello1")); 422 423 stack2 = malloc(STACK_SIZE); 424 pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE, 425 CLONE_VM | CLONE_FS | CLONE_FILES | 426 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM, 427 "hello2")); 428 429 wait_for_child(pid1); 430 free(stack1); 431 wait_for_child(pid2); 432 free(stack2); 433 434 if (thread1_res != 5 || 435 thread2_res != 6) 436 error("clone"); 437 } 438 439 /***********************************/ 440 441 volatile int alarm_count; 442 jmp_buf jmp_env; 443 444 static void sig_alarm(int sig) 445 { 446 if (sig != SIGALRM) 447 error("signal"); 448 alarm_count++; 449 } 450 451 static void sig_segv(int sig, siginfo_t *info, void *puc) 452 { 453 if (sig != SIGSEGV) 454 error("signal"); 455 longjmp(jmp_env, 1); 456 } 457 458 static void test_signal(void) 459 { 460 struct sigaction act; 461 struct itimerval it, oit; 462 463 /* timer test */ 464 465 alarm_count = 0; 466 467 act.sa_handler = sig_alarm; 468 sigemptyset(&act.sa_mask); 469 act.sa_flags = 0; 470 chk_error(sigaction(SIGALRM, &act, NULL)); 471 472 it.it_interval.tv_sec = 0; 473 it.it_interval.tv_usec = 10 * 1000; 474 it.it_value.tv_sec = 0; 475 it.it_value.tv_usec = 10 * 1000; 476 chk_error(setitimer(ITIMER_REAL, &it, NULL)); 477 chk_error(getitimer(ITIMER_REAL, &oit)); 478 479 while (alarm_count < 5) { 480 usleep(10 * 1000); 481 getitimer(ITIMER_REAL, &oit); 482 } 483 484 it.it_interval.tv_sec = 0; 485 it.it_interval.tv_usec = 0; 486 it.it_value.tv_sec = 0; 487 it.it_value.tv_usec = 0; 488 memset(&oit, 0xff, sizeof(oit)); 489 chk_error(setitimer(ITIMER_REAL, &it, &oit)); 490 491 /* SIGSEGV test */ 492 act.sa_sigaction = sig_segv; 493 sigemptyset(&act.sa_mask); 494 act.sa_flags = SA_SIGINFO; 495 chk_error(sigaction(SIGSEGV, &act, NULL)); 496 if (setjmp(jmp_env) == 0) { 497 /* 498 * clang requires volatile or it will turn this into a 499 * call to abort() instead of forcing a SIGSEGV. 500 */ 501 *(volatile uint8_t *)0 = 0; 502 } 503 504 act.sa_handler = SIG_DFL; 505 sigemptyset(&act.sa_mask); 506 act.sa_flags = 0; 507 chk_error(sigaction(SIGSEGV, &act, NULL)); 508 509 if (sigaction(SIGKILL, &act, NULL) == 0) { 510 error("sigaction(SIGKILL, &act, NULL) must not succeed"); 511 } 512 if (sigaction(SIGSTOP, &act, NULL) == 0) { 513 error("sigaction(SIGSTOP, &act, NULL) must not succeed"); 514 } 515 chk_error(sigaction(SIGKILL, NULL, &act)); 516 chk_error(sigaction(SIGSTOP, NULL, &act)); 517 } 518 519 #define SHM_SIZE 32768 520 521 static void test_shm(void) 522 { 523 void *ptr; 524 int shmid; 525 526 shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777)); 527 ptr = shmat(shmid, NULL, 0); 528 if (ptr == (void *)-1) { 529 error("shmat"); 530 } 531 532 memset(ptr, 0, SHM_SIZE); 533 534 chk_error(shmctl(shmid, IPC_RMID, 0)); 535 chk_error(shmdt(ptr)); 536 } 537 538 int main(int argc, char **argv) 539 { 540 test_file(); 541 test_pipe(); 542 test_fork(); 543 test_time(); 544 test_socket(); 545 546 if (argc > 1) { 547 printf("test_clone still considered buggy\n"); 548 test_clone(); 549 } 550 551 test_signal(); 552 test_shm(); 553 return 0; 554 } 555