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