usertests.c (31834B)
1 #include "param.h" 2 #include "types.h" 3 #include "stat.h" 4 #include "user.h" 5 #include "fs.h" 6 #include "fcntl.h" 7 #include "syscall.h" 8 #include "traps.h" 9 #include "memlayout.h" 10 11 char buf[8192]; 12 char name[3]; 13 char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 }; 14 int stdout = 1; 15 16 // simple file system tests 17 18 void 19 opentest(void) 20 { 21 int fd; 22 23 printf(stdout, "open test\n"); 24 fd = open("echo", 0); 25 if(fd < 0){ 26 printf(stdout, "open echo failed!\n"); 27 exit(); 28 } 29 close(fd); 30 fd = open("doesnotexist", 0); 31 if(fd >= 0){ 32 printf(stdout, "open doesnotexist succeeded!\n"); 33 exit(); 34 } 35 printf(stdout, "open test ok\n"); 36 } 37 38 void 39 writetest(void) 40 { 41 int fd; 42 int i; 43 44 printf(stdout, "small file test\n"); 45 fd = open("small", O_CREATE|O_RDWR); 46 if(fd >= 0){ 47 printf(stdout, "creat small succeeded; ok\n"); 48 } else { 49 printf(stdout, "error: creat small failed!\n"); 50 exit(); 51 } 52 for(i = 0; i < 100; i++){ 53 if(write(fd, "aaaaaaaaaa", 10) != 10){ 54 printf(stdout, "error: write aa %d new file failed\n", i); 55 exit(); 56 } 57 if(write(fd, "bbbbbbbbbb", 10) != 10){ 58 printf(stdout, "error: write bb %d new file failed\n", i); 59 exit(); 60 } 61 } 62 printf(stdout, "writes ok\n"); 63 close(fd); 64 fd = open("small", O_RDONLY); 65 if(fd >= 0){ 66 printf(stdout, "open small succeeded ok\n"); 67 } else { 68 printf(stdout, "error: open small failed!\n"); 69 exit(); 70 } 71 i = read(fd, buf, 2000); 72 if(i == 2000){ 73 printf(stdout, "read succeeded ok\n"); 74 } else { 75 printf(stdout, "read failed\n"); 76 exit(); 77 } 78 close(fd); 79 80 if(unlink("small") < 0){ 81 printf(stdout, "unlink small failed\n"); 82 exit(); 83 } 84 printf(stdout, "small file test ok\n"); 85 } 86 87 void 88 writetest1(void) 89 { 90 int i, fd, n; 91 92 printf(stdout, "big files test\n"); 93 94 fd = open("big", O_CREATE|O_RDWR); 95 if(fd < 0){ 96 printf(stdout, "error: creat big failed!\n"); 97 exit(); 98 } 99 100 for(i = 0; i < MAXFILE; i++){ 101 ((int*)buf)[0] = i; 102 if(write(fd, buf, 512) != 512){ 103 printf(stdout, "error: write big file failed\n", i); 104 exit(); 105 } 106 } 107 108 close(fd); 109 110 fd = open("big", O_RDONLY); 111 if(fd < 0){ 112 printf(stdout, "error: open big failed!\n"); 113 exit(); 114 } 115 116 n = 0; 117 for(;;){ 118 i = read(fd, buf, 512); 119 if(i == 0){ 120 if(n == MAXFILE - 1){ 121 printf(stdout, "read only %d blocks from big", n); 122 exit(); 123 } 124 break; 125 } else if(i != 512){ 126 printf(stdout, "read failed %d\n", i); 127 exit(); 128 } 129 if(((int*)buf)[0] != n){ 130 printf(stdout, "read content of block %d is %d\n", 131 n, ((int*)buf)[0]); 132 exit(); 133 } 134 n++; 135 } 136 close(fd); 137 if(unlink("big") < 0){ 138 printf(stdout, "unlink big failed\n"); 139 exit(); 140 } 141 printf(stdout, "big files ok\n"); 142 } 143 144 void 145 createtest(void) 146 { 147 int i, fd; 148 149 printf(stdout, "many creates, followed by unlink test\n"); 150 151 name[0] = 'a'; 152 name[2] = '\0'; 153 for(i = 0; i < 52; i++){ 154 name[1] = '0' + i; 155 fd = open(name, O_CREATE|O_RDWR); 156 close(fd); 157 } 158 name[0] = 'a'; 159 name[2] = '\0'; 160 for(i = 0; i < 52; i++){ 161 name[1] = '0' + i; 162 unlink(name); 163 } 164 printf(stdout, "many creates, followed by unlink; ok\n"); 165 } 166 167 void dirtest(void) 168 { 169 printf(stdout, "mkdir test\n"); 170 171 if(mkdir("dir0") < 0){ 172 printf(stdout, "mkdir failed\n"); 173 exit(); 174 } 175 176 if(chdir("dir0") < 0){ 177 printf(stdout, "chdir dir0 failed\n"); 178 exit(); 179 } 180 181 if(chdir("..") < 0){ 182 printf(stdout, "chdir .. failed\n"); 183 exit(); 184 } 185 186 if(unlink("dir0") < 0){ 187 printf(stdout, "unlink dir0 failed\n"); 188 exit(); 189 } 190 printf(stdout, "mkdir test\n"); 191 } 192 193 void 194 exectest(void) 195 { 196 printf(stdout, "exec test\n"); 197 if(exec("echo", echoargv) < 0){ 198 printf(stdout, "exec echo failed\n"); 199 exit(); 200 } 201 } 202 203 // simple fork and pipe read/write 204 205 void 206 pipe1(void) 207 { 208 int fds[2], pid; 209 int seq, i, n, cc, total; 210 211 if(pipe(fds) != 0){ 212 printf(1, "pipe() failed\n"); 213 exit(); 214 } 215 pid = fork(); 216 seq = 0; 217 if(pid == 0){ 218 close(fds[0]); 219 for(n = 0; n < 5; n++){ 220 for(i = 0; i < 1033; i++) 221 buf[i] = seq++; 222 if(write(fds[1], buf, 1033) != 1033){ 223 printf(1, "pipe1 oops 1\n"); 224 exit(); 225 } 226 } 227 exit(); 228 } else if(pid > 0){ 229 close(fds[1]); 230 total = 0; 231 cc = 1; 232 while((n = read(fds[0], buf, cc)) > 0){ 233 for(i = 0; i < n; i++){ 234 if((buf[i] & 0xff) != (seq++ & 0xff)){ 235 printf(1, "pipe1 oops 2\n"); 236 return; 237 } 238 } 239 total += n; 240 cc = cc * 2; 241 if(cc > sizeof(buf)) 242 cc = sizeof(buf); 243 } 244 if(total != 5 * 1033){ 245 printf(1, "pipe1 oops 3 total %d\n", total); 246 exit(); 247 } 248 close(fds[0]); 249 wait(); 250 } else { 251 printf(1, "fork() failed\n"); 252 exit(); 253 } 254 printf(1, "pipe1 ok\n"); 255 } 256 257 // meant to be run w/ at most two CPUs 258 void 259 preempt(void) 260 { 261 int pid1, pid2, pid3; 262 int pfds[2]; 263 264 printf(1, "preempt: "); 265 pid1 = fork(); 266 if(pid1 == 0) 267 for(;;) 268 ; 269 270 pid2 = fork(); 271 if(pid2 == 0) 272 for(;;) 273 ; 274 275 pipe(pfds); 276 pid3 = fork(); 277 if(pid3 == 0){ 278 close(pfds[0]); 279 if(write(pfds[1], "x", 1) != 1) 280 printf(1, "preempt write error"); 281 close(pfds[1]); 282 for(;;) 283 ; 284 } 285 286 close(pfds[1]); 287 if(read(pfds[0], buf, sizeof(buf)) != 1){ 288 printf(1, "preempt read error"); 289 return; 290 } 291 close(pfds[0]); 292 printf(1, "kill... "); 293 kill(pid1); 294 kill(pid2); 295 kill(pid3); 296 printf(1, "wait... "); 297 wait(); 298 wait(); 299 wait(); 300 printf(1, "preempt ok\n"); 301 } 302 303 // try to find any races between exit and wait 304 void 305 exitwait(void) 306 { 307 int i, pid; 308 309 for(i = 0; i < 100; i++){ 310 pid = fork(); 311 if(pid < 0){ 312 printf(1, "fork failed\n"); 313 return; 314 } 315 if(pid){ 316 if(wait() != pid){ 317 printf(1, "wait wrong pid\n"); 318 return; 319 } 320 } else { 321 exit(); 322 } 323 } 324 printf(1, "exitwait ok\n"); 325 } 326 327 void 328 mem(void) 329 { 330 void *m1, *m2; 331 int pid, ppid; 332 333 printf(1, "mem test\n"); 334 ppid = getpid(); 335 if((pid = fork()) == 0){ 336 m1 = 0; 337 while((m2 = malloc(10001)) != 0){ 338 *(char**)m2 = m1; 339 m1 = m2; 340 } 341 while(m1){ 342 m2 = *(char**)m1; 343 free(m1); 344 m1 = m2; 345 } 346 m1 = malloc(1024*20); 347 if(m1 == 0){ 348 printf(1, "couldn't allocate mem?!!\n"); 349 kill(ppid); 350 exit(); 351 } 352 free(m1); 353 printf(1, "mem ok\n"); 354 exit(); 355 } else { 356 wait(); 357 } 358 } 359 360 // More file system tests 361 362 // two processes write to the same file descriptor 363 // is the offset shared? does inode locking work? 364 void 365 sharedfd(void) 366 { 367 int fd, pid, i, n, nc, np; 368 char buf[10]; 369 370 printf(1, "sharedfd test\n"); 371 372 unlink("sharedfd"); 373 fd = open("sharedfd", O_CREATE|O_RDWR); 374 if(fd < 0){ 375 printf(1, "fstests: cannot open sharedfd for writing"); 376 return; 377 } 378 pid = fork(); 379 memset(buf, pid==0?'c':'p', sizeof(buf)); 380 for(i = 0; i < 1000; i++){ 381 if(write(fd, buf, sizeof(buf)) != sizeof(buf)){ 382 printf(1, "fstests: write sharedfd failed\n"); 383 break; 384 } 385 } 386 if(pid == 0) 387 exit(); 388 else 389 wait(); 390 close(fd); 391 fd = open("sharedfd", 0); 392 if(fd < 0){ 393 printf(1, "fstests: cannot open sharedfd for reading\n"); 394 return; 395 } 396 nc = np = 0; 397 while((n = read(fd, buf, sizeof(buf))) > 0){ 398 for(i = 0; i < sizeof(buf); i++){ 399 if(buf[i] == 'c') 400 nc++; 401 if(buf[i] == 'p') 402 np++; 403 } 404 } 405 close(fd); 406 unlink("sharedfd"); 407 if(nc == 10000 && np == 10000){ 408 printf(1, "sharedfd ok\n"); 409 } else { 410 printf(1, "sharedfd oops %d %d\n", nc, np); 411 exit(); 412 } 413 } 414 415 // two processes write two different files at the same 416 // time, to test block allocation. 417 void 418 twofiles(void) 419 { 420 int fd, pid, i, j, n, total; 421 char *fname; 422 423 printf(1, "twofiles test\n"); 424 425 unlink("f1"); 426 unlink("f2"); 427 428 pid = fork(); 429 if(pid < 0){ 430 printf(1, "fork failed\n"); 431 exit(); 432 } 433 434 fname = pid ? "f1" : "f2"; 435 fd = open(fname, O_CREATE | O_RDWR); 436 if(fd < 0){ 437 printf(1, "create failed\n"); 438 exit(); 439 } 440 441 memset(buf, pid?'p':'c', 512); 442 for(i = 0; i < 12; i++){ 443 if((n = write(fd, buf, 500)) != 500){ 444 printf(1, "write failed %d\n", n); 445 exit(); 446 } 447 } 448 close(fd); 449 if(pid) 450 wait(); 451 else 452 exit(); 453 454 for(i = 0; i < 2; i++){ 455 fd = open(i?"f1":"f2", 0); 456 total = 0; 457 while((n = read(fd, buf, sizeof(buf))) > 0){ 458 for(j = 0; j < n; j++){ 459 if(buf[j] != (i?'p':'c')){ 460 printf(1, "wrong char\n"); 461 exit(); 462 } 463 } 464 total += n; 465 } 466 close(fd); 467 if(total != 12*500){ 468 printf(1, "wrong length %d\n", total); 469 exit(); 470 } 471 } 472 473 unlink("f1"); 474 unlink("f2"); 475 476 printf(1, "twofiles ok\n"); 477 } 478 479 // two processes create and delete different files in same directory 480 void 481 createdelete(void) 482 { 483 enum { N = 20 }; 484 int pid, i, fd; 485 char name[32]; 486 487 printf(1, "createdelete test\n"); 488 pid = fork(); 489 if(pid < 0){ 490 printf(1, "fork failed\n"); 491 exit(); 492 } 493 494 name[0] = pid ? 'p' : 'c'; 495 name[2] = '\0'; 496 for(i = 0; i < N; i++){ 497 name[1] = '0' + i; 498 fd = open(name, O_CREATE | O_RDWR); 499 if(fd < 0){ 500 printf(1, "create failed\n"); 501 exit(); 502 } 503 close(fd); 504 if(i > 0 && (i % 2 ) == 0){ 505 name[1] = '0' + (i / 2); 506 if(unlink(name) < 0){ 507 printf(1, "unlink failed\n"); 508 exit(); 509 } 510 } 511 } 512 513 if(pid==0) 514 exit(); 515 else 516 wait(); 517 518 for(i = 0; i < N; i++){ 519 name[0] = 'p'; 520 name[1] = '0' + i; 521 fd = open(name, 0); 522 if((i == 0 || i >= N/2) && fd < 0){ 523 printf(1, "oops createdelete %s didn't exist\n", name); 524 exit(); 525 } else if((i >= 1 && i < N/2) && fd >= 0){ 526 printf(1, "oops createdelete %s did exist\n", name); 527 exit(); 528 } 529 if(fd >= 0) 530 close(fd); 531 532 name[0] = 'c'; 533 name[1] = '0' + i; 534 fd = open(name, 0); 535 if((i == 0 || i >= N/2) && fd < 0){ 536 printf(1, "oops createdelete %s didn't exist\n", name); 537 exit(); 538 } else if((i >= 1 && i < N/2) && fd >= 0){ 539 printf(1, "oops createdelete %s did exist\n", name); 540 exit(); 541 } 542 if(fd >= 0) 543 close(fd); 544 } 545 546 for(i = 0; i < N; i++){ 547 name[0] = 'p'; 548 name[1] = '0' + i; 549 unlink(name); 550 name[0] = 'c'; 551 unlink(name); 552 } 553 554 printf(1, "createdelete ok\n"); 555 } 556 557 // can I unlink a file and still read it? 558 void 559 unlinkread(void) 560 { 561 int fd, fd1; 562 563 printf(1, "unlinkread test\n"); 564 fd = open("unlinkread", O_CREATE | O_RDWR); 565 if(fd < 0){ 566 printf(1, "create unlinkread failed\n"); 567 exit(); 568 } 569 write(fd, "hello", 5); 570 close(fd); 571 572 fd = open("unlinkread", O_RDWR); 573 if(fd < 0){ 574 printf(1, "open unlinkread failed\n"); 575 exit(); 576 } 577 if(unlink("unlinkread") != 0){ 578 printf(1, "unlink unlinkread failed\n"); 579 exit(); 580 } 581 582 fd1 = open("unlinkread", O_CREATE | O_RDWR); 583 write(fd1, "yyy", 3); 584 close(fd1); 585 586 if(read(fd, buf, sizeof(buf)) != 5){ 587 printf(1, "unlinkread read failed"); 588 exit(); 589 } 590 if(buf[0] != 'h'){ 591 printf(1, "unlinkread wrong data\n"); 592 exit(); 593 } 594 if(write(fd, buf, 10) != 10){ 595 printf(1, "unlinkread write failed\n"); 596 exit(); 597 } 598 close(fd); 599 unlink("unlinkread"); 600 printf(1, "unlinkread ok\n"); 601 } 602 603 void 604 linktest(void) 605 { 606 int fd; 607 608 printf(1, "linktest\n"); 609 610 unlink("lf1"); 611 unlink("lf2"); 612 613 fd = open("lf1", O_CREATE|O_RDWR); 614 if(fd < 0){ 615 printf(1, "create lf1 failed\n"); 616 exit(); 617 } 618 if(write(fd, "hello", 5) != 5){ 619 printf(1, "write lf1 failed\n"); 620 exit(); 621 } 622 close(fd); 623 624 if(link("lf1", "lf2") < 0){ 625 printf(1, "link lf1 lf2 failed\n"); 626 exit(); 627 } 628 unlink("lf1"); 629 630 if(open("lf1", 0) >= 0){ 631 printf(1, "unlinked lf1 but it is still there!\n"); 632 exit(); 633 } 634 635 fd = open("lf2", 0); 636 if(fd < 0){ 637 printf(1, "open lf2 failed\n"); 638 exit(); 639 } 640 if(read(fd, buf, sizeof(buf)) != 5){ 641 printf(1, "read lf2 failed\n"); 642 exit(); 643 } 644 close(fd); 645 646 if(link("lf2", "lf2") >= 0){ 647 printf(1, "link lf2 lf2 succeeded! oops\n"); 648 exit(); 649 } 650 651 unlink("lf2"); 652 if(link("lf2", "lf1") >= 0){ 653 printf(1, "link non-existant succeeded! oops\n"); 654 exit(); 655 } 656 657 if(link(".", "lf1") >= 0){ 658 printf(1, "link . lf1 succeeded! oops\n"); 659 exit(); 660 } 661 662 printf(1, "linktest ok\n"); 663 } 664 665 // test concurrent create/link/unlink of the same file 666 void 667 concreate(void) 668 { 669 char file[3]; 670 int i, pid, n, fd; 671 char fa[40]; 672 struct { 673 ushort inum; 674 char name[14]; 675 } de; 676 677 printf(1, "concreate test\n"); 678 file[0] = 'C'; 679 file[2] = '\0'; 680 for(i = 0; i < 40; i++){ 681 file[1] = '0' + i; 682 unlink(file); 683 pid = fork(); 684 if(pid && (i % 3) == 1){ 685 link("C0", file); 686 } else if(pid == 0 && (i % 5) == 1){ 687 link("C0", file); 688 } else { 689 fd = open(file, O_CREATE | O_RDWR); 690 if(fd < 0){ 691 printf(1, "concreate create %s failed\n", file); 692 exit(); 693 } 694 close(fd); 695 } 696 if(pid == 0) 697 exit(); 698 else 699 wait(); 700 } 701 702 memset(fa, 0, sizeof(fa)); 703 fd = open(".", 0); 704 n = 0; 705 while(read(fd, &de, sizeof(de)) > 0){ 706 if(de.inum == 0) 707 continue; 708 if(de.name[0] == 'C' && de.name[2] == '\0'){ 709 i = de.name[1] - '0'; 710 if(i < 0 || i >= sizeof(fa)){ 711 printf(1, "concreate weird file %s\n", de.name); 712 exit(); 713 } 714 if(fa[i]){ 715 printf(1, "concreate duplicate file %s\n", de.name); 716 exit(); 717 } 718 fa[i] = 1; 719 n++; 720 } 721 } 722 close(fd); 723 724 if(n != 40){ 725 printf(1, "concreate not enough files in directory listing\n"); 726 exit(); 727 } 728 729 for(i = 0; i < 40; i++){ 730 file[1] = '0' + i; 731 pid = fork(); 732 if(pid < 0){ 733 printf(1, "fork failed\n"); 734 exit(); 735 } 736 if(((i % 3) == 0 && pid == 0) || 737 ((i % 3) == 1 && pid != 0)){ 738 close(open(file, 0)); 739 close(open(file, 0)); 740 close(open(file, 0)); 741 close(open(file, 0)); 742 } else { 743 unlink(file); 744 unlink(file); 745 unlink(file); 746 unlink(file); 747 } 748 if(pid == 0) 749 exit(); 750 else 751 wait(); 752 } 753 754 printf(1, "concreate ok\n"); 755 } 756 757 // another concurrent link/unlink/create test, 758 // to look for deadlocks. 759 void 760 linkunlink() 761 { 762 int pid, i; 763 764 printf(1, "linkunlink test\n"); 765 766 unlink("x"); 767 pid = fork(); 768 if(pid < 0){ 769 printf(1, "fork failed\n"); 770 exit(); 771 } 772 773 unsigned int x = (pid ? 1 : 97); 774 for(i = 0; i < 100; i++){ 775 x = x * 1103515245 + 12345; 776 if((x % 3) == 0){ 777 close(open("x", O_RDWR | O_CREATE)); 778 } else if((x % 3) == 1){ 779 link("cat", "x"); 780 } else { 781 unlink("x"); 782 } 783 } 784 785 if(pid) 786 wait(); 787 else 788 exit(); 789 790 printf(1, "linkunlink ok\n"); 791 } 792 793 // directory that uses indirect blocks 794 void 795 bigdir(void) 796 { 797 int i, fd; 798 char name[10]; 799 800 printf(1, "bigdir test\n"); 801 unlink("bd"); 802 803 fd = open("bd", O_CREATE); 804 if(fd < 0){ 805 printf(1, "bigdir create failed\n"); 806 exit(); 807 } 808 close(fd); 809 810 for(i = 0; i < 500; i++){ 811 name[0] = 'x'; 812 name[1] = '0' + (i / 64); 813 name[2] = '0' + (i % 64); 814 name[3] = '\0'; 815 if(link("bd", name) != 0){ 816 printf(1, "bigdir link failed\n"); 817 exit(); 818 } 819 } 820 821 unlink("bd"); 822 for(i = 0; i < 500; i++){ 823 name[0] = 'x'; 824 name[1] = '0' + (i / 64); 825 name[2] = '0' + (i % 64); 826 name[3] = '\0'; 827 if(unlink(name) != 0){ 828 printf(1, "bigdir unlink failed"); 829 exit(); 830 } 831 } 832 833 printf(1, "bigdir ok\n"); 834 } 835 836 void 837 subdir(void) 838 { 839 int fd, cc; 840 841 printf(1, "subdir test\n"); 842 843 unlink("ff"); 844 if(mkdir("dd") != 0){ 845 printf(1, "subdir mkdir dd failed\n"); 846 exit(); 847 } 848 849 fd = open("dd/ff", O_CREATE | O_RDWR); 850 if(fd < 0){ 851 printf(1, "create dd/ff failed\n"); 852 exit(); 853 } 854 write(fd, "ff", 2); 855 close(fd); 856 857 if(unlink("dd") >= 0){ 858 printf(1, "unlink dd (non-empty dir) succeeded!\n"); 859 exit(); 860 } 861 862 if(mkdir("/dd/dd") != 0){ 863 printf(1, "subdir mkdir dd/dd failed\n"); 864 exit(); 865 } 866 867 fd = open("dd/dd/ff", O_CREATE | O_RDWR); 868 if(fd < 0){ 869 printf(1, "create dd/dd/ff failed\n"); 870 exit(); 871 } 872 write(fd, "FF", 2); 873 close(fd); 874 875 fd = open("dd/dd/../ff", 0); 876 if(fd < 0){ 877 printf(1, "open dd/dd/../ff failed\n"); 878 exit(); 879 } 880 cc = read(fd, buf, sizeof(buf)); 881 if(cc != 2 || buf[0] != 'f'){ 882 printf(1, "dd/dd/../ff wrong content\n"); 883 exit(); 884 } 885 close(fd); 886 887 if(link("dd/dd/ff", "dd/dd/ffff") != 0){ 888 printf(1, "link dd/dd/ff dd/dd/ffff failed\n"); 889 exit(); 890 } 891 892 if(unlink("dd/dd/ff") != 0){ 893 printf(1, "unlink dd/dd/ff failed\n"); 894 exit(); 895 } 896 if(open("dd/dd/ff", O_RDONLY) >= 0){ 897 printf(1, "open (unlinked) dd/dd/ff succeeded\n"); 898 exit(); 899 } 900 901 if(chdir("dd") != 0){ 902 printf(1, "chdir dd failed\n"); 903 exit(); 904 } 905 if(chdir("dd/../../dd") != 0){ 906 printf(1, "chdir dd/../../dd failed\n"); 907 exit(); 908 } 909 if(chdir("dd/../../../dd") != 0){ 910 printf(1, "chdir dd/../../dd failed\n"); 911 exit(); 912 } 913 if(chdir("./..") != 0){ 914 printf(1, "chdir ./.. failed\n"); 915 exit(); 916 } 917 918 fd = open("dd/dd/ffff", 0); 919 if(fd < 0){ 920 printf(1, "open dd/dd/ffff failed\n"); 921 exit(); 922 } 923 if(read(fd, buf, sizeof(buf)) != 2){ 924 printf(1, "read dd/dd/ffff wrong len\n"); 925 exit(); 926 } 927 close(fd); 928 929 if(open("dd/dd/ff", O_RDONLY) >= 0){ 930 printf(1, "open (unlinked) dd/dd/ff succeeded!\n"); 931 exit(); 932 } 933 934 if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){ 935 printf(1, "create dd/ff/ff succeeded!\n"); 936 exit(); 937 } 938 if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){ 939 printf(1, "create dd/xx/ff succeeded!\n"); 940 exit(); 941 } 942 if(open("dd", O_CREATE) >= 0){ 943 printf(1, "create dd succeeded!\n"); 944 exit(); 945 } 946 if(open("dd", O_RDWR) >= 0){ 947 printf(1, "open dd rdwr succeeded!\n"); 948 exit(); 949 } 950 if(open("dd", O_WRONLY) >= 0){ 951 printf(1, "open dd wronly succeeded!\n"); 952 exit(); 953 } 954 if(link("dd/ff/ff", "dd/dd/xx") == 0){ 955 printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n"); 956 exit(); 957 } 958 if(link("dd/xx/ff", "dd/dd/xx") == 0){ 959 printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n"); 960 exit(); 961 } 962 if(link("dd/ff", "dd/dd/ffff") == 0){ 963 printf(1, "link dd/ff dd/dd/ffff succeeded!\n"); 964 exit(); 965 } 966 if(mkdir("dd/ff/ff") == 0){ 967 printf(1, "mkdir dd/ff/ff succeeded!\n"); 968 exit(); 969 } 970 if(mkdir("dd/xx/ff") == 0){ 971 printf(1, "mkdir dd/xx/ff succeeded!\n"); 972 exit(); 973 } 974 if(mkdir("dd/dd/ffff") == 0){ 975 printf(1, "mkdir dd/dd/ffff succeeded!\n"); 976 exit(); 977 } 978 if(unlink("dd/xx/ff") == 0){ 979 printf(1, "unlink dd/xx/ff succeeded!\n"); 980 exit(); 981 } 982 if(unlink("dd/ff/ff") == 0){ 983 printf(1, "unlink dd/ff/ff succeeded!\n"); 984 exit(); 985 } 986 if(chdir("dd/ff") == 0){ 987 printf(1, "chdir dd/ff succeeded!\n"); 988 exit(); 989 } 990 if(chdir("dd/xx") == 0){ 991 printf(1, "chdir dd/xx succeeded!\n"); 992 exit(); 993 } 994 995 if(unlink("dd/dd/ffff") != 0){ 996 printf(1, "unlink dd/dd/ff failed\n"); 997 exit(); 998 } 999 if(unlink("dd/ff") != 0){ 1000 printf(1, "unlink dd/ff failed\n"); 1001 exit(); 1002 } 1003 if(unlink("dd") == 0){ 1004 printf(1, "unlink non-empty dd succeeded!\n"); 1005 exit(); 1006 } 1007 if(unlink("dd/dd") < 0){ 1008 printf(1, "unlink dd/dd failed\n"); 1009 exit(); 1010 } 1011 if(unlink("dd") < 0){ 1012 printf(1, "unlink dd failed\n"); 1013 exit(); 1014 } 1015 1016 printf(1, "subdir ok\n"); 1017 } 1018 1019 // test writes that are larger than the log. 1020 void 1021 bigwrite(void) 1022 { 1023 int fd, sz; 1024 1025 printf(1, "bigwrite test\n"); 1026 1027 unlink("bigwrite"); 1028 for(sz = 499; sz < 12*512; sz += 471){ 1029 fd = open("bigwrite", O_CREATE | O_RDWR); 1030 if(fd < 0){ 1031 printf(1, "cannot create bigwrite\n"); 1032 exit(); 1033 } 1034 int i; 1035 for(i = 0; i < 2; i++){ 1036 int cc = write(fd, buf, sz); 1037 if(cc != sz){ 1038 printf(1, "write(%d) ret %d\n", sz, cc); 1039 exit(); 1040 } 1041 } 1042 close(fd); 1043 unlink("bigwrite"); 1044 } 1045 1046 printf(1, "bigwrite ok\n"); 1047 } 1048 1049 void 1050 bigfile(void) 1051 { 1052 int fd, i, total, cc; 1053 1054 printf(1, "bigfile test\n"); 1055 1056 unlink("bigfile"); 1057 fd = open("bigfile", O_CREATE | O_RDWR); 1058 if(fd < 0){ 1059 printf(1, "cannot create bigfile"); 1060 exit(); 1061 } 1062 for(i = 0; i < 20; i++){ 1063 memset(buf, i, 600); 1064 if(write(fd, buf, 600) != 600){ 1065 printf(1, "write bigfile failed\n"); 1066 exit(); 1067 } 1068 } 1069 close(fd); 1070 1071 fd = open("bigfile", 0); 1072 if(fd < 0){ 1073 printf(1, "cannot open bigfile\n"); 1074 exit(); 1075 } 1076 total = 0; 1077 for(i = 0; ; i++){ 1078 cc = read(fd, buf, 300); 1079 if(cc < 0){ 1080 printf(1, "read bigfile failed\n"); 1081 exit(); 1082 } 1083 if(cc == 0) 1084 break; 1085 if(cc != 300){ 1086 printf(1, "short read bigfile\n"); 1087 exit(); 1088 } 1089 if(buf[0] != i/2 || buf[299] != i/2){ 1090 printf(1, "read bigfile wrong data\n"); 1091 exit(); 1092 } 1093 total += cc; 1094 } 1095 close(fd); 1096 if(total != 20*600){ 1097 printf(1, "read bigfile wrong total\n"); 1098 exit(); 1099 } 1100 unlink("bigfile"); 1101 1102 printf(1, "bigfile test ok\n"); 1103 } 1104 1105 void 1106 fourteen(void) 1107 { 1108 int fd; 1109 1110 // DIRSIZ is 14. 1111 printf(1, "fourteen test\n"); 1112 1113 if(mkdir("12345678901234") != 0){ 1114 printf(1, "mkdir 12345678901234 failed\n"); 1115 exit(); 1116 } 1117 if(mkdir("12345678901234/123456789012345") != 0){ 1118 printf(1, "mkdir 12345678901234/123456789012345 failed\n"); 1119 exit(); 1120 } 1121 fd = open("123456789012345/123456789012345/123456789012345", O_CREATE); 1122 if(fd < 0){ 1123 printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n"); 1124 exit(); 1125 } 1126 close(fd); 1127 fd = open("12345678901234/12345678901234/12345678901234", 0); 1128 if(fd < 0){ 1129 printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n"); 1130 exit(); 1131 } 1132 close(fd); 1133 1134 if(mkdir("12345678901234/12345678901234") == 0){ 1135 printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n"); 1136 exit(); 1137 } 1138 if(mkdir("123456789012345/12345678901234") == 0){ 1139 printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n"); 1140 exit(); 1141 } 1142 1143 printf(1, "fourteen ok\n"); 1144 } 1145 1146 void 1147 rmdot(void) 1148 { 1149 printf(1, "rmdot test\n"); 1150 if(mkdir("dots") != 0){ 1151 printf(1, "mkdir dots failed\n"); 1152 exit(); 1153 } 1154 if(chdir("dots") != 0){ 1155 printf(1, "chdir dots failed\n"); 1156 exit(); 1157 } 1158 if(unlink(".") == 0){ 1159 printf(1, "rm . worked!\n"); 1160 exit(); 1161 } 1162 if(unlink("..") == 0){ 1163 printf(1, "rm .. worked!\n"); 1164 exit(); 1165 } 1166 if(chdir("/") != 0){ 1167 printf(1, "chdir / failed\n"); 1168 exit(); 1169 } 1170 if(unlink("dots/.") == 0){ 1171 printf(1, "unlink dots/. worked!\n"); 1172 exit(); 1173 } 1174 if(unlink("dots/..") == 0){ 1175 printf(1, "unlink dots/.. worked!\n"); 1176 exit(); 1177 } 1178 if(unlink("dots") != 0){ 1179 printf(1, "unlink dots failed!\n"); 1180 exit(); 1181 } 1182 printf(1, "rmdot ok\n"); 1183 } 1184 1185 void 1186 dirfile(void) 1187 { 1188 int fd; 1189 1190 printf(1, "dir vs file\n"); 1191 1192 fd = open("dirfile", O_CREATE); 1193 if(fd < 0){ 1194 printf(1, "create dirfile failed\n"); 1195 exit(); 1196 } 1197 close(fd); 1198 if(chdir("dirfile") == 0){ 1199 printf(1, "chdir dirfile succeeded!\n"); 1200 exit(); 1201 } 1202 fd = open("dirfile/xx", 0); 1203 if(fd >= 0){ 1204 printf(1, "create dirfile/xx succeeded!\n"); 1205 exit(); 1206 } 1207 fd = open("dirfile/xx", O_CREATE); 1208 if(fd >= 0){ 1209 printf(1, "create dirfile/xx succeeded!\n"); 1210 exit(); 1211 } 1212 if(mkdir("dirfile/xx") == 0){ 1213 printf(1, "mkdir dirfile/xx succeeded!\n"); 1214 exit(); 1215 } 1216 if(unlink("dirfile/xx") == 0){ 1217 printf(1, "unlink dirfile/xx succeeded!\n"); 1218 exit(); 1219 } 1220 if(link("README", "dirfile/xx") == 0){ 1221 printf(1, "link to dirfile/xx succeeded!\n"); 1222 exit(); 1223 } 1224 if(unlink("dirfile") != 0){ 1225 printf(1, "unlink dirfile failed!\n"); 1226 exit(); 1227 } 1228 1229 fd = open(".", O_RDWR); 1230 if(fd >= 0){ 1231 printf(1, "open . for writing succeeded!\n"); 1232 exit(); 1233 } 1234 fd = open(".", 0); 1235 if(write(fd, "x", 1) > 0){ 1236 printf(1, "write . succeeded!\n"); 1237 exit(); 1238 } 1239 close(fd); 1240 1241 printf(1, "dir vs file OK\n"); 1242 } 1243 1244 // test that iput() is called at the end of _namei() 1245 void 1246 iref(void) 1247 { 1248 int i, fd; 1249 1250 printf(1, "empty file name\n"); 1251 1252 // the 50 is NINODE 1253 for(i = 0; i < 50 + 1; i++){ 1254 if(mkdir("irefd") != 0){ 1255 printf(1, "mkdir irefd failed\n"); 1256 exit(); 1257 } 1258 if(chdir("irefd") != 0){ 1259 printf(1, "chdir irefd failed\n"); 1260 exit(); 1261 } 1262 1263 mkdir(""); 1264 link("README", ""); 1265 fd = open("", O_CREATE); 1266 if(fd >= 0) 1267 close(fd); 1268 fd = open("xx", O_CREATE); 1269 if(fd >= 0) 1270 close(fd); 1271 unlink("xx"); 1272 } 1273 1274 chdir("/"); 1275 printf(1, "empty file name OK\n"); 1276 } 1277 1278 // test that fork fails gracefully 1279 // the forktest binary also does this, but it runs out of proc entries first. 1280 // inside the bigger usertests binary, we run out of memory first. 1281 void 1282 forktest(void) 1283 { 1284 int n, pid; 1285 1286 printf(1, "fork test\n"); 1287 1288 for(n=0; n<1000; n++){ 1289 pid = fork(); 1290 if(pid < 0) 1291 break; 1292 if(pid == 0) 1293 exit(); 1294 } 1295 1296 if(n == 1000){ 1297 printf(1, "fork claimed to work 1000 times!\n"); 1298 exit(); 1299 } 1300 1301 for(; n > 0; n--){ 1302 if(wait() < 0){ 1303 printf(1, "wait stopped early\n"); 1304 exit(); 1305 } 1306 } 1307 1308 if(wait() != -1){ 1309 printf(1, "wait got too many\n"); 1310 exit(); 1311 } 1312 1313 printf(1, "fork test OK\n"); 1314 } 1315 1316 void 1317 sbrktest(void) 1318 { 1319 int fds[2], pid, pids[10], ppid; 1320 char *a, *b, *c, *lastaddr, *oldbrk, *p, scratch; 1321 uint amt; 1322 1323 printf(stdout, "sbrk test\n"); 1324 oldbrk = sbrk(0); 1325 1326 // can one sbrk() less than a page? 1327 a = sbrk(0); 1328 int i; 1329 for(i = 0; i < 5000; i++){ 1330 b = sbrk(1); 1331 if(b != a){ 1332 printf(stdout, "sbrk test failed %d %x %x\n", i, a, b); 1333 exit(); 1334 } 1335 *b = 1; 1336 a = b + 1; 1337 } 1338 pid = fork(); 1339 if(pid < 0){ 1340 printf(stdout, "sbrk test fork failed\n"); 1341 exit(); 1342 } 1343 c = sbrk(1); 1344 c = sbrk(1); 1345 if(c != a + 1){ 1346 printf(stdout, "sbrk test failed post-fork\n"); 1347 exit(); 1348 } 1349 if(pid == 0) 1350 exit(); 1351 wait(); 1352 1353 // can one grow address space to something big? 1354 #define BIG (100*1024*1024) 1355 a = sbrk(0); 1356 amt = (BIG) - (uint)a; 1357 p = sbrk(amt); 1358 if (p != a) { 1359 printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n"); 1360 exit(); 1361 } 1362 lastaddr = (char*) (BIG-1); 1363 *lastaddr = 99; 1364 1365 // can one de-allocate? 1366 a = sbrk(0); 1367 c = sbrk(-4096); 1368 if(c == (char*)0xffffffff){ 1369 printf(stdout, "sbrk could not deallocate\n"); 1370 exit(); 1371 } 1372 c = sbrk(0); 1373 if(c != a - 4096){ 1374 printf(stdout, "sbrk deallocation produced wrong address, a %x c %x\n", a, c); 1375 exit(); 1376 } 1377 1378 // can one re-allocate that page? 1379 a = sbrk(0); 1380 c = sbrk(4096); 1381 if(c != a || sbrk(0) != a + 4096){ 1382 printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c); 1383 exit(); 1384 } 1385 if(*lastaddr == 99){ 1386 // should be zero 1387 printf(stdout, "sbrk de-allocation didn't really deallocate\n"); 1388 exit(); 1389 } 1390 1391 a = sbrk(0); 1392 c = sbrk(-(sbrk(0) - oldbrk)); 1393 if(c != a){ 1394 printf(stdout, "sbrk downsize failed, a %x c %x\n", a, c); 1395 exit(); 1396 } 1397 1398 // can we read the kernel's memory? 1399 for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){ 1400 ppid = getpid(); 1401 pid = fork(); 1402 if(pid < 0){ 1403 printf(stdout, "fork failed\n"); 1404 exit(); 1405 } 1406 if(pid == 0){ 1407 printf(stdout, "oops could read %x = %x\n", a, *a); 1408 kill(ppid); 1409 exit(); 1410 } 1411 wait(); 1412 } 1413 1414 // if we run the system out of memory, does it clean up the last 1415 // failed allocation? 1416 if(pipe(fds) != 0){ 1417 printf(1, "pipe() failed\n"); 1418 exit(); 1419 } 1420 for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ 1421 if((pids[i] = fork()) == 0){ 1422 // allocate a lot of memory 1423 sbrk(BIG - (uint)sbrk(0)); 1424 write(fds[1], "x", 1); 1425 // sit around until killed 1426 for(;;) sleep(1000); 1427 } 1428 if(pids[i] != -1) 1429 read(fds[0], &scratch, 1); 1430 } 1431 // if those failed allocations freed up the pages they did allocate, 1432 // we'll be able to allocate here 1433 c = sbrk(4096); 1434 for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ 1435 if(pids[i] == -1) 1436 continue; 1437 kill(pids[i]); 1438 wait(); 1439 } 1440 if(c == (char*)0xffffffff){ 1441 printf(stdout, "failed sbrk leaked memory\n"); 1442 exit(); 1443 } 1444 1445 if(sbrk(0) > oldbrk) 1446 sbrk(-(sbrk(0) - oldbrk)); 1447 1448 printf(stdout, "sbrk test OK\n"); 1449 } 1450 1451 void 1452 validateint(int *p) 1453 { 1454 int res; 1455 #ifndef X64 1456 asm("mov %%esp, %%ebx\n\t" 1457 "mov %3, %%esp\n\t" 1458 "int %2\n\t" 1459 "mov %%ebx, %%esp" : 1460 "=a" (res) : 1461 "a" (SYS_sleep), "n" (T_SYSCALL), "c" (p) : 1462 "ebx"); 1463 #endif 1464 } 1465 1466 void 1467 validatetest(void) 1468 { 1469 int hi, pid; 1470 uint p; 1471 1472 printf(stdout, "validate test\n"); 1473 hi = 1100*1024; 1474 1475 for(p = 0; p <= (uint)hi; p += 4096){ 1476 if((pid = fork()) == 0){ 1477 // try to crash the kernel by passing in a badly placed integer 1478 validateint((int*)p); 1479 exit(); 1480 } 1481 sleep(0); 1482 sleep(0); 1483 kill(pid); 1484 wait(); 1485 1486 // try to crash the kernel by passing in a bad string pointer 1487 if(link("nosuchfile", (char*)p) != -1){ 1488 printf(stdout, "link should not succeed\n"); 1489 exit(); 1490 } 1491 } 1492 1493 printf(stdout, "validate ok\n"); 1494 } 1495 1496 // does unintialized data start out zero? 1497 char uninit[10000]; 1498 void 1499 bsstest(void) 1500 { 1501 int i; 1502 1503 printf(stdout, "bss test\n"); 1504 for(i = 0; i < sizeof(uninit); i++){ 1505 if(uninit[i] != '\0'){ 1506 printf(stdout, "bss test failed\n"); 1507 exit(); 1508 } 1509 } 1510 printf(stdout, "bss test ok\n"); 1511 } 1512 1513 // does exec return an error if the arguments 1514 // are larger than a page? or does it write 1515 // below the stack and wreck the instructions/data? 1516 void 1517 bigargtest(void) 1518 { 1519 int pid, fd; 1520 1521 unlink("bigarg-ok"); 1522 pid = fork(); 1523 if(pid == 0){ 1524 static char *args[MAXARG]; 1525 int i; 1526 for(i = 0; i < MAXARG-1; i++) 1527 args[i] = "bigargs test: failed\n "; 1528 args[MAXARG-1] = 0; 1529 printf(stdout, "bigarg test\n"); 1530 exec("echo", args); 1531 printf(stdout, "bigarg test ok\n"); 1532 fd = open("bigarg-ok", O_CREATE); 1533 close(fd); 1534 exit(); 1535 } else if(pid < 0){ 1536 printf(stdout, "bigargtest: fork failed\n"); 1537 exit(); 1538 } 1539 wait(); 1540 fd = open("bigarg-ok", 0); 1541 if(fd < 0){ 1542 printf(stdout, "bigarg test failed!\n"); 1543 exit(); 1544 } 1545 close(fd); 1546 unlink("bigarg-ok"); 1547 } 1548 1549 // what happens when the file system runs out of blocks? 1550 // answer: balloc panics, so this test is not useful. 1551 void 1552 fsfull() 1553 { 1554 int nfiles; 1555 int fsblocks = 0; 1556 1557 printf(1, "fsfull test\n"); 1558 1559 for(nfiles = 0; ; nfiles++){ 1560 char name[64]; 1561 name[0] = 'f'; 1562 name[1] = '0' + nfiles / 1000; 1563 name[2] = '0' + (nfiles % 1000) / 100; 1564 name[3] = '0' + (nfiles % 100) / 10; 1565 name[4] = '0' + (nfiles % 10); 1566 name[5] = '\0'; 1567 printf(1, "writing %s\n", name); 1568 int fd = open(name, O_CREATE|O_RDWR); 1569 if(fd < 0){ 1570 printf(1, "open %s failed\n", name); 1571 break; 1572 } 1573 int total = 0; 1574 while(1){ 1575 int cc = write(fd, buf, 512); 1576 if(cc < 512) 1577 break; 1578 total += cc; 1579 fsblocks++; 1580 } 1581 printf(1, "wrote %d bytes\n", total); 1582 close(fd); 1583 if(total == 0) 1584 break; 1585 } 1586 1587 while(nfiles >= 0){ 1588 char name[64]; 1589 name[0] = 'f'; 1590 name[1] = '0' + nfiles / 1000; 1591 name[2] = '0' + (nfiles % 1000) / 100; 1592 name[3] = '0' + (nfiles % 100) / 10; 1593 name[4] = '0' + (nfiles % 10); 1594 name[5] = '\0'; 1595 unlink(name); 1596 nfiles--; 1597 } 1598 1599 printf(1, "fsfull test finished\n"); 1600 } 1601 1602 unsigned long randstate = 1; 1603 unsigned int 1604 rand() 1605 { 1606 randstate = randstate * 1664525 + 1013904223; 1607 return randstate; 1608 } 1609 1610 int 1611 main(int argc, char *argv[]) 1612 { 1613 printf(1, "usertests starting\n"); 1614 1615 if(open("usertests.ran", 0) >= 0){ 1616 printf(1, "already ran user tests -- rebuild fs.img\n"); 1617 exit(); 1618 } 1619 close(open("usertests.ran", O_CREATE)); 1620 1621 bigargtest(); 1622 bigwrite(); 1623 bigargtest(); 1624 bsstest(); 1625 sbrktest(); 1626 validatetest(); 1627 1628 opentest(); 1629 writetest(); 1630 writetest1(); 1631 createtest(); 1632 1633 mem(); 1634 pipe1(); 1635 preempt(); 1636 exitwait(); 1637 1638 rmdot(); 1639 fourteen(); 1640 bigfile(); 1641 subdir(); 1642 concreate(); 1643 linkunlink(); 1644 linktest(); 1645 unlinkread(); 1646 createdelete(); 1647 twofiles(); 1648 sharedfd(); 1649 dirfile(); 1650 iref(); 1651 forktest(); 1652 bigdir(); // slow 1653 1654 exectest(); 1655 1656 exit(); 1657 }