Commit 196ad10903ee4c2148f296600f537d7028ea845d

Authored by bellard
1 parent b7dda06a

portable Linux test


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@384 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 510 additions and 0 deletions
tests/linux-test.c 0 → 100644
  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 +
  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, args...) error1(__FILE__, __LINE__, fmt, ##args)
  67 +
  68 +#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
  69 +
  70 +/*******************************************************/
  71 +
  72 +#define FILE_BUF_SIZE 300
  73 +
  74 +void file_test(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;
  318 + struct sockaddr_in sockaddr;
  319 + socklen_t len;
  320 + char buf[512];
  321 +
  322 + server_fd = server_socket();
  323 + pid = chk_error(fork());
  324 + if (pid == 0) {
  325 + client_fd = client_socket();
  326 + send(client_fd, socket_msg, sizeof(socket_msg), 0);
  327 + close(client_fd);
  328 + exit(0);
  329 + }
  330 + len = sizeof(sockaddr);
  331 + fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len));
  332 +
  333 + ret = chk_error(recv(fd, buf, sizeof(buf), 0));
  334 + if (ret != sizeof(socket_msg))
  335 + error("recv");
  336 + if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0)
  337 + error("socket_msg");
  338 + chk_error(close(fd));
  339 + chk_error(close(server_fd));
  340 +}
  341 +
  342 +#define WCOUNT_MAX 512
  343 +
  344 +void test_pipe(void)
  345 +{
  346 + fd_set rfds, wfds;
  347 + int fds[2], fd_max, ret;
  348 + uint8_t ch;
  349 + int wcount, rcount;
  350 +
  351 + chk_error(pipe(fds));
  352 + chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK));
  353 + chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK));
  354 + wcount = 0;
  355 + rcount = 0;
  356 + for(;;) {
  357 + FD_ZERO(&rfds);
  358 + fd_max = fds[0];
  359 + FD_SET(fds[0], &rfds);
  360 +
  361 + FD_ZERO(&wfds);
  362 + FD_SET(fds[1], &wfds);
  363 + if (fds[1] > fd_max)
  364 + fd_max = fds[1];
  365 +
  366 + ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL));
  367 + if (ret > 0) {
  368 + if (FD_ISSET(fds[0], &rfds)) {
  369 + chk_error(read(fds[0], &ch, 1));
  370 + rcount++;
  371 + if (rcount >= WCOUNT_MAX)
  372 + break;
  373 + }
  374 + if (FD_ISSET(fds[1], &wfds)) {
  375 + ch = 'a';
  376 + chk_error(write(fds[0], &ch, 1));
  377 + wcount++;
  378 + }
  379 + }
  380 + }
  381 + chk_error(close(fds[0]));
  382 + chk_error(close(fds[1]));
  383 +}
  384 +
  385 +int thread1_res;
  386 +int thread2_res;
  387 +
  388 +int thread1_func(void *arg)
  389 +{
  390 + int i;
  391 + for(i=0;i<5;i++) {
  392 + thread1_res++;
  393 + usleep(10 * 1000);
  394 + }
  395 + return 0;
  396 +}
  397 +
  398 +int thread2_func(void *arg)
  399 +{
  400 + int i;
  401 + for(i=0;i<6;i++) {
  402 + thread2_res++;
  403 + usleep(10 * 1000);
  404 + }
  405 + return 0;
  406 +}
  407 +
  408 +void test_clone(void)
  409 +{
  410 + uint8_t *stack1, *stack2;
  411 + int pid1, pid2, status1, status2;
  412 +
  413 + stack1 = malloc(STACK_SIZE);
  414 + pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE,
  415 + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1"));
  416 +
  417 + stack2 = malloc(STACK_SIZE);
  418 + pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE,
  419 + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2"));
  420 +
  421 + while (waitpid(pid1, &status1, 0) != pid1);
  422 + while (waitpid(pid2, &status2, 0) != pid2);
  423 + if (thread1_res != 5 ||
  424 + thread2_res != 6)
  425 + error("clone");
  426 +}
  427 +
  428 +/***********************************/
  429 +
  430 +volatile int alarm_count;
  431 +jmp_buf jmp_env;
  432 +
  433 +void sig_alarm(int sig)
  434 +{
  435 + if (sig != SIGALRM)
  436 + error("signal");
  437 + alarm_count++;
  438 +}
  439 +
  440 +void sig_segv(int sig, siginfo_t *info, void *puc)
  441 +{
  442 + if (sig != SIGSEGV)
  443 + error("signal");
  444 + longjmp(jmp_env, 1);
  445 +}
  446 +
  447 +void test_signal(void)
  448 +{
  449 + struct sigaction act;
  450 + struct itimerval it, oit;
  451 +
  452 + /* timer test */
  453 +
  454 + alarm_count = 0;
  455 +
  456 + act.sa_handler = sig_alarm;
  457 + sigemptyset(&act.sa_mask);
  458 + act.sa_flags = 0;
  459 + chk_error(sigaction(SIGALRM, &act, NULL));
  460 +
  461 + it.it_interval.tv_sec = 0;
  462 + it.it_interval.tv_usec = 10 * 1000;
  463 + it.it_value.tv_sec = 0;
  464 + it.it_value.tv_usec = 10 * 1000;
  465 + chk_error(setitimer(ITIMER_REAL, &it, NULL));
  466 + chk_error(getitimer(ITIMER_REAL, &oit));
  467 + if (oit.it_value.tv_sec != it.it_value.tv_sec ||
  468 + oit.it_value.tv_usec != it.it_value.tv_usec)
  469 + error("itimer");
  470 +
  471 + while (alarm_count < 5) {
  472 + usleep(10 * 1000);
  473 + }
  474 +
  475 + it.it_interval.tv_sec = 0;
  476 + it.it_interval.tv_usec = 0;
  477 + it.it_value.tv_sec = 0;
  478 + it.it_value.tv_usec = 0;
  479 + memset(&oit, 0xff, sizeof(oit));
  480 + chk_error(setitimer(ITIMER_REAL, &it, &oit));
  481 + if (oit.it_value.tv_sec != 0 ||
  482 + oit.it_value.tv_usec != 10 * 1000)
  483 + error("setitimer");
  484 +
  485 + /* SIGSEGV test */
  486 + act.sa_sigaction = sig_segv;
  487 + sigemptyset(&act.sa_mask);
  488 + act.sa_flags = SA_SIGINFO;
  489 + chk_error(sigaction(SIGSEGV, &act, NULL));
  490 + if (setjmp(jmp_env) == 0) {
  491 + *(uint8_t *)0 = 0;
  492 + }
  493 +
  494 + act.sa_handler = SIG_DFL;
  495 + sigemptyset(&act.sa_mask);
  496 + act.sa_flags = 0;
  497 + chk_error(sigaction(SIGSEGV, &act, NULL));
  498 +}
  499 +
  500 +int main(int argc, char **argv)
  501 +{
  502 + file_test();
  503 + test_fork();
  504 + test_time();
  505 + test_socket();
  506 + test_clone();
  507 + test_signal();
  508 + return 0;
  509 +}
  510 +
... ...