check: allow '-e testid' to exclude a single test
[xfstests-dev.git] / dmapi / src / suite2 / src / test_invis.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2001 Silicon Graphics, Inc.
4  * All Rights Reserved.
5  */
6
7 #include <sys/types.h>
8 #include <sys/stat.h>
9
10 #include <limits.h>
11
12 #include <lib/hsm.h>
13 #include <lib/errtest.h>
14
15 #include <getopt.h>
16 #include <string.h>
17 #include <time.h>
18
19 /*---------------------------------------------------------------------------
20
21 Automated test of the DMAPI functions dm_write_invis() and dm_read_invis()
22
23 The command line is:
24
25         test_invis [-s sid] [-v] ls_path pathname
26
27 where:
28    sid
29       is the session ID whose events you you are interested in.
30    ls_path
31       is the path to a specific copy of ls, important only for its size
32    pathname
33       is the filesystem to use for the test.
34
35 DM_WRITE_SYNC is is not supported.
36 ----------------------------------------------------------------------------*/
37
38 #define OFF_MAX  50
39 #define OFF_STEP 5
40 #define LEN_MAX  50
41 #define LEN_STEP 5
42
43 #ifndef linux
44 extern  char    *sys_errlist[];
45 #endif
46 extern  int     optind;
47 extern  char    *optarg;
48
49
50 char    *Progname;
51
52
53 static void
54 usage(void)
55 {
56         fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path pathname\n", 
57                 Progname);
58         exit(1);
59 }
60
61
62 int
63 main(
64         int     argc, 
65         char    **argv)
66 {
67         dm_sessid_t     sid = DM_NO_SESSION;
68         char            *dir_name = NULL;
69         char            *ls_path = NULL;
70         dm_off_t        offset = 0;
71         dm_size_t       length = 1;
72         dm_size_t       curlength = 0;
73         u_char          ch;
74         void            *bufp = NULL;
75         void            *hanp;
76         size_t          hlen;
77         dm_ssize_t      rc;
78         char            *name;
79         char            test_file[128];
80         char            command[128];
81         int             opt;
82         int             i;
83         int             j;
84         int             k;
85         int             Vflag=0;
86         struct stat     statbuf;
87         struct stat     checkbuf;
88         dm_token_t      test_token;
89         void*           test_vp;
90         int             cont;
91         int             error_reported;
92
93         Progname = strrchr(argv[0], '/');
94         if (Progname) {
95                 Progname++;
96         } else {
97                 Progname = argv[0];
98         }
99
100         /* Crack and validate the command line options. */
101
102         while ((opt = getopt(argc, argv, "vs:")) != EOF) {
103                 switch (opt) {
104                 case 'v':
105                         Vflag++;
106                         break;
107                 case 's':
108                         sid = atol(optarg);
109                         break;
110                 case '?':
111                         usage();
112                 }
113         }
114         if (optind + 2 != argc)
115                 usage();
116         ls_path = argv[optind];
117         dir_name = argv[optind+1];
118
119         if (dm_init_service(&name) == -1)  {
120                 fprintf(stderr, "Can't initialize the DMAPI\n");
121                 exit(1);
122         }
123         if (sid == DM_NO_SESSION)
124                 find_test_session(&sid);
125         
126         /* Get a random character for read/write tests */
127         srand((unsigned int)time(NULL));
128         ch = (u_char)rand(); 
129
130         printf("Invisible read/write tests beginning...\n");
131         
132         /* File creation loop*/
133         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
134           for (j=0; j<OFF_MAX; j+=OFF_STEP) {
135             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
136                     dir_name, i, j);
137             sprintf(command, "cp %s %s\n", ls_path, test_file); 
138             system(command);
139           }
140         }
141         
142         /* Write to files, then read them to check for correct results. 
143            Do timestamp checking along the way. */
144
145         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
146           for (j=0; j<OFF_MAX; j+=OFF_STEP) {
147
148 #define max(a,b) ((a) > (b) ? (a) : (b))
149             length = max((dm_size_t)(i), length);
150             offset = (dm_off_t)(j);
151
152             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
153                     dir_name, i, j);
154             
155             if (stat(test_file, &statbuf)){
156               fprintf(stdout, 
157                       "Error: unable to stat test file; %s (before test)\n", 
158                       test_file);
159               continue;
160             }
161             
162             if (dm_path_to_handle(test_file, &hanp, &hlen)) {
163               fprintf(stderr, "can't get handle for %s; bypassing test\n",
164                       test_file);
165               continue;
166             }
167             
168             if (length > curlength) {
169               if(curlength>0)
170                 free(bufp);
171               if ((bufp = malloc(length)) == NULL) {
172                 fprintf(stderr, "malloc of %llu bytes failed\n",
173                         (unsigned long long) length);
174                 continue;
175               }
176               curlength = length;
177               memset(bufp, ch, length);
178             }
179
180             rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
181                                 0, offset, length, bufp);
182             cont = 0;
183             if (rc < 0) {
184               fprintf(stderr, "dm_write_invis failed, %s\n", ERR_NAME);
185               cont=1;
186             } else if (rc != length) {
187               fprintf(stderr, "expected to write %lld bytes, actually "
188                       "wrote %lld\n", (long long) length, (long long) rc);
189               cont=1;
190             }
191             if(cont)
192                 continue;
193             
194             /* Timestamp checking, part 1 */
195             if (stat(test_file, &checkbuf)){
196               fprintf(stdout, 
197                       "Error: unable to stat the test file; %s (after write)\n", 
198                       test_file);
199             }
200             else {
201               if ((statbuf.st_atime == checkbuf.st_atime) &&
202               (statbuf.st_mtime == checkbuf.st_mtime) &&
203               (statbuf.st_ctime == checkbuf.st_ctime))
204                 {
205                 if (Vflag) {
206                   printf("Report: time stamp unchanged by write\n");
207                 }
208               }
209               else {
210                 printf("Error: time stamp changed by write\n");
211               }
212             }
213             
214             rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
215                                 offset, length, bufp);
216             if (rc < 0) {
217               fprintf(stderr, "dm_read_invis failed, %s\n", ERR_NAME);
218               continue;
219             } 
220             else if (rc != length) {
221               fprintf(stderr, "expected to read %lld bytes, actually "
222                       "wrote %lld\n", (long long) length, (long long) rc);
223               continue;
224             }
225             else {
226               /* Be sure the buffer is filled with the test char */
227               error_reported = 0;
228               for (k=0; k<i; k++){
229                 if (((u_char *)bufp)[k] == ch) {
230                   if (Vflag) printf(".");
231                 }
232                 else {
233                   if(!error_reported){
234                         printf("Error!(line=%d)\n", __LINE__);
235                         error_reported++;
236                   }
237                 }
238               }
239               if (Vflag) printf("\n");
240             }
241
242             /* Timestamp checking, part 2 */
243             if (stat(test_file, &statbuf)){
244               fprintf(stdout, 
245                       "Error: unable to stat the test file; %s (after write)\n", 
246                       test_file);
247             }
248             else {
249               if ((statbuf.st_atime == checkbuf.st_atime) &&
250               (statbuf.st_mtime == checkbuf.st_mtime) &&
251               (statbuf.st_ctime == checkbuf.st_ctime))
252                 {
253                 if (Vflag) {
254                   printf("Report: time stamp unchanged by read\n");
255                 }
256               }
257               else {
258                 printf("Error: time stamp changed by read\n");
259               }
260             }
261           } /* for (j=0; j<OFF_MAX; j+=OFF_STEP) */
262         } /* for(i=0; i<LEN_MAX; i+=LEN_STEP) */
263         
264         /* File deletion loop*/
265         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
266           for(j=0; j<OFF_MAX; j+=OFF_STEP) {
267             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
268                     dir_name, i, j);
269             sprintf(command, "rm %s\n", test_file); 
270             system(command);
271           }
272         }
273         
274         /*************************************\
275         |* Correct-input testing complete.   *|
276         |* Beginning improper-input testing. *|
277         \*************************************/
278         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
279                 dir_name);
280         sprintf(command, "cp %s %s\n", ls_path, test_file); 
281         system(command);
282
283         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
284           fprintf(stderr, "can't get handle for %s; bypassing errno tests\n",
285                   test_file);
286         }
287         else {
288           dm_off_t offset;
289
290           /* Try writing a character waaaaaay up in the millions range */
291           sprintf(bufp, "%c", ch);
292           if (stat(test_file, &statbuf)){
293            fprintf(stdout, 
294                     "Error: unable to stat the test file; %s \n", 
295                     test_file);
296           }
297           offset = ((1000000*(dm_off_t)(ch)) > statbuf.st_size) ? 
298                             statbuf.st_size : (1000000*(dm_off_t)(ch));
299           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
300                              offset, 1, bufp)==-1){
301             printf("Error invis-writing 0x%x at byte 0x%x million: %s\n", 
302                    *(u_char *)bufp, (unsigned int)ch, ERR_NAME);
303           }
304           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
305                                  offset, 1, bufp)==-1){
306             printf("Error invis-reading at byte %u million: %s\n",
307                    (unsigned int)ch, ERR_NAME);
308           }
309           else if (((u_char *)bufp)[0]!=ch) {
310             printf("Error: wanted to read %c and instead got %s.\n",
311                    ch, (u_char *)bufp);
312           }
313           else if (Vflag) {
314             printf("Report: \"0x%x\" was written and \"0x%x\" was read "
315                    "at byte %d million.\n", ch, *(u_char *)bufp, ch);
316           }
317           printf("\t(errno subtests beginning...)\n");
318           /**** WRITE tests ****/
319           /*---------------------------------------------------------*/
320           EXCLTEST("write", hanp, hlen, test_token, 
321                    dm_write_invis(sid, hanp, hlen, test_token,
322                                   0, 0, 13, "write test 1"))
323           /*---------------------------------------------------------*/
324             if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
325             fprintf(stderr, 
326                     "Cannot create a test handle (%s); skipping EBADF test\n",
327                     ERR_NAME);
328           }
329           else {
330             ((char *) test_vp)[hlen/2]++;
331             ERRTEST(EBADF,
332                     "write",
333                     dm_write_invis(sid, test_vp, hlen, DM_NO_TOKEN,
334                                    0, 0, 0, bufp))
335             ERRTEST(EBADF,
336                     "read",
337                     dm_read_invis(sid, test_vp, hlen, DM_NO_TOKEN,
338                                   0, 0, bufp))
339             dm_handle_free(test_vp, hlen);
340           }
341
342           /*---------------------------------------------------------*/
343           ERRTEST(EBADF,
344                   "write",
345                   dm_write_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
346                                  0, 0, 0, NULL))
347           /*---------------------------------------------------------*/
348           ERRTEST(EFAULT,
349                   "write",
350                   dm_write_invis(sid, NULL, hlen, DM_NO_TOKEN,
351                                  0, 0, 0, NULL))
352           /*---------------------------------------------------------*/
353 #if 0
354           PROBLEM: write_invis refuses to produce EINVAL for 
355           lengths that will not fit in a dm_size_t.
356
357           ERRTEST(EINVAL,
358                   "(bad length) write",
359                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
360                                  0, 4096, (long long)0xFFFFFFFFFFFFFFFFLL,
361                                  "write invalid length test"))
362 #endif
363           /*---------------------------------------------------------*/
364 #if 0
365           PROBLEM (somewhat fixed): A signal is sent, rather than EFBIG.
366           Presumably, this signal is needed to comply with...something.
367           If this is uncommented, the program will abort here, with the 
368           error message "exceeded file size limit". 
369
370           ERRTEST(EFBIG,
371                   "write",
372                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
373                                  0, (long long)0xFFFFFFFFFFLL, 
374                                  (long long)0xFFFFFFFFFFLL,
375                                  "foo foo foo"))
376 #endif
377           /*---------------------------------------------------------*/
378 #ifdef VERITAS_21
379           ERRTEST(EINVAL,
380                   "(bad offset) write",
381                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
382                                  0, (dm_size_t) ULONG_MAX, 5,
383                                  "write invalid offset test"))
384 #else
385 #ifndef linux
386           ERRTEST(EINVAL,
387                   "(bad offset) write",
388                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
389                                  0, (dm_size_t) ULONGLONG_MAX, 5,
390                                  "write invalid offset test"))
391 #endif
392 #endif
393
394           /*---------------------------------------------------------*/
395           ERRTEST(EINVAL,
396                   "(bad sid) write",
397                   dm_write_invis(-100, hanp, hlen, DM_NO_TOKEN,
398                                  0, 0, 26, "write invalid offset test"))
399
400
401           /**** READ tests ****/
402           /*---------------------------------------------------------*/
403           SHAREDTEST("read", hanp, hlen, test_token,
404                      dm_read_invis(sid, hanp, hlen, test_token, 
405                                    0, 13, bufp))
406           /*---------------------------------------------------------*/
407           ERRTEST(EBADF,
408                   "read",
409                   dm_read_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
410                                  0, 0, bufp))
411           /*---------------------------------------------------------*/
412           ERRTEST(EFAULT,
413                   "read",
414                   dm_read_invis(sid, NULL, hlen, DM_NO_TOKEN,
415                                  0, 0, bufp))
416           /*---------------------------------------------------------*/
417 #ifdef  VERITAS_21
418           ERRTEST(EINVAL,
419                   "(bad offset) read",
420                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
421                                 ULONG_MAX, 5, bufp));
422 #else
423 #ifndef linux
424           ERRTEST(EINVAL,
425                   "(bad offset) read",
426                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
427                                 ULONGLONG_MAX, 5, bufp));
428 #endif
429 #endif
430
431           /*---------------------------------------------------------*/
432           ERRTEST(EINVAL,
433                   "(bad sid) read",
434                   dm_read_invis(-100, hanp, hlen, DM_NO_TOKEN,
435                                 0, 5, bufp))
436           /*---------------------------------------------------------*/
437           printf("\t(errno subtests complete!)\n");
438         }
439         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
440                 dir_name);
441         sprintf(command, "rm %s \n", test_file); 
442         system(command);
443
444         printf("Invisible read/write tests complete.\n");
445
446         dm_handle_free(hanp, hlen);
447         exit(0);
448 }