|
|
1.1 ! root 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: #include <stdarg.h> ! 20: #include <stdlib.h> ! 21: #include <stdio.h> ! 22: #include <unistd.h> ! 23: #include <fcntl.h> ! 24: #include <inttypes.h> ! 25: #include <string.h> ! 26: #include <sys/types.h> ! 27: #include <sys/stat.h> ! 28: #include <sys/wait.h> ! 29: #include <errno.h> ! 30: #include <utime.h> ! 31: #include <time.h> ! 32: #include <sys/time.h> ! 33: #include <sys/uio.h> ! 34: #include <sys/socket.h> ! 35: #include <netinet/in.h> ! 36: #include <arpa/inet.h> ! 37: #include <sched.h> ! 38: #include <dirent.h> ! 39: #include <setjmp.h> ! 40: #include <sys/shm.h> ! 41: ! 42: #define TESTPATH "/tmp/linux-test.tmp" ! 43: #define TESTPORT 7654 ! 44: #define STACK_SIZE 16384 ! 45: ! 46: void error1(const char *filename, int line, const char *fmt, ...) ! 47: { ! 48: va_list ap; ! 49: va_start(ap, fmt); ! 50: fprintf(stderr, "%s:%d: ", filename, line); ! 51: vfprintf(stderr, fmt, ap); ! 52: fprintf(stderr, "\n"); ! 53: va_end(ap); ! 54: exit(1); ! 55: } ! 56: ! 57: int __chk_error(const char *filename, int line, int ret) ! 58: { ! 59: if (ret < 0) { ! 60: error1(filename, line, "%m (ret=%d, errno=%d)", ! 61: ret, errno); ! 62: } ! 63: return ret; ! 64: } ! 65: ! 66: #define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__) ! 67: ! 68: #define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret)) ! 69: ! 70: /*******************************************************/ ! 71: ! 72: #define FILE_BUF_SIZE 300 ! 73: ! 74: void test_file(void) ! 75: { ! 76: int fd, i, len, ret; ! 77: uint8_t buf[FILE_BUF_SIZE]; ! 78: uint8_t buf2[FILE_BUF_SIZE]; ! 79: uint8_t buf3[FILE_BUF_SIZE]; ! 80: char cur_dir[1024]; ! 81: struct stat st; ! 82: struct utimbuf tbuf; ! 83: struct iovec vecs[2]; ! 84: DIR *dir; ! 85: struct dirent *de; ! 86: ! 87: /* clean up, just in case */ ! 88: unlink(TESTPATH "/file1"); ! 89: unlink(TESTPATH "/file2"); ! 90: unlink(TESTPATH "/file3"); ! 91: rmdir(TESTPATH); ! 92: ! 93: if (getcwd(cur_dir, sizeof(cur_dir)) == NULL) ! 94: error("getcwd"); ! 95: ! 96: chk_error(mkdir(TESTPATH, 0755)); ! 97: ! 98: chk_error(chdir(TESTPATH)); ! 99: ! 100: /* open/read/write/close/readv/writev/lseek */ ! 101: ! 102: fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644)); ! 103: for(i=0;i < FILE_BUF_SIZE; i++) ! 104: buf[i] = i; ! 105: len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2)); ! 106: if (len != (FILE_BUF_SIZE / 2)) ! 107: error("write"); ! 108: vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2); ! 109: vecs[0].iov_len = 16; ! 110: vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16; ! 111: vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16; ! 112: len = chk_error(writev(fd, vecs, 2)); ! 113: if (len != (FILE_BUF_SIZE / 2)) ! 114: error("writev"); ! 115: chk_error(close(fd)); ! 116: ! 117: chk_error(rename("file1", "file2")); ! 118: ! 119: fd = chk_error(open("file2", O_RDONLY)); ! 120: ! 121: len = chk_error(read(fd, buf2, FILE_BUF_SIZE)); ! 122: if (len != FILE_BUF_SIZE) ! 123: error("read"); ! 124: if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0) ! 125: error("memcmp"); ! 126: ! 127: #define FOFFSET 16 ! 128: ret = chk_error(lseek(fd, FOFFSET, SEEK_SET)); ! 129: if (ret != 16) ! 130: error("lseek"); ! 131: vecs[0].iov_base = buf3; ! 132: vecs[0].iov_len = 32; ! 133: vecs[1].iov_base = buf3 + 32; ! 134: vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32; ! 135: len = chk_error(readv(fd, vecs, 2)); ! 136: if (len != FILE_BUF_SIZE - FOFFSET) ! 137: error("readv"); ! 138: if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0) ! 139: error("memcmp"); ! 140: ! 141: chk_error(close(fd)); ! 142: ! 143: /* access */ ! 144: chk_error(access("file2", R_OK)); ! 145: ! 146: /* stat/chmod/utime/truncate */ ! 147: ! 148: chk_error(chmod("file2", 0600)); ! 149: tbuf.actime = 1001; ! 150: tbuf.modtime = 1000; ! 151: chk_error(truncate("file2", 100)); ! 152: chk_error(utime("file2", &tbuf)); ! 153: chk_error(stat("file2", &st)); ! 154: if (st.st_size != 100) ! 155: error("stat size"); ! 156: if (!S_ISREG(st.st_mode)) ! 157: error("stat mode"); ! 158: if ((st.st_mode & 0777) != 0600) ! 159: error("stat mode2"); ! 160: if (st.st_atime != 1001 || ! 161: st.st_mtime != 1000) ! 162: error("stat time"); ! 163: ! 164: chk_error(stat(TESTPATH, &st)); ! 165: if (!S_ISDIR(st.st_mode)) ! 166: error("stat mode"); ! 167: ! 168: /* fstat */ ! 169: fd = chk_error(open("file2", O_RDWR)); ! 170: chk_error(ftruncate(fd, 50)); ! 171: chk_error(fstat(fd, &st)); ! 172: chk_error(close(fd)); ! 173: ! 174: if (st.st_size != 50) ! 175: error("stat size"); ! 176: if (!S_ISREG(st.st_mode)) ! 177: error("stat mode"); ! 178: ! 179: /* symlink/lstat */ ! 180: chk_error(symlink("file2", "file3")); ! 181: chk_error(lstat("file3", &st)); ! 182: if (!S_ISLNK(st.st_mode)) ! 183: error("stat mode"); ! 184: ! 185: /* getdents */ ! 186: dir = opendir(TESTPATH); ! 187: if (!dir) ! 188: error("opendir"); ! 189: len = 0; ! 190: for(;;) { ! 191: de = readdir(dir); ! 192: if (!de) ! 193: break; ! 194: if (strcmp(de->d_name, ".") != 0 && ! 195: strcmp(de->d_name, "..") != 0 && ! 196: strcmp(de->d_name, "file2") != 0 && ! 197: strcmp(de->d_name, "file3") != 0) ! 198: error("readdir"); ! 199: len++; ! 200: } ! 201: closedir(dir); ! 202: if (len != 4) ! 203: error("readdir"); ! 204: ! 205: chk_error(unlink("file3")); ! 206: chk_error(unlink("file2")); ! 207: chk_error(chdir(cur_dir)); ! 208: chk_error(rmdir(TESTPATH)); ! 209: } ! 210: ! 211: void test_fork(void) ! 212: { ! 213: int pid, status; ! 214: ! 215: pid = chk_error(fork()); ! 216: if (pid == 0) { ! 217: /* child */ ! 218: exit(2); ! 219: } ! 220: chk_error(waitpid(pid, &status, 0)); ! 221: if (!WIFEXITED(status) || WEXITSTATUS(status) != 2) ! 222: error("waitpid status=0x%x", status); ! 223: } ! 224: ! 225: void test_time(void) ! 226: { ! 227: struct timeval tv, tv2; ! 228: struct timespec ts, rem; ! 229: struct rusage rusg1, rusg2; ! 230: int ti, i; ! 231: ! 232: chk_error(gettimeofday(&tv, NULL)); ! 233: rem.tv_sec = 1; ! 234: ts.tv_sec = 0; ! 235: ts.tv_nsec = 20 * 1000000; ! 236: chk_error(nanosleep(&ts, &rem)); ! 237: if (rem.tv_sec != 1) ! 238: error("nanosleep"); ! 239: chk_error(gettimeofday(&tv2, NULL)); ! 240: ti = tv2.tv_sec - tv.tv_sec; ! 241: if (ti >= 2) ! 242: error("gettimeofday"); ! 243: ! 244: chk_error(getrusage(RUSAGE_SELF, &rusg1)); ! 245: for(i = 0;i < 10000; i++); ! 246: chk_error(getrusage(RUSAGE_SELF, &rusg2)); ! 247: if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 || ! 248: (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0) ! 249: error("getrusage"); ! 250: } ! 251: ! 252: void pstrcpy(char *buf, int buf_size, const char *str) ! 253: { ! 254: int c; ! 255: char *q = buf; ! 256: ! 257: if (buf_size <= 0) ! 258: return; ! 259: ! 260: for(;;) { ! 261: c = *str++; ! 262: if (c == 0 || q >= buf + buf_size - 1) ! 263: break; ! 264: *q++ = c; ! 265: } ! 266: *q = '\0'; ! 267: } ! 268: ! 269: /* strcat and truncate. */ ! 270: char *pstrcat(char *buf, int buf_size, const char *s) ! 271: { ! 272: int len; ! 273: len = strlen(buf); ! 274: if (len < buf_size) ! 275: pstrcpy(buf + len, buf_size - len, s); ! 276: return buf; ! 277: } ! 278: ! 279: int server_socket(void) ! 280: { ! 281: int val, fd; ! 282: struct sockaddr_in sockaddr; ! 283: ! 284: /* server socket */ ! 285: fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); ! 286: ! 287: val = 1; ! 288: chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))); ! 289: ! 290: sockaddr.sin_family = AF_INET; ! 291: sockaddr.sin_port = htons(TESTPORT); ! 292: sockaddr.sin_addr.s_addr = 0; ! 293: chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); ! 294: chk_error(listen(fd, 0)); ! 295: return fd; ! 296: ! 297: } ! 298: ! 299: int client_socket(void) ! 300: { ! 301: int fd; ! 302: struct sockaddr_in sockaddr; ! 303: ! 304: /* server socket */ ! 305: fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); ! 306: sockaddr.sin_family = AF_INET; ! 307: sockaddr.sin_port = htons(TESTPORT); ! 308: inet_aton("127.0.0.1", &sockaddr.sin_addr); ! 309: chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); ! 310: return fd; ! 311: } ! 312: ! 313: const char socket_msg[] = "hello socket\n"; ! 314: ! 315: void test_socket(void) ! 316: { ! 317: int server_fd, client_fd, fd, pid, ret, val; ! 318: struct sockaddr_in sockaddr; ! 319: socklen_t len; ! 320: char buf[512]; ! 321: ! 322: server_fd = server_socket(); ! 323: ! 324: /* test a few socket options */ ! 325: len = sizeof(val); ! 326: chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len)); ! 327: if (val != SOCK_STREAM) ! 328: error("getsockopt"); ! 329: ! 330: pid = chk_error(fork()); ! 331: if (pid == 0) { ! 332: client_fd = client_socket(); ! 333: send(client_fd, socket_msg, sizeof(socket_msg), 0); ! 334: close(client_fd); ! 335: exit(0); ! 336: } ! 337: len = sizeof(sockaddr); ! 338: fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len)); ! 339: ! 340: ret = chk_error(recv(fd, buf, sizeof(buf), 0)); ! 341: if (ret != sizeof(socket_msg)) ! 342: error("recv"); ! 343: if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0) ! 344: error("socket_msg"); ! 345: chk_error(close(fd)); ! 346: chk_error(close(server_fd)); ! 347: } ! 348: ! 349: #define WCOUNT_MAX 512 ! 350: ! 351: void test_pipe(void) ! 352: { ! 353: fd_set rfds, wfds; ! 354: int fds[2], fd_max, ret; ! 355: uint8_t ch; ! 356: int wcount, rcount; ! 357: ! 358: chk_error(pipe(fds)); ! 359: chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK)); ! 360: chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK)); ! 361: wcount = 0; ! 362: rcount = 0; ! 363: for(;;) { ! 364: FD_ZERO(&rfds); ! 365: fd_max = fds[0]; ! 366: FD_SET(fds[0], &rfds); ! 367: ! 368: FD_ZERO(&wfds); ! 369: FD_SET(fds[1], &wfds); ! 370: if (fds[1] > fd_max) ! 371: fd_max = fds[1]; ! 372: ! 373: ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL)); ! 374: if (ret > 0) { ! 375: if (FD_ISSET(fds[0], &rfds)) { ! 376: chk_error(read(fds[0], &ch, 1)); ! 377: rcount++; ! 378: if (rcount >= WCOUNT_MAX) ! 379: break; ! 380: } ! 381: if (FD_ISSET(fds[1], &wfds)) { ! 382: ch = 'a'; ! 383: chk_error(write(fds[0], &ch, 1)); ! 384: wcount++; ! 385: } ! 386: } ! 387: } ! 388: chk_error(close(fds[0])); ! 389: chk_error(close(fds[1])); ! 390: } ! 391: ! 392: int thread1_res; ! 393: int thread2_res; ! 394: ! 395: int thread1_func(void *arg) ! 396: { ! 397: int i; ! 398: for(i=0;i<5;i++) { ! 399: thread1_res++; ! 400: usleep(10 * 1000); ! 401: } ! 402: return 0; ! 403: } ! 404: ! 405: int thread2_func(void *arg) ! 406: { ! 407: int i; ! 408: for(i=0;i<6;i++) { ! 409: thread2_res++; ! 410: usleep(10 * 1000); ! 411: } ! 412: return 0; ! 413: } ! 414: ! 415: void test_clone(void) ! 416: { ! 417: uint8_t *stack1, *stack2; ! 418: int pid1, pid2, status1, status2; ! 419: ! 420: stack1 = malloc(STACK_SIZE); ! 421: pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE, ! 422: CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1")); ! 423: ! 424: stack2 = malloc(STACK_SIZE); ! 425: pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE, ! 426: CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2")); ! 427: ! 428: while (waitpid(pid1, &status1, 0) != pid1); ! 429: free(stack1); ! 430: while (waitpid(pid2, &status2, 0) != pid2); ! 431: free(stack2); ! 432: if (thread1_res != 5 || ! 433: thread2_res != 6) ! 434: error("clone"); ! 435: } ! 436: ! 437: /***********************************/ ! 438: ! 439: volatile int alarm_count; ! 440: jmp_buf jmp_env; ! 441: ! 442: void sig_alarm(int sig) ! 443: { ! 444: if (sig != SIGALRM) ! 445: error("signal"); ! 446: alarm_count++; ! 447: } ! 448: ! 449: void sig_segv(int sig, siginfo_t *info, void *puc) ! 450: { ! 451: if (sig != SIGSEGV) ! 452: error("signal"); ! 453: longjmp(jmp_env, 1); ! 454: } ! 455: ! 456: void test_signal(void) ! 457: { ! 458: struct sigaction act; ! 459: struct itimerval it, oit; ! 460: ! 461: /* timer test */ ! 462: ! 463: alarm_count = 0; ! 464: ! 465: act.sa_handler = sig_alarm; ! 466: sigemptyset(&act.sa_mask); ! 467: act.sa_flags = 0; ! 468: chk_error(sigaction(SIGALRM, &act, NULL)); ! 469: ! 470: it.it_interval.tv_sec = 0; ! 471: it.it_interval.tv_usec = 10 * 1000; ! 472: it.it_value.tv_sec = 0; ! 473: it.it_value.tv_usec = 10 * 1000; ! 474: chk_error(setitimer(ITIMER_REAL, &it, NULL)); ! 475: chk_error(getitimer(ITIMER_REAL, &oit)); ! 476: if (oit.it_value.tv_sec != it.it_value.tv_sec || ! 477: oit.it_value.tv_usec != it.it_value.tv_usec) ! 478: error("itimer"); ! 479: ! 480: while (alarm_count < 5) { ! 481: usleep(10 * 1000); ! 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: if (oit.it_value.tv_sec != 0 || ! 491: oit.it_value.tv_usec != 10 * 1000) ! 492: error("setitimer"); ! 493: ! 494: /* SIGSEGV test */ ! 495: act.sa_sigaction = sig_segv; ! 496: sigemptyset(&act.sa_mask); ! 497: act.sa_flags = SA_SIGINFO; ! 498: chk_error(sigaction(SIGSEGV, &act, NULL)); ! 499: if (setjmp(jmp_env) == 0) { ! 500: *(uint8_t *)0 = 0; ! 501: } ! 502: ! 503: act.sa_handler = SIG_DFL; ! 504: sigemptyset(&act.sa_mask); ! 505: act.sa_flags = 0; ! 506: chk_error(sigaction(SIGSEGV, &act, NULL)); ! 507: } ! 508: ! 509: #define SHM_SIZE 32768 ! 510: ! 511: void test_shm(void) ! 512: { ! 513: void *ptr; ! 514: int shmid; ! 515: ! 516: shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777)); ! 517: ptr = shmat(shmid, NULL, 0); ! 518: if (!ptr) ! 519: error("shmat"); ! 520: ! 521: memset(ptr, 0, SHM_SIZE); ! 522: ! 523: chk_error(shmctl(shmid, IPC_RMID, 0)); ! 524: chk_error(shmdt(ptr)); ! 525: } ! 526: ! 527: int main(int argc, char **argv) ! 528: { ! 529: test_file(); ! 530: test_fork(); ! 531: test_time(); ! 532: test_socket(); ! 533: // test_clone(); ! 534: test_signal(); ! 535: test_shm(); ! 536: return 0; ! 537: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.