use oxpcie only if enabled to avoid baud bottleneck of uart.
[minix.git] / test / test50.c
blob7da55f0168e1177c3d47df66b15d35287d6bc6f9
1 /* Tests for truncate(2) call family - by D.C. van Moolenbroek */
2 #define _POSIX_SOURCE 1
3 #include <sys/stat.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <assert.h>
8 #define ITERATIONS 1
9 #define MAX_ERROR 4
11 #define TESTFILE "testfile"
12 #define TESTSIZE 4096
13 #define THRESHOLD 1048576
15 #ifndef MIN
16 #define MIN(x,y) (((x)<(y))?(x):(y))
17 #endif
19 #include "common.c"
21 _PROTOTYPE(int main, (int argc, char *argv[]));
22 _PROTOTYPE(void prepare, (void));
23 _PROTOTYPE(int make_file, (off_t size));
24 _PROTOTYPE(void check_file, (int fd, off_t size, off_t hole_start,
25 off_t hole_end));
26 _PROTOTYPE(void all_sizes,
27 (_PROTOTYPE(void (*call), (off_t osize, off_t nsize))));
28 _PROTOTYPE(void test50a, (void));
29 _PROTOTYPE(void test50b, (void));
30 _PROTOTYPE(void test50c, (void));
31 _PROTOTYPE(void test50d, (void));
32 _PROTOTYPE(void sub50e, (off_t osize, off_t nsize));
33 _PROTOTYPE(void test50e, (void));
34 _PROTOTYPE(void sub50f, (off_t osize, off_t nsize));
35 _PROTOTYPE(void test50f, (void));
36 _PROTOTYPE(void sub50g, (off_t osize, off_t nsize));
37 _PROTOTYPE(void test50g, (void));
38 _PROTOTYPE(void sub50h, (off_t osize, off_t nsize));
39 _PROTOTYPE(void test50h, (void));
40 _PROTOTYPE(void sub50i, (off_t size, off_t off, size_t len, int type));
41 _PROTOTYPE(void test50i, (void));
43 /* Some of the sizes have been chosen in such a way that they should be on the
44 * edge of direct/single indirect/double indirect switchovers for a MINIX
45 * file system with 4K block size.
47 static off_t sizes[] = {
48 0L, 1L, 511L, 512L, 513L, 1023L, 1024L, 1025L, 2047L, 2048L, 2049L, 3071L,
49 3072L, 3073L, 4095L, 4096L, 4097L, 16383L, 16384L, 16385L, 28671L, 28672L,
50 28673L, 65535L, 65536L, 65537L, 4222975L, 4222976L, 4222977L
53 static unsigned char *data;
55 int main(argc, argv)
56 int argc;
57 char *argv[];
59 int i, j, m = 0xFFFF;
61 start(50);
62 prepare();
63 if (argc == 2) m = atoi(argv[1]);
64 for (j = 0; j < ITERATIONS; j++) {
65 if (m & 00001) test50a();
66 if (m & 00002) test50b();
67 if (m & 00004) test50c();
68 if (m & 00010) test50d();
69 if (m & 00020) test50e();
70 if (m & 00040) test50f();
71 if (m & 00100) test50g();
72 if (m & 00200) test50h();
73 if (m & 00400) test50i();
76 quit();
77 return(-1); /* impossible */
80 void prepare()
82 size_t largest;
83 int i;
85 largest = 0;
86 for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++)
87 if (largest < sizes[i]) largest = sizes[i];
89 /* internal integrity check: this is needed for early tests */
90 assert(largest >= TESTSIZE);
92 data = malloc(largest);
93 if (data == NULL) e(1000);
95 srand(1);
97 for (i = 0; i < largest; i++)
98 data[i] = (unsigned char) (rand() % 255 + 1);
101 void all_sizes(call)
102 _PROTOTYPE(void (*call), (off_t osize, off_t nsize));
104 int i, j;
106 for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++)
107 for (j = 0; j < sizeof(sizes) / sizeof(sizes[0]); j++)
108 call(sizes[i], sizes[j]);
111 int make_file(size)
112 off_t size;
114 off_t off;
115 int i, fd, r;
117 if ((fd = open(TESTFILE, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0) e(1001);
119 off = 0;
120 while (off < size) {
121 r = write(fd, data + off, size - off);
123 if (r != size - off) e(1002);
125 off += r;
128 return fd;
131 void check_file(fd, hole_start, hole_end, size)
132 int fd;
133 off_t hole_start;
134 off_t hole_end;
135 off_t size;
137 static unsigned char buf[16384];
138 struct stat statbuf;
139 off_t off;
140 int i, chunk;
142 /* The size must match. */
143 if (fstat(fd, &statbuf) != 0) e(1003);
144 if (statbuf.st_size != size) e(1004);
146 if (lseek(fd, 0L, SEEK_SET) != 0L) e(1005);
148 /* All bytes in the file must be equal to what we wrote, except for the bytes
149 * in the hole, which must be zero.
151 for (off = 0; off < size; off += chunk) {
152 chunk = MIN(sizeof(buf), size - off);
154 if (read(fd, buf, chunk) != chunk) e(1006);
156 for (i = 0; i < chunk; i++) {
157 if (off + i >= hole_start && off + i < hole_end) {
158 if (buf[i] != 0) e(1007);
160 else {
161 if (buf[i] != data[off+i]) e(1008);
166 /* We must get back EOF at the end. */
167 if (read(fd, buf, sizeof(buf)) != 0) e(1009);
170 void test50a()
172 struct stat statbuf;
173 int fd;
175 subtest = 1;
177 if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
179 if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
181 /* Negative sizes should result in EINVAL. */
182 if (truncate(TESTFILE, -1) != -1) e(3);
183 if (errno != EINVAL) e(4);
185 /* Make sure the file size did not change. */
186 if (fstat(fd, &statbuf) != 0) e(5);
187 if (statbuf.st_size != TESTSIZE) e(6);
189 close(fd);
190 if (unlink(TESTFILE) != 0) e(7);
192 /* An empty path should result in ENOENT. */
193 if (truncate("", 0) != -1) e(8);
194 if (errno != ENOENT) e(9);
196 /* A non-existing file name should result in ENOENT. */
197 if (truncate(TESTFILE"2", 0) != -1) e(10);
198 if (errno != ENOENT) e(11);
201 void test50b()
203 struct stat statbuf;
204 int fd;
206 subtest = 2;
208 if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
210 if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
212 /* Negative sizes should result in EINVAL. */
213 if (ftruncate(fd, -1) != -1) e(3);
214 if (errno != EINVAL) e(4);
216 /* Make sure the file size did not change. */
217 if (fstat(fd, &statbuf) != 0) e(5);
218 if (statbuf.st_size != TESTSIZE) e(6);
220 close(fd);
222 /* Calls on an invalid file descriptor should return EBADF or EINVAL. */
223 if (ftruncate(fd, 0) != -1) e(7);
224 if (errno != EBADF && errno != EINVAL) e(8);
226 if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(9);
228 /* Calls on a file opened read-only should return EBADF or EINVAL. */
229 if (ftruncate(fd, 0) != -1) e(10);
230 if (errno != EBADF && errno != EINVAL) e(11);
232 close(fd);
234 if (unlink(TESTFILE) != 0) e(12);
237 void test50c()
239 struct stat statbuf;
240 struct flock flock;
241 off_t off;
242 int fd;
244 subtest = 3;
246 if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
248 if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
250 off = TESTSIZE / 2;
251 if (lseek(fd, off, SEEK_SET) != off) e(3);
253 flock.l_len = 0;
255 /* Negative sizes should result in EINVAL. */
256 flock.l_whence = SEEK_SET;
257 flock.l_start = -1;
258 if (fcntl(fd, F_FREESP, &flock) != -1) e(4);
259 if (errno != EINVAL) e(5);
261 flock.l_whence = SEEK_CUR;
262 flock.l_start = -off - 1;
263 if (fcntl(fd, F_FREESP, &flock) != -1) e(6);
264 if (errno != EINVAL) e(7);
266 flock.l_whence = SEEK_END;
267 flock.l_start = -TESTSIZE - 1;
268 if (fcntl(fd, F_FREESP, &flock) != -1) e(8);
269 if (errno != EINVAL) e(9);
271 /* Make sure the file size did not change. */
272 if (fstat(fd, &statbuf) != 0) e(10);
273 if (statbuf.st_size != TESTSIZE) e(11);
275 /* Proper negative values should work, however. */
276 flock.l_whence = SEEK_CUR;
277 flock.l_start = -1;
278 if (fcntl(fd, F_FREESP, &flock) != 0) e(12);
280 if (fstat(fd, &statbuf) != 0) e(13);
281 if (statbuf.st_size != off - 1) e(14);
283 flock.l_whence = SEEK_END;
284 flock.l_start = -off + 1;
285 if (fcntl(fd, F_FREESP, &flock) != 0) e(15);
287 if (fstat(fd, &statbuf) != 0) e(16);
288 if (statbuf.st_size != 0L) e(17);
290 close(fd);
292 /* Calls on an invalid file descriptor should return EBADF or EINVAL. */
293 flock.l_whence = SEEK_SET;
294 flock.l_start = 0;
295 if (fcntl(fd, F_FREESP, &flock) != -1) e(18);
296 if (errno != EBADF && errno != EINVAL) e(19);
298 if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(20);
300 /* Calls on a file opened read-only should return EBADF or EINVAL. */
301 if (fcntl(fd, F_FREESP, &flock) != -1) e(21);
302 if (errno != EBADF && errno != EINVAL) e(22);
304 close(fd);
306 if (unlink(TESTFILE) != 0) e(23);
309 void test50d()
311 struct stat statbuf;
312 struct flock flock;
313 off_t off;
314 int fd;
316 subtest = 4;
318 if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
320 if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
322 off = TESTSIZE / 2;
323 if (lseek(fd, off, SEEK_SET) != off) e(3);
325 /* The given length must be positive. */
326 flock.l_whence = SEEK_CUR;
327 flock.l_start = 0;
328 flock.l_len = -1;
329 if (fcntl(fd, F_FREESP, &flock) != -1) e(4);
330 if (errno != EINVAL) e(5);
332 /* Negative start positions are not allowed. */
333 flock.l_whence = SEEK_SET;
334 flock.l_start = -1;
335 flock.l_len = 1;
336 if (fcntl(fd, F_FREESP, &flock) != -1) e(6);
337 if (errno != EINVAL) e(7);
339 flock.l_whence = SEEK_CUR;
340 flock.l_start = -off - 1;
341 if (fcntl(fd, F_FREESP, &flock) != -1) e(8);
342 if (errno != EINVAL) e(9);
344 flock.l_whence = SEEK_END;
345 flock.l_start = -TESTSIZE - 1;
346 if (fcntl(fd, F_FREESP, &flock) != -1) e(10);
347 if (errno != EINVAL) e(11);
349 /* Start positions at or beyond the end of the file are no good, either. */
350 flock.l_whence = SEEK_SET;
351 flock.l_start = TESTSIZE;
352 if (fcntl(fd, F_FREESP, &flock) != -1) e(12);
353 if (errno != EINVAL) e(13);
355 flock.l_start = TESTSIZE + 1;
356 if (fcntl(fd, F_FREESP, &flock) != -1) e(13);
357 if (errno != EINVAL) e(14);
359 flock.l_whence = SEEK_CUR;
360 flock.l_start = TESTSIZE - off;
361 if (fcntl(fd, F_FREESP, &flock) != -1) e(15);
362 if (errno != EINVAL) e(16);
364 flock.l_whence = SEEK_END;
365 flock.l_start = 1;
366 if (fcntl(fd, F_FREESP, &flock) != -1) e(17);
367 if (errno != EINVAL) e(18);
369 /* End positions beyond the end of the file may be silently bounded. */
370 flock.l_whence = SEEK_SET;
371 flock.l_start = 0;
372 flock.l_len = TESTSIZE + 1;
373 if (fcntl(fd, F_FREESP, &flock) != 0) e(19);
375 flock.l_whence = SEEK_CUR;
376 flock.l_len = TESTSIZE - off + 1;
377 if (fcntl(fd, F_FREESP, &flock) != 0) e(20);
379 flock.l_whence = SEEK_END;
380 flock.l_start = -1;
381 flock.l_len = 2;
382 if (fcntl(fd, F_FREESP, &flock) != 0) e(21);
384 /* However, this must never cause the file size to change. */
385 if (fstat(fd, &statbuf) != 0) e(22);
386 if (statbuf.st_size != TESTSIZE) e(23);
388 close(fd);
390 /* Calls on an invalid file descriptor should return EBADF or EINVAL. */
391 flock.l_whence = SEEK_SET;
392 flock.l_start = 0;
393 if (fcntl(fd, F_FREESP, &flock) != -1) e(24);
394 if (errno != EBADF && errno != EINVAL) e(25);
396 if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(26);
398 /* Calls on a file opened read-only should return EBADF or EINVAL. */
399 if (fcntl(fd, F_FREESP, &flock) != -1) e(27);
400 if (errno != EBADF && errno != EINVAL) e(28);
402 close(fd);
404 if (unlink(TESTFILE) != 0) e(29);
407 void sub50e(osize, nsize)
408 off_t osize;
409 off_t nsize;
411 int fd;
413 fd = make_file(osize);
415 if (truncate(TESTFILE, nsize) != 0) e(1);
417 check_file(fd, osize, nsize, nsize);
419 if (nsize < osize) {
420 if (truncate(TESTFILE, osize) != 0) e(2);
422 check_file(fd, nsize, osize, osize);
425 close(fd);
427 if (unlink(TESTFILE) != 0) e(3);
431 void test50e()
433 subtest = 5;
435 /* truncate(2) on a file that is open. */
436 all_sizes(sub50e);
439 void sub50f(osize, nsize)
440 off_t osize;
441 off_t nsize;
443 int fd;
445 fd = make_file(osize);
447 close(fd);
449 if (truncate(TESTFILE, nsize) != 0) e(1);
451 if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(2);
453 check_file(fd, osize, nsize, nsize);
455 if (nsize < osize) {
456 close(fd);
458 if (truncate(TESTFILE, osize) != 0) e(3);
460 if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(4);
462 check_file(fd, nsize, osize, osize);
465 close(fd);
467 if (unlink(TESTFILE) != 0) e(5);
470 void test50f()
472 subtest = 6;
474 /* truncate(2) on a file that is not open. */
475 all_sizes(sub50f);
478 void sub50g(osize, nsize)
479 off_t osize;
480 off_t nsize;
482 int fd, r;
484 fd = make_file(osize);
486 if (ftruncate(fd, nsize) != 0) e(1);
488 check_file(fd, osize, nsize, nsize);
490 if (nsize < osize) {
491 if (ftruncate(fd, osize) != 0) e(2);
493 check_file(fd, nsize, osize, osize);
496 close(fd);
498 if (unlink(TESTFILE) != 0) e(3);
501 void test50g()
503 subtest = 7;
505 /* ftruncate(2) on an open file. */
506 all_sizes(sub50g);
509 void sub50h(osize, nsize)
510 off_t osize;
511 off_t nsize;
513 struct flock flock;
514 int fd;
516 fd = make_file(osize);
518 flock.l_whence = SEEK_SET;
519 flock.l_start = nsize;
520 flock.l_len = 0;
521 if (fcntl(fd, F_FREESP, &flock) != 0) e(1);
523 check_file(fd, osize, nsize, nsize);
525 if (nsize < osize) {
526 flock.l_whence = SEEK_SET;
527 flock.l_start = osize;
528 flock.l_len = 0;
529 if (fcntl(fd, F_FREESP, &flock) != 0) e(2);
531 check_file(fd, nsize, osize, osize);
534 close(fd);
536 if (unlink(TESTFILE) != 0) e(3);
539 void test50h()
541 subtest = 8;
543 /* fcntl(2) with F_FREESP and l_len=0. */
544 all_sizes(sub50h);
547 void sub50i(size, off, len, type)
548 off_t size;
549 off_t off;
550 size_t len;
551 int type;
553 struct flock flock;
554 int fd;
556 fd = make_file(size);
558 switch (type) {
559 case 0:
560 flock.l_whence = SEEK_SET;
561 flock.l_start = off;
562 break;
563 case 1:
564 if (lseek(fd, off, SEEK_SET) != off) e(1);
565 flock.l_whence = SEEK_CUR;
566 flock.l_start = 0;
567 break;
568 case 2:
569 flock.l_whence = SEEK_END;
570 flock.l_start = off - size;
571 break;
572 default:
573 e(1);
576 flock.l_len = len;
577 if (fcntl(fd, F_FREESP, &flock) != 0) e(2);
579 check_file(fd, off, off + len, size);
581 /* Repeat the call in order to see whether the file system can handle holes
582 * while freeing up. If not, the server would typically crash; we need not
583 * check the results again.
585 flock.l_whence = SEEK_SET;
586 flock.l_start = off;
587 if (fcntl(fd, F_FREESP, &flock) != 0) e(3);
589 close(fd);
591 if (unlink(TESTFILE) != 0) e(4);
594 void test50i()
596 off_t off;
597 int i, j, k, l;
599 subtest = 9;
601 /* fcntl(2) with F_FREESP and l_len>0. */
603 /* This loop determines the size of the test file. */
604 for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) {
605 /* Big files simply take too long. We have to compromise here. */
606 if (sizes[i] >= THRESHOLD) continue;
608 /* This loop determines one of the two values for the offset. */
609 for (j = 0; j < sizeof(sizes) / sizeof(sizes[0]); j++) {
610 if (sizes[j] >= sizes[i]) continue;
612 /* This loop determines the other. */
613 for (k = 0; k < sizeof(sizes) / sizeof(sizes[0]); k++) {
614 if (sizes[k] > sizes[j]) continue;
616 /* Construct an offset by adding the two sizes. */
617 off = sizes[j] + sizes[k];
619 if (j + 1 < sizeof(sizes) / sizeof(sizes[0]) &&
620 off >= sizes[j + 1]) continue;
622 /* This loop determines the length of the hole. */
623 for (l = 0; l < sizeof(sizes) / sizeof(sizes[0]); l++) {
624 if (sizes[l] == 0 || off + sizes[l] > sizes[i])
625 continue;
627 /* This could have been a loop, too! */
628 sub50i(sizes[i], off, sizes[l], 0);
629 sub50i(sizes[i], off, sizes[l], 1);
630 sub50i(sizes[i], off, sizes[l], 2);