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