xref: /minix/minix/tests/common.c (revision 7f5f010b)
1 /* Utility routines for Minix tests.
2  * This is designed to be #includ'ed near the top of test programs.  It is
3  * self-contained except for max_error.
4  */
5 
6 #include <errno.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <sys/statvfs.h>
12 #include <sys/syslimits.h>
13 
14 #include "common.h"
15 
16 int common_test_nr = -1, errct = 0, subtest;
17 int quietflag = 1, bigflag = 0;
18 
19 /* provide a default max_error symbol as Max_error with a value
20  * of 5. The test program can override it wit its own max_error
21  * symbol if it wants that this code will then use instead.
22  */
23 __weak_alias(max_error,Max_error);
24 int Max_error = 5;
25 extern int max_error;
26 
27 void start(test_nr)
28 int test_nr;
29 {
30   char buf[64];
31   int i;
32 
33   /* if this variable is set, specify to tests we are running
34    * in 'overnight' mode
35    */
36   bigflag = !!getenv(BIGVARNAME);
37 
38   common_test_nr = test_nr;
39   printf("Test %2d ", test_nr);
40   fflush(stdout);		/* since stdout is probably line buffered */
41   sync();
42   rm_rf_dir(test_nr);
43   sprintf(buf, "mkdir DIR_%02d", test_nr);
44   if (system(buf) != 0) {
45 	e(666);
46 	quit();
47   }
48   sprintf(buf, "DIR_%02d", test_nr);
49   if (chdir(buf) != 0) {
50 	e(6666);
51 	quit();
52   }
53 
54   for (i = 3; i < OPEN_MAX; ++i) {
55 	/* Close all files except stdin, stdout, and stderr */
56 	(void) close(i);
57   }
58 }
59 
60 int does_fs_truncate(void)
61 {
62   struct statvfs stvfs;
63   int does_truncate = 0;
64   char cwd[PATH_MAX];		/* Storage for path to current working dir */
65 
66   if (realpath(".", cwd) == NULL) e(7777);	/* Get current working dir */
67   if (statvfs(cwd, &stvfs) != 0) e(7778);	/* Get FS information */
68   /* Depending on how an FS handles too long file names, we have to adjust our
69    * error checking. If an FS does not truncate file names, it should generate
70    * an ENAMETOOLONG error when we provide too long a file name.
71    */
72   if (!(stvfs.f_flag & ST_NOTRUNC)) does_truncate = 1;
73 
74   return(does_truncate);
75 }
76 
77 int name_max(char *path)
78 {
79   struct statvfs stvfs;
80 
81   if (statvfs(path, &stvfs) != 0) e(7779);
82   return(stvfs.f_namemax);
83 }
84 
85 
86 void rm_rf_dir(test_nr)
87 int test_nr;
88 {
89   char buf[128];
90 
91   sprintf(buf, "rm -rf DIR_%02d >/dev/null 2>&1", test_nr);
92   if (system(buf) != 0) printf("Warning: system(\"%s\") failed\n", buf);
93 }
94 
95 void rm_rf_ppdir(test_nr)
96 int test_nr;
97 {
98 /* Attempt to remove everything in the test directory (== the current dir). */
99 
100   char buf[128];
101 
102   sprintf(buf, "chmod 777 ../DIR_%02d/* ../DIR_%02d/*/* >/dev/null 2>&1",
103 	  test_nr, test_nr);
104   (void) system(buf);
105   sprintf(buf, "rm -rf ../DIR_%02d >/dev/null 2>&1", test_nr);
106   if (system(buf) != 0) printf("Warning: system(\"%s\") failed\n", buf);
107 }
108 
109 void e_f(char *file, int line, int n)
110 {
111   int err_number;
112   err_number = errno;	/* Store before printf can clobber it */
113   if (errct == 0) printf("\n");	/* finish header */
114   printf("%s:%d: Subtest %d,  error %d,  errno %d: %s\n",
115 	file, line, subtest, n, err_number, strerror(err_number));
116   if (++errct > max_error) {
117 	printf("Too many errors; test aborted\n");
118 	cleanup();
119 	exit(1);
120   }
121   errno = err_number;
122 }
123 
124 void cleanup()
125 {
126   if (chdir("..") == 0 && common_test_nr != -1) rm_rf_dir(common_test_nr);
127 }
128 
129 void quit()
130 {
131   cleanup();
132   if (errct == 0) {
133 	printf("ok\n");
134 	exit(0);
135   } else {
136 	printf("%d errors\n", errct);
137 	exit(1);
138   }
139 }
140 
141 void
142 printprogress(char *msg, int i, int max)
143 {
144         int use_i = i + 1;
145         static time_t start_time, prev_time;
146         static int prev_i;
147         time_t now;
148 
149 	if(quietflag) return;
150 
151         time(&now);
152         if(prev_i >= i) start_time = now;
153 
154         if(now > start_time && prev_time < now) {
155                 double i_per_sec = i / (now - start_time);
156                 int remain_secs;
157 
158                 remain_secs = (int)((max-i) / i_per_sec);
159 
160                 fprintf(stderr, "%-35s  %7d/%7d  %3d%%  ETA %3ds\r", msg,
161                       use_i, (max), use_i*100/(max), remain_secs);
162                 fflush(stderr);
163         }
164 
165         if(use_i >= max) {
166                 fprintf(stderr, "%-35s  done                                      \n", msg);
167         }
168 
169         prev_i = i;
170         prev_time = now;
171 }
172 
173 void getmem(u32_t *total, u32_t *free, u32_t *cached)
174 {
175         u32_t pagesize, largest;
176         FILE *f = fopen("/proc/meminfo", "r");
177         if(!f) return;
178         if(fscanf(f, "%u %u %u %u %u", &pagesize, total, free,
179                 &largest, cached) != 5) {
180 		fprintf(stderr, "fscanf of meminfo failed\n");
181 		exit(1);
182 	}
183         fclose(f);
184 }
185 
186