11 #include <sys/types.h> 15 static char testfile[1024];
16 static char testfile2[1024];
17 static char testdir[1024];
18 static char testdir2[1024];
19 static char subfile[1024];
21 static char testfile_r[1024];
22 static char testfile2_r[1024];
23 static char testdir_r[1024];
24 static char testdir2_r[1024];
25 static char subfile_r[1024];
27 static char testname[256];
28 static char testdata[] =
"abcdefghijklmnopqrstuvwxyz";
29 static char testdata2[] =
"1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
30 static const char *testdir_files[] = {
"f1",
"f2", NULL};
31 static char zerodata[4096];
32 static int testdatalen =
sizeof(testdata) - 1;
33 static int testdata2len =
sizeof(testdata2) - 1;
34 static unsigned int testnum = 1;
35 static unsigned int select_test = 0;
36 static unsigned int skip_test = 0;
38 #define MAX_ENTRIES 1024 40 static void test_perror(
const char *func,
const char *msg)
42 fprintf(stderr,
"%s %s() - %s: %s\n", testname, func, msg,
46 static void test_error(
const char *func,
const char *msg, ...)
47 __attribute__ ((format (printf, 2, 3)));
49 static
void __start_test(const
char *fmt, ...)
50 __attribute__ ((format (printf, 1, 2)));
52 static
void test_error(const
char *func, const
char *msg, ...)
55 fprintf(stderr,
"%s %s() - ", testname, func);
57 vfprintf(stderr, msg, ap);
59 fprintf(stderr,
"\n");
62 static void success(
void)
64 fprintf(stderr,
"%s OK\n", testname);
67 static void __start_test(
const char *fmt, ...)
71 n = sprintf(testname,
"%3i [", testnum++);
73 n += vsprintf(testname + n, fmt, ap);
75 sprintf(testname + n,
"]");
78 #define start_test(msg, args...) { \ 79 if ((select_test && testnum != select_test) || \ 80 (testnum == skip_test)) { \ 84 __start_test(msg, ##args); \ 87 #define PERROR(msg) test_perror(__FUNCTION__, msg) 88 #define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args) 90 static int check_size(
const char *path,
int len)
93 int res = stat(path, &stbuf);
98 if (stbuf.st_size != len) {
99 ERROR(
"length %u instead of %u", (
int) stbuf.st_size,
106 static int fcheck_size(
int fd,
int len)
109 int res = fstat(fd, &stbuf);
114 if (stbuf.st_size != len) {
115 ERROR(
"length %u instead of %u", (
int) stbuf.st_size,
122 static int check_type(
const char *path, mode_t type)
125 int res = lstat(path, &stbuf);
130 if ((stbuf.st_mode & S_IFMT) != type) {
131 ERROR(
"type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
137 static int fcheck_type(
int fd, mode_t type)
140 int res = fstat(fd, &stbuf);
145 if ((stbuf.st_mode & S_IFMT) != type) {
146 ERROR(
"type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
152 static int check_mode(
const char *path, mode_t mode)
155 int res = lstat(path, &stbuf);
160 if ((stbuf.st_mode & 07777) != mode) {
161 ERROR(
"mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
167 static int fcheck_mode(
int fd, mode_t mode)
170 int res = fstat(fd, &stbuf);
175 if ((stbuf.st_mode & 07777) != mode) {
176 ERROR(
"mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
182 static int check_times(
const char *path, time_t atime, time_t mtime)
186 int res = lstat(path, &stbuf);
191 if (stbuf.st_atime != atime) {
192 ERROR(
"atime %li instead of %li", stbuf.st_atime, atime);
195 if (stbuf.st_mtime != mtime) {
196 ERROR(
"mtime %li instead of %li", stbuf.st_mtime, mtime);
206 static int fcheck_times(
int fd, time_t atime, time_t mtime)
210 int res = fstat(fd, &stbuf);
215 if (stbuf.st_atime != atime) {
216 ERROR(
"atime %li instead of %li", stbuf.st_atime, atime);
219 if (stbuf.st_mtime != mtime) {
220 ERROR(
"mtime %li instead of %li", stbuf.st_mtime, mtime);
230 static int check_nlink(
const char *path, nlink_t nlink)
233 int res = lstat(path, &stbuf);
238 if (stbuf.st_nlink != nlink) {
239 ERROR(
"nlink %li instead of %li", (
long) stbuf.st_nlink,
246 static int fcheck_nlink(
int fd, nlink_t nlink)
249 int res = fstat(fd, &stbuf);
254 if (stbuf.st_nlink != nlink) {
255 ERROR(
"nlink %li instead of %li", (
long) stbuf.st_nlink,
262 static int check_nonexist(
const char *path)
265 int res = lstat(path, &stbuf);
267 ERROR(
"file should not exist");
270 if (errno != ENOENT) {
271 ERROR(
"file should not exist: %s", strerror(errno));
277 static int check_buffer(
const char *buf,
const char *data,
unsigned len)
279 if (memcmp(buf, data, len) != 0) {
280 ERROR(
"data mismatch");
286 static int check_data(
const char *path,
const char *data,
int offset,
291 int fd = open(path, O_RDONLY);
296 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
302 int rdlen = len <
sizeof(buf) ? len :
sizeof(buf);
303 res = read(fd, buf, rdlen);
310 ERROR(
"short read: %u instead of %u", res, rdlen);
314 if (check_buffer(buf, data, rdlen) != 0) {
329 static int fcheck_data(
int fd,
const char *data,
int offset,
334 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
339 int rdlen = len <
sizeof(buf) ? len :
sizeof(buf);
340 res = read(fd, buf, rdlen);
346 ERROR(
"short read: %u instead of %u", res, rdlen);
349 if (check_buffer(buf, data, rdlen) != 0) {
358 static int check_dir_contents(
const char *path,
const char **contents)
363 int found[MAX_ENTRIES];
364 const char *cont[MAX_ENTRIES];
367 for (i = 0; contents[i]; i++) {
368 assert(i < MAX_ENTRIES - 3);
370 cont[i] = contents[i];
383 memset(found, 0,
sizeof(found));
396 for (i = 0; cont[i] != NULL; i++) {
397 assert(i < MAX_ENTRIES);
398 if (strcmp(cont[i], de->d_name) == 0) {
400 ERROR(
"duplicate entry <%s>",
409 ERROR(
"unexpected entry <%s>", de->d_name);
413 for (i = 0; cont[i] != NULL; i++) {
415 ERROR(
"missing entry <%s>", cont[i]);
430 static int create_file(
const char *path,
const char *data,
int len)
436 fd = creat(path, 0644);
442 res = write(fd, data, len);
449 ERROR(
"write is short: %u instead of %u", res, len);
459 res = check_type(path, S_IFREG);
462 res = check_mode(path, 0644);
465 res = check_nlink(path, 1);
468 res = check_size(path, len);
473 res = check_data(path, data, 0, len);
481 static int cleanup_dir(
const char *path,
const char **dir_files,
int quiet)
486 for (i = 0; dir_files[i]; i++) {
489 sprintf(fpath,
"%s/%s", path, dir_files[i]);
491 if (res == -1 && !quiet) {
502 static int create_dir(
const char *path,
const char **dir_files)
508 res = mkdir(path, 0755);
513 res = check_type(path, S_IFDIR);
516 res = check_mode(path, 0755);
520 for (i = 0; dir_files[i]; i++) {
522 sprintf(fpath,
"%s/%s", path, dir_files[i]);
523 res = create_file(fpath,
"", 0);
525 cleanup_dir(path, dir_files, 1);
529 res = check_dir_contents(path, dir_files);
531 cleanup_dir(path, dir_files, 1);
538 static int test_truncate(
int len)
540 const char *data = testdata;
541 int datalen = testdatalen;
544 start_test(
"truncate(%u)", (
int) len);
545 res = create_file(testfile, data, datalen);
549 res = truncate(testfile, len);
554 res = check_size(testfile, len);
559 if (len <= datalen) {
560 res = check_data(testfile, data, 0, len);
564 res = check_data(testfile, data, 0, datalen);
567 res = check_data(testfile, zerodata, datalen,
573 res = unlink(testfile);
578 res = check_nonexist(testfile);
586 static int test_ftruncate(
int len,
int mode)
588 const char *data = testdata;
589 int datalen = testdatalen;
593 start_test(
"ftruncate(%u) mode: 0%03o", len, mode);
594 res = create_file(testfile, data, datalen);
598 fd = open(testfile, O_WRONLY);
604 res = fchmod(fd, mode);
610 res = check_mode(testfile, mode);
615 res = ftruncate(fd, len);
622 res = check_size(testfile, len);
627 if (len <= datalen) {
628 res = check_data(testfile, data, 0, len);
632 res = check_data(testfile, data, 0, datalen);
635 res = check_data(testfile, zerodata, datalen,
641 res = unlink(testfile);
646 res = check_nonexist(testfile);
654 static int test_utime(
void)
657 time_t atime = 987631200;
658 time_t mtime = 123116400;
662 res = create_file(testfile, NULL, 0);
668 res = utime(testfile, &utm);
673 res = check_times(testfile, atime, mtime);
677 res = unlink(testfile);
682 res = check_nonexist(testfile);
690 static int test_create(
void)
692 const char *data = testdata;
693 int datalen = testdatalen;
698 start_test(
"create");
700 fd = creat(testfile, 0644);
705 res = write(fd, data, datalen);
711 if (res != datalen) {
712 ERROR(
"write is short: %u instead of %u", res, datalen);
721 res = check_type(testfile, S_IFREG);
724 err += check_mode(testfile, 0644);
725 err += check_nlink(testfile, 1);
726 err += check_size(testfile, datalen);
727 err += check_data(testfile, data, 0, datalen);
728 res = unlink(testfile);
733 res = check_nonexist(testfile);
743 static int test_create_unlink(
void)
745 const char *data = testdata;
746 int datalen = testdatalen;
751 start_test(
"create+unlink");
753 fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
758 res = unlink(testfile);
764 res = check_nonexist(testfile);
767 res = write(fd, data, datalen);
773 if (res != datalen) {
774 ERROR(
"write is short: %u instead of %u", res, datalen);
778 err += fcheck_type(fd, S_IFREG);
779 err += fcheck_mode(fd, 0644);
780 err += fcheck_nlink(fd, 0);
781 err += fcheck_size(fd, datalen);
782 err += fcheck_data(fd, data, 0, datalen);
796 static int test_mknod(
void)
803 res = mknod(testfile, 0644, 0);
808 res = check_type(testfile, S_IFREG);
811 err += check_mode(testfile, 0644);
812 err += check_nlink(testfile, 1);
813 err += check_size(testfile, 0);
814 res = unlink(testfile);
819 res = check_nonexist(testfile);
830 #define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode) 832 static int do_test_open(
int exist,
int flags,
const char *flags_str,
int mode)
835 const char *data = testdata;
836 int datalen = testdatalen;
837 unsigned currlen = 0;
843 start_test(
"open(%s, %s, 0%03o)", exist ?
"+" :
"-", flags_str, mode);
846 res = create_file(testfile_r, testdata2, testdata2len);
850 currlen = testdata2len;
853 fd = open(testfile, flags, mode);
854 if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
856 ERROR(
"open should have failed");
859 }
else if (errno == EEXIST)
862 if (!(flags & O_CREAT) && !exist) {
864 ERROR(
"open should have failed");
867 }
else if (errno == ENOENT)
878 err += check_type(testfile, S_IFREG);
880 err += check_mode(testfile, 0644);
882 err += check_mode(testfile, mode);
883 err += check_nlink(testfile, 1);
884 err += check_size(testfile, currlen);
885 if (exist && !(flags & O_TRUNC) && (mode & 0400))
886 err += check_data(testfile, testdata2, 0, testdata2len);
888 res = write(fd, data, datalen);
889 if ((flags & O_ACCMODE) != O_RDONLY) {
893 }
else if (res != datalen) {
894 ERROR(
"write is short: %u instead of %u", res, datalen);
897 if (datalen > (
int) currlen)
900 err += check_size(testfile, currlen);
903 err += check_data(testfile, data, 0, datalen);
904 if (exist && !(flags & O_TRUNC) &&
905 testdata2len > datalen)
906 err += check_data(testfile,
909 testdata2len - datalen);
914 ERROR(
"write should have failed");
916 }
else if (errno != EBADF) {
921 off = lseek(fd, SEEK_SET, 0);
922 if (off == (off_t) -1) {
925 }
else if (off != 0) {
926 ERROR(
"offset should have returned 0");
929 res = read(fd, buf,
sizeof(buf));
930 if ((flags & O_ACCMODE) != O_WRONLY) {
936 currlen <
sizeof(buf) ? currlen :
sizeof(buf);
937 if (res != readsize) {
938 ERROR(
"read is short: %i instead of %u",
942 if ((flags & O_ACCMODE) != O_RDONLY) {
943 err += check_buffer(buf, data, datalen);
944 if (exist && !(flags & O_TRUNC) &&
945 testdata2len > datalen)
946 err += check_buffer(buf + datalen,
948 testdata2len - datalen);
950 err += check_buffer(buf, testdata2,
956 ERROR(
"read should have failed");
958 }
else if (errno != EBADF) {
969 res = unlink(testfile);
974 res = check_nonexist(testfile);
977 res = check_nonexist(testfile_r);
988 #define test_open_acc(flags, mode, err) \ 989 do_test_open_acc(flags, #flags, mode, err) 991 static int do_test_open_acc(
int flags,
const char *flags_str,
int mode,
int err)
993 const char *data = testdata;
994 int datalen = testdatalen;
998 start_test(
"open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
1001 res = create_file(testfile, data, datalen);
1005 res = chmod(testfile, mode);
1011 res = check_mode(testfile, mode);
1015 fd = open(testfile, flags);
1023 ERROR(
"open should have failed");
1033 static int test_symlink(
void)
1036 const char *data = testdata;
1037 int datalen = testdatalen;
1038 int linklen = strlen(testfile);
1042 start_test(
"symlink");
1043 res = create_file(testfile, data, datalen);
1048 res = symlink(testfile, testfile2);
1053 res = check_type(testfile2, S_IFLNK);
1056 err += check_mode(testfile2, 0777);
1057 err += check_nlink(testfile2, 1);
1058 res = readlink(testfile2, buf,
sizeof(buf));
1063 if (res != linklen) {
1064 ERROR(
"short readlink: %u instead of %u", res, linklen);
1067 if (memcmp(buf, testfile, linklen) != 0) {
1068 ERROR(
"link mismatch");
1071 err += check_size(testfile2, datalen);
1072 err += check_data(testfile2, data, 0, datalen);
1073 res = unlink(testfile2);
1078 res = check_nonexist(testfile2);
1088 static int test_link(
void)
1090 const char *data = testdata;
1091 int datalen = testdatalen;
1096 res = create_file(testfile, data, datalen);
1101 res = link(testfile, testfile2);
1106 res = check_type(testfile2, S_IFREG);
1109 err += check_mode(testfile2, 0644);
1110 err += check_nlink(testfile2, 2);
1111 err += check_size(testfile2, datalen);
1112 err += check_data(testfile2, data, 0, datalen);
1113 res = unlink(testfile);
1118 res = check_nonexist(testfile);
1122 err += check_nlink(testfile2, 1);
1123 res = unlink(testfile2);
1128 res = check_nonexist(testfile2);
1138 static int test_link2(
void)
1140 const char *data = testdata;
1141 int datalen = testdatalen;
1145 start_test(
"link-unlink-link");
1146 res = create_file(testfile, data, datalen);
1151 res = link(testfile, testfile2);
1156 res = unlink(testfile);
1161 res = check_nonexist(testfile);
1164 res = link(testfile2, testfile);
1168 res = check_type(testfile, S_IFREG);
1171 err += check_mode(testfile, 0644);
1172 err += check_nlink(testfile, 2);
1173 err += check_size(testfile, datalen);
1174 err += check_data(testfile, data, 0, datalen);
1176 res = unlink(testfile2);
1181 err += check_nlink(testfile, 1);
1182 res = unlink(testfile);
1187 res = check_nonexist(testfile);
1197 static int test_rename_file(
void)
1199 const char *data = testdata;
1200 int datalen = testdatalen;
1204 start_test(
"rename file");
1205 res = create_file(testfile, data, datalen);
1210 res = rename(testfile, testfile2);
1215 res = check_nonexist(testfile);
1218 res = check_type(testfile2, S_IFREG);
1221 err += check_mode(testfile2, 0644);
1222 err += check_nlink(testfile2, 1);
1223 err += check_size(testfile2, datalen);
1224 err += check_data(testfile2, data, 0, datalen);
1225 res = unlink(testfile2);
1230 res = check_nonexist(testfile2);
1240 static int test_rename_dir(
void)
1245 start_test(
"rename dir");
1246 res = create_dir(testdir, testdir_files);
1251 res = rename(testdir, testdir2);
1254 cleanup_dir(testdir, testdir_files, 1);
1257 res = check_nonexist(testdir);
1259 cleanup_dir(testdir, testdir_files, 1);
1262 res = check_type(testdir2, S_IFDIR);
1264 cleanup_dir(testdir2, testdir_files, 1);
1267 err += check_mode(testdir2, 0755);
1268 err += check_dir_contents(testdir2, testdir_files);
1269 err += cleanup_dir(testdir2, testdir_files, 0);
1270 res = rmdir(testdir2);
1275 res = check_nonexist(testdir2);
1286 static int test_mkfifo(
void)
1291 start_test(
"mkfifo");
1293 res = mkfifo(testfile, 0644);
1298 res = check_type(testfile, S_IFIFO);
1301 err += check_mode(testfile, 0644);
1302 err += check_nlink(testfile, 1);
1303 res = unlink(testfile);
1308 res = check_nonexist(testfile);
1319 static int test_mkdir(
void)
1323 const char *dir_contents[] = {NULL};
1325 start_test(
"mkdir");
1327 res = mkdir(testdir, 0755);
1332 res = check_type(testdir, S_IFDIR);
1335 err += check_mode(testdir, 0755);
1339 err += check_dir_contents(testdir, dir_contents);
1340 res = rmdir(testdir);
1345 res = check_nonexist(testdir);
1355 #define test_create_ro_dir(flags) \ 1356 do_test_create_ro_dir(flags, #flags) 1358 static int do_test_create_ro_dir(
int flags,
const char *flags_str)
1364 start_test(
"open(%s) in read-only directory", flags_str);
1366 res = mkdir(testdir, 0555);
1371 fd = open(subfile, flags, 0644);
1375 ERROR(
"open should have failed");
1378 res = check_nonexist(subfile);
1383 res = rmdir(testdir);
1388 res = check_nonexist(testdir);
1398 int main(
int argc,
char *argv[])
1400 const char *basepath;
1401 const char *realpath;
1407 if (argc < 2 || argc > 4) {
1408 fprintf(stderr,
"usage: %s testdir [:realdir] [[-]test#]\n", argv[0]);
1412 realpath = basepath;
1413 for (a = 2; a < argc; a++) {
1415 char *arg = argv[a];
1416 if (arg[0] ==
':') {
1419 if (arg[0] ==
'-') {
1421 skip_test = strtoul(arg, &endptr, 10);
1423 select_test = strtoul(arg, &endptr, 10);
1425 if (arg[0] ==
'\0' || *endptr !=
'\0') {
1426 fprintf(stderr,
"invalid number: '%s'\n", arg);
1431 assert(strlen(basepath) < 512);
1432 assert(strlen(realpath) < 512);
1433 if (basepath[0] !=
'/') {
1434 fprintf(stderr,
"testdir must be an absolute path\n");
1438 sprintf(testfile,
"%s/testfile", basepath);
1439 sprintf(testfile2,
"%s/testfile2", basepath);
1440 sprintf(testdir,
"%s/testdir", basepath);
1441 sprintf(testdir2,
"%s/testdir2", basepath);
1442 sprintf(subfile,
"%s/subfile", testdir2);
1444 sprintf(testfile_r,
"%s/testfile", realpath);
1445 sprintf(testfile2_r,
"%s/testfile2", realpath);
1446 sprintf(testdir_r,
"%s/testdir", realpath);
1447 sprintf(testdir2_r,
"%s/testdir2", realpath);
1448 sprintf(subfile_r,
"%s/subfile", testdir2_r);
1450 is_root = (geteuid() == 0);
1452 err += test_create();
1453 err += test_create_unlink();
1454 err += test_symlink();
1456 err += test_link2();
1458 err += test_mknod();
1459 err += test_mkfifo();
1461 err += test_mkdir();
1462 err += test_rename_file();
1463 err += test_rename_dir();
1464 err += test_utime();
1465 err += test_truncate(0);
1466 err += test_truncate(testdatalen / 2);
1467 err += test_truncate(testdatalen);
1468 err += test_truncate(testdatalen + 100);
1469 err += test_ftruncate(0, 0600);
1470 err += test_ftruncate(testdatalen / 2, 0600);
1471 err += test_ftruncate(testdatalen, 0600);
1472 err += test_ftruncate(testdatalen + 100, 0600);
1473 err += test_ftruncate(0, 0400);
1474 err += test_ftruncate(0, 0200);
1475 err += test_ftruncate(0, 0000);
1476 err += test_open(0, O_RDONLY, 0);
1477 err += test_open(1, O_RDONLY, 0);
1478 err += test_open(1, O_RDWR, 0);
1479 err += test_open(1, O_WRONLY, 0);
1480 err += test_open(0, O_RDWR | O_CREAT, 0600);
1481 err += test_open(1, O_RDWR | O_CREAT, 0600);
1482 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
1483 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
1484 err += test_open(0, O_RDONLY | O_CREAT, 0600);
1485 err += test_open(0, O_RDONLY | O_CREAT, 0400);
1486 err += test_open(0, O_RDONLY | O_CREAT, 0200);
1487 err += test_open(0, O_RDONLY | O_CREAT, 0000);
1488 err += test_open(0, O_WRONLY | O_CREAT, 0600);
1489 err += test_open(0, O_WRONLY | O_CREAT, 0400);
1490 err += test_open(0, O_WRONLY | O_CREAT, 0200);
1491 err += test_open(0, O_WRONLY | O_CREAT, 0000);
1492 err += test_open(0, O_RDWR | O_CREAT, 0400);
1493 err += test_open(0, O_RDWR | O_CREAT, 0200);
1494 err += test_open(0, O_RDWR | O_CREAT, 0000);
1495 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
1496 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
1497 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
1498 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
1499 err += test_open_acc(O_RDONLY, 0600, 0);
1500 err += test_open_acc(O_WRONLY, 0600, 0);
1501 err += test_open_acc(O_RDWR, 0600, 0);
1502 err += test_open_acc(O_RDONLY, 0400, 0);
1503 err += test_open_acc(O_WRONLY, 0200, 0);
1505 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
1506 err += test_open_acc(O_WRONLY, 0400, EACCES);
1507 err += test_open_acc(O_RDWR, 0400, EACCES);
1508 err += test_open_acc(O_RDONLY, 0200, EACCES);
1509 err += test_open_acc(O_RDWR, 0200, EACCES);
1510 err += test_open_acc(O_RDONLY, 0000, EACCES);
1511 err += test_open_acc(O_WRONLY, 0000, EACCES);
1512 err += test_open_acc(O_RDWR, 0000, EACCES);
1514 err += test_create_ro_dir(O_CREAT);
1515 err += test_create_ro_dir(O_CREAT | O_EXCL);
1516 err += test_create_ro_dir(O_CREAT | O_WRONLY);
1517 err += test_create_ro_dir(O_CREAT | O_TRUNC);
1525 fprintf(stderr,
"%i tests failed\n", -err);