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