Skip to content
Snippets Groups Projects
usertests.c 43.2 KiB
Newer Older
    // causing exit() to panic.
    sbrk(-sz);
    // user page fault here.
    exit(0);
  }
  wait(0);

  pid = fork();
  if(pid < 0){
    printf("fork failed\n");
    exit(1);
  }
  if(pid == 0){
    int sz = (uint64) sbrk(0);
    // set the break to somewhere in the very first
    // page; there used to be a bug that would incorrectly
    // free the first page.
    sbrk(-(sz - 3500));
    exit(0);
  }
  wait(0);

  pid = fork();
  if(pid < 0){
    printf("fork failed\n");
    exit(1);
  }
  if(pid == 0){
    // set the break in the middle of a page.
    sbrk((10*4096 + 2048) - (uint64)sbrk(0));

    // reduce the break a bit, but not enough to
    // cause a page to be freed. this used to cause
    // a panic.
    sbrk(-10);

    exit(0);
  }
  wait(0);

  exit(0);
}

// regression test. does write() with an invalid buffer pointer cause
// a block to be allocated for a file that is then not freed when the
// file is deleted? if the kernel has this bug, it will panic: balloc:
// out of blocks. assumed_free may need to be raised to be more than
// the number of free blocks. this test takes a long time.
void
badwrite(char *s)
{
  int assumed_free = 600;
  
  unlink("junk");
  for(int i = 0; i < assumed_free; i++){
    int fd = open("junk", O_CREATE|O_WRONLY);
    if(fd < 0){
      printf("open junk failed\n");
      exit(1);
    }
    write(fd, (char*)0xffffffffffL, 1);
    close(fd);
    unlink("junk");
  }

  int fd = open("junk", O_CREATE|O_WRONLY);
  if(fd < 0){
    printf("open junk failed\n");
    exit(1);
  }
  if(write(fd, "x", 1) != 1){
    printf("write failed\n");
    exit(1);
  }
  close(fd);
  unlink("junk");

  exit(0);
}

// regression test. test whether exec() leaks memory if one of the
// arguments is invalid. the test passes if the kernel doesn't panic.
void
badarg(char *s)
{
  for(int i = 0; i < 50000; i++){
    char *argv[2];
    argv[0] = (char*)0xffffffff;
    argv[1] = 0;
    exec("echo", argv);
  }
  
  exit(0);
}

// run each test in its own process. run returns 1 if child's exit()
// indicates success.
int
run(void f(char *), char *s) {
  int pid;
  int xstatus;
  
  printf("test %s: ", s);
Wilke Pierre's avatar
Wilke Pierre committed
  fflush(1);
  if((pid = fork()) < 0) {
    printf("runtest: fork error\n");
    exit(1);
  }
  if(pid == 0) {
    f(s);
    exit(0);
  } else {
    wait(&xstatus);
    if(xstatus != 0) 
      printf("FAILED\n", s);
    else
      printf("OK\n", s);
    return xstatus == 0;
  }
}

int
main(int argc, char *argv[])
{
  char *n = 0;
  if(argc > 1) {
    n = argv[1];
  }
  
  struct test {
    void (*f)(char *);
    char *s;
Wilke Pierre's avatar
Wilke Pierre committed
    int ok;
  } tests[] = {
Wilke Pierre's avatar
Wilke Pierre committed
    {reparent2, "reparent2", 0},
    {pgbug, "pgbug" , 0},
    {sbrkbugs, "sbrkbugs" , 0},
    // {badwrite, "badwrite" , 0},
    {badarg, "badarg" , 0},
    {reparent, "reparent" , 0},
    {twochildren, "twochildren", 0},
    {forkfork, "forkfork", 0},
    {forkforkfork, "forkforkfork", 0},
    {argptest, "argptest", 0},
    {createdelete, "createdelete", 0},
    {linkunlink, "linkunlink", 0},
    {linktest, "linktest", 0},
    {unlinkread, "unlinkread", 0},
    {concreate, "concreate", 0},
    {subdir, "subdir", 0},
    {fourfiles, "fourfiles", 0},
    {sharedfd, "sharedfd", 0},
    {exectest, "exectest", 0},
    {bigargtest, "bigargtest", 0},
    {bigwrite, "bigwrite", 0},
    {bsstest, "bsstest", 0},
    {sbrkbasic, "sbrkbasic", 0},
    {sbrkmuch, "sbrkmuch", 0},
    {kernmem, "kernmem", 0},
    {sbrkfail, "sbrkfail", 0},
    {sbrkarg, "sbrkarg", 0},
    {validatetest, "validatetest", 0},
    {stacktest, "stacktest", 0},
    {opentest, "opentest", 0},
    {writetest, "writetest", 0},
    {writebig, "writebig", 0},
    {createtest, "createtest", 0},
    {openiputtest, "openiput", 0},
    {exitiputtest, "exitiput", 0},
    {iputtest, "iput", 0},
    {mem, "mem", 0},
    {pipe1, "pipe1", 0},
    {preempt, "preempt", 0},
    {exitwait, "exitwait", 0},
    {rmdot, "rmdot", 0},
    {fourteen, "fourteen", 0},
    {bigfile, "bigfile", 0},
    {dirfile, "dirfile", 0},
    {iref, "iref", 0},
    {forktest, "forktest", 0},
    {bigdir, "bigdir", 0}, // slow
    { 0, 0, 0},
  };
    
  printf("usertests starting\n");

Wilke Pierre's avatar
Wilke Pierre committed
  /* if(open("usertests.ran", 0) >= 0){ */
  /*   printf("already ran user tests -- rebuild fs.img (rm fs.img; make fs.img)\n"); */
  /*   exit(1); */
  /* } */
  /* close(open("usertests.ran", O_CREATE)); */

  int fail = 0;
  for (struct test *t = tests; t->s != 0; t++) {
    if((n == 0) || strcmp(t->s, n) == 0) {
Wilke Pierre's avatar
Wilke Pierre committed
      if(!run(t->f, t->s)){
        fail = 1;
Wilke Pierre's avatar
Wilke Pierre committed
        t->ok = 0;
      } else {
        t->ok = 1;
      }
    }
  }
  if(!fail)
    printf("ALL TESTS PASSED\n");
Wilke Pierre's avatar
Wilke Pierre committed
  else{
    printf("SOME TESTS FAILED\n");
Wilke Pierre's avatar
Wilke Pierre committed
    for (struct test *t = tests; t->s != 0; t++) {
      if((n == 0) || strcmp(t->s, n) == 0) {
        if(t->ok == 0){
          printf("Test %s failed.\n", t->s);
        }
      }
    }
  }
  exit(1);   // not reached.
}