Update dmapi test suite, add Makefiles, remove Conscript files.
[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             if (length > curlength) {
196               if(curlength>0)
197                 free(bufp);
198               if ((bufp = malloc(length)) == NULL) {
199                 fprintf(stderr, "malloc of %llu bytes failed\n", length);
200                 continue;
201               }
202               curlength = length;
203               memset(bufp, ch, length);
204             }
205
206             rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
207                                 0, offset, length, bufp);
208             cont = 0;
209             if (rc < 0) {
210               fprintf(stderr, "dm_write_invis failed, %s\n", ERR_NAME);
211               cont=1;
212             } else if (rc != length) {
213               fprintf(stderr, "expected to write %lld bytes, actually "
214                       "wrote %lld\n", length, rc);
215               cont=1;
216             }
217             if(cont)
218                 continue;
219             
220             /* Timestamp checking, part 1 */
221             if (stat(test_file, &checkbuf)){
222               fprintf(stdout, 
223                       "Error: unable to stat the test file; %s (after write)\n", 
224                       test_file);
225             }
226             else {
227 #ifdef __sgi
228               if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
229               (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
230               (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
231               (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
232               (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
233               (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
234 #else
235               if ((statbuf.st_atime == checkbuf.st_atime) &&
236               (statbuf.st_mtime == checkbuf.st_mtime) &&
237               (statbuf.st_ctime == checkbuf.st_ctime))
238 #endif
239                 {
240                 if (Vflag) {
241                   printf("Report: time stamp unchanged by write\n");
242                 }
243               }
244               else {
245                 printf("Error: time stamp changed by write\n");
246               }
247             }
248             
249             rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
250                                 offset, length, bufp);
251             if (rc < 0) {
252               fprintf(stderr, "dm_read_invis failed, %s\n", ERR_NAME);
253               continue;
254             } 
255             else if (rc != length) {
256               fprintf(stderr, "expected to read %lld bytes, actually "
257                       "wrote %lld\n", length, rc);
258               continue;
259             }
260             else {
261               /* Be sure the buffer is filled with the test char */
262               error_reported = 0;
263               for (k=0; k<i; k++){
264                 if (((char *)bufp)[k] == ch) {
265                   if (Vflag) printf(".");
266                 }
267                 else {
268                   if(!error_reported){
269                         printf("Error!(line=%d)\n", __LINE__);
270                         error_reported++;
271                   }
272                 }
273               }
274               if (Vflag) printf("\n");
275             }
276
277             /* Timestamp checking, part 2 */
278             if (stat(test_file, &statbuf)){
279               fprintf(stdout, 
280                       "Error: unable to stat the test file; %s (after write)\n", 
281                       test_file);
282             }
283             else {
284 #ifdef __sgi
285               if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
286               (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
287               (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
288               (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
289               (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
290               (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
291 #else
292               if ((statbuf.st_atime == checkbuf.st_atime) &&
293               (statbuf.st_mtime == checkbuf.st_mtime) &&
294               (statbuf.st_ctime == checkbuf.st_ctime))
295 #endif
296                 {
297                 if (Vflag) {
298                   printf("Report: time stamp unchanged by read\n");
299                 }
300               }
301               else {
302                 printf("Error: time stamp changed by read\n");
303               }
304             }
305           } /* for (j=0; j<OFF_MAX; j+=OFF_STEP) */
306         } /* for(i=0; i<LEN_MAX; i+=LEN_STEP) */
307         
308         /* File deletion loop*/
309         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
310           for(j=0; j<OFF_MAX; j+=OFF_STEP) {
311             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
312                     dir_name, i, j);
313             sprintf(command, "rm %s\n", test_file); 
314             system(command);
315           }
316         }
317         
318         /*************************************\
319         |* Correct-input testing complete.   *|
320         |* Beginning improper-input testing. *|
321         \*************************************/
322         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
323                 dir_name);
324         sprintf(command, "cp %s %s\n", ls_path, test_file); 
325         system(command);
326
327         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
328           fprintf(stderr, "can't get handle for %s; bypassing errno tests\n",
329                   test_file);
330         }
331         else {
332
333           /* Try writing a character waaaaaay up in the millions range */
334           sprintf(bufp, "%c", ch);
335           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
336                              (1000000*(unsigned int)(ch)), 1, bufp)==-1){
337             printf("Error invis-writing %s at byte %u million: %s\n", 
338                    (char*)bufp, (unsigned int)ch, ERR_NAME);
339           }
340           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
341                                  (1000000*(unsigned int)(ch)), 1, bufp)==-1){
342             printf("Error invis-reading at byte %u million: %s\n",
343                    (unsigned int)ch, ERR_NAME);
344           }
345           else if (((char*)bufp)[0]!=ch) {
346             printf("Error: wanted to read %c and instead got %s.\n",
347                    ch, (char*)bufp);
348           }
349           else if (Vflag) {
350             printf("Report: \"%c\" was written and \"%s\" was read "
351                    "at byte %d million.\n", ch, (char*)bufp, ch);
352           }
353
354 #ifdef __sgi
355           /* Try writing a character in the 2 gigabyte (2^31) range */
356           sprintf(bufp, "%c", ch);
357           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
358                              2147840000, 1, bufp)==-1){
359             printf("Error invis-writing %s at 2 gigabytes: %s\n", 
360                    (char*)bufp, ERR_NAME);
361           }
362           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
363                                  2147840000, 1, bufp)==-1){
364             printf("Error invis-reading at 2 gigabytes: %s\n",
365                    ERR_NAME);
366           }
367           else if (((char*)bufp)[0]!=ch) {
368             printf("Error: wanted to read %c and instead got %s.\n",
369                    ch, (char*)bufp);
370           }
371           else if (Vflag) {
372             printf("Report: \"%c\" was written and \"%s\" was read "
373                    "at 2147840000 bytes\n\t(a bit over 2 gigabytes).\n", 
374                    ch, (char*)bufp);
375           }
376 #endif
377
378           printf("\t(errno subtests beginning...)\n");
379           /**** WRITE tests ****/
380           /*---------------------------------------------------------*/
381           EXCLTEST("write", hanp, hlen, test_token, 
382                    dm_write_invis(sid, hanp, hlen, test_token,
383                                   0, 0, 13, "write test 1"))
384           /*---------------------------------------------------------*/
385             if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
386             fprintf(stderr, 
387                     "Cannot create a test handle (%s); skipping EBADF test\n",
388                     ERR_NAME);
389           }
390           else {
391             ((char *) test_vp)[hlen/2]++;
392             ERRTEST(EBADF,
393                     "write",
394                     dm_write_invis(sid, test_vp, hlen, DM_NO_TOKEN,
395                                    0, 0, 0, bufp))
396             ERRTEST(EBADF,
397                     "read",
398                     dm_read_invis(sid, test_vp, hlen, DM_NO_TOKEN,
399                                   0, 0, bufp))
400             dm_handle_free(test_vp, hlen);
401           }
402
403           /*---------------------------------------------------------*/
404           ERRTEST(EBADF,
405                   "write",
406                   dm_write_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
407                                  0, 0, 0, NULL))
408           /*---------------------------------------------------------*/
409           ERRTEST(EFAULT,
410                   "write",
411                   dm_write_invis(sid, NULL, hlen, DM_NO_TOKEN,
412                                  0, 0, 0, NULL))
413           /*---------------------------------------------------------*/
414 #if 0
415           PROBLEM: write_invis refuses to produce EINVAL for 
416           lengths that will not fit in a dm_size_t.
417
418           ERRTEST(EINVAL,
419                   "(bad length) write",
420                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
421                                  0, 4096, (long long)0xFFFFFFFFFFFFFFFFLL,
422                                  "write invalid length test"))
423 #endif
424           /*---------------------------------------------------------*/
425 #if 0
426           PROBLEM (somewhat fixed): A signal is sent, rather than EFBIG.
427           Presumably, this signal is needed to comply with...something.
428           If this is uncommented, the program will abort here, with the 
429           error message "exceeded file size limit". 
430
431           ERRTEST(EFBIG,
432                   "write",
433                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
434                                  0, (long long)0xFFFFFFFFFFLL, 
435                                  (long long)0xFFFFFFFFFFLL,
436                                  "foo foo foo"))
437 #endif
438           /*---------------------------------------------------------*/
439 #ifdef VERITAS_21
440           ERRTEST(EINVAL,
441                   "(bad offset) write",
442                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
443                                  0, (dm_size_t) ULONG_MAX, 5,
444                                  "write invalid offset test"))
445 #else
446 #ifndef linux
447           ERRTEST(EINVAL,
448                   "(bad offset) write",
449                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
450                                  0, (dm_size_t) ULONGLONG_MAX, 5,
451                                  "write invalid offset test"))
452 #endif
453 #endif
454
455           /*---------------------------------------------------------*/
456           ERRTEST(EINVAL,
457                   "(bad sid) write",
458                   dm_write_invis(-100, hanp, hlen, DM_NO_TOKEN,
459                                  0, 0, 26, "write invalid offset test"))
460
461
462           /**** READ tests ****/
463           /*---------------------------------------------------------*/
464           SHAREDTEST("read", hanp, hlen, test_token,
465                      dm_read_invis(sid, hanp, hlen, test_token, 
466                                    0, 13, bufp))
467           /*---------------------------------------------------------*/
468           ERRTEST(EBADF,
469                   "read",
470                   dm_read_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
471                                  0, 0, bufp))
472           /*---------------------------------------------------------*/
473           ERRTEST(EFAULT,
474                   "read",
475                   dm_read_invis(sid, NULL, hlen, DM_NO_TOKEN,
476                                  0, 0, bufp))
477           /*---------------------------------------------------------*/
478 #ifdef  VERITAS_21
479           ERRTEST(EINVAL,
480                   "(bad offset) read",
481                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
482                                 ULONG_MAX, 5, bufp));
483 #else
484 #ifndef linux
485           ERRTEST(EINVAL,
486                   "(bad offset) read",
487                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
488                                 ULONGLONG_MAX, 5, bufp));
489 #endif
490 #endif
491
492           /*---------------------------------------------------------*/
493           ERRTEST(EINVAL,
494                   "(bad sid) read",
495                   dm_read_invis(-100, hanp, hlen, DM_NO_TOKEN,
496                                 0, 5, bufp))
497           /*---------------------------------------------------------*/
498           printf("\t(errno subtests complete!)\n");
499         }
500         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
501                 dir_name);
502         sprintf(command, "rm %s \n", test_file); 
503         system(command);
504
505         printf("Invisible read/write tests complete.\n");
506
507         dm_handle_free(hanp, hlen);
508         exit(0);
509 }