d97274902341d40b72b2cb379e95d17fffeedc67
[xfstests-dev.git] / dmapi / src / suite2 / src / test_invis.c
1 /*
2  * Copyright (c) 2000-2001 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 #include <getopt.h>
42 #include <string.h>
43 #include <time.h>
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         fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path pathname\n", 
83                 Progname);
84         exit(1);
85 }
86
87
88 int
89 main(
90         int     argc, 
91         char    **argv)
92 {
93         dm_sessid_t     sid = DM_NO_SESSION;
94         char            *dir_name = NULL;
95         char            *ls_path = NULL;
96         dm_off_t        offset = 0;
97         dm_size_t       length = 1;
98         dm_size_t       curlength = 0;
99         u_char          ch;
100         void            *bufp = NULL;
101         void            *hanp;
102         size_t          hlen;
103         dm_ssize_t      rc;
104         char            *name;
105         char            test_file[128];
106         char            command[128];
107         int             opt;
108         int             i;
109         int             j;
110         int             k;
111         int             Vflag=0;
112         struct stat     statbuf;
113         struct stat     checkbuf;
114         dm_token_t      test_token;
115         void*           test_vp;
116         int             cont;
117         int             error_reported;
118
119         if (Progname = strrchr(argv[0], '/')) {
120                 Progname++;
121         } else {
122                 Progname = argv[0];
123         }
124
125         /* Crack and validate the command line options. */
126
127         while ((opt = getopt(argc, argv, "vs:")) != EOF) {
128                 switch (opt) {
129                 case 'v':
130                         Vflag++;
131                         break;
132                 case 's':
133                         sid = atol(optarg);
134                         break;
135                 case '?':
136                         usage();
137                 }
138         }
139         if (optind + 2 != argc)
140                 usage();
141         ls_path = argv[optind];
142         dir_name = argv[optind+1];
143
144         if (dm_init_service(&name) == -1)  {
145                 fprintf(stderr, "Can't initialize the DMAPI\n");
146                 exit(1);
147         }
148         if (sid == DM_NO_SESSION)
149                 find_test_session(&sid);
150         
151         /* Get a random character for read/write tests */
152         srand((unsigned int)time(NULL));
153         ch = (char)rand(); 
154
155         printf("Invisible read/write tests beginning...\n");
156         
157         /* File creation loop*/
158         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
159           for (j=0; j<OFF_MAX; j+=OFF_STEP) {
160             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
161                     dir_name, i, j);
162             sprintf(command, "cp %s %s\n", ls_path, test_file); 
163             system(command);
164           }
165         }
166         
167         /* Write to files, then read them to check for correct results. 
168            Do timestamp checking along the way. */
169
170         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
171           for (j=0; j<OFF_MAX; j+=OFF_STEP) {
172
173 #define max(a,b) ((a) > (b) ? (a) : (b))
174             length = max((dm_size_t)(i), length);
175             offset = (dm_off_t)(j);
176
177             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
178                     dir_name, i, j);
179             
180             if (stat(test_file, &statbuf)){
181               fprintf(stdout, 
182                       "Error: unable to stat test file; %s (before test)\n", 
183                       test_file);
184               continue;
185             }
186             
187             if (dm_path_to_handle(test_file, &hanp, &hlen)) {
188               fprintf(stderr, "can't get handle for %s; bypassing test\n",
189                       test_file);
190               continue;
191             }
192             
193             if (length > curlength) {
194               if(curlength>0)
195                 free(bufp);
196               if ((bufp = malloc(length)) == NULL) {
197                 fprintf(stderr, "malloc of %llu bytes failed\n", length);
198                 continue;
199               }
200               curlength = length;
201               memset(bufp, ch, length);
202             }
203
204             rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
205                                 0, offset, length, bufp);
206             cont = 0;
207             if (rc < 0) {
208               fprintf(stderr, "dm_write_invis failed, %s\n", ERR_NAME);
209               cont=1;
210             } else if (rc != length) {
211               fprintf(stderr, "expected to write %lld bytes, actually "
212                       "wrote %lld\n", length, rc);
213               cont=1;
214             }
215             if(cont)
216                 continue;
217             
218             /* Timestamp checking, part 1 */
219             if (stat(test_file, &checkbuf)){
220               fprintf(stdout, 
221                       "Error: unable to stat the test file; %s (after write)\n", 
222                       test_file);
223             }
224             else {
225 #ifdef __sgi
226               if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
227               (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
228               (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
229               (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
230               (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
231               (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
232 #else
233               if ((statbuf.st_atime == checkbuf.st_atime) &&
234               (statbuf.st_mtime == checkbuf.st_mtime) &&
235               (statbuf.st_ctime == checkbuf.st_ctime))
236 #endif
237                 {
238                 if (Vflag) {
239                   printf("Report: time stamp unchanged by write\n");
240                 }
241               }
242               else {
243                 printf("Error: time stamp changed by write\n");
244               }
245             }
246             
247             rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
248                                 offset, length, bufp);
249             if (rc < 0) {
250               fprintf(stderr, "dm_read_invis failed, %s\n", ERR_NAME);
251               continue;
252             } 
253             else if (rc != length) {
254               fprintf(stderr, "expected to read %lld bytes, actually "
255                       "wrote %lld\n", length, rc);
256               continue;
257             }
258             else {
259               /* Be sure the buffer is filled with the test char */
260               error_reported = 0;
261               for (k=0; k<i; k++){
262                 if (((char *)bufp)[k] == ch) {
263                   if (Vflag) printf(".");
264                 }
265                 else {
266                   if(!error_reported){
267                         printf("Error!(line=%d)\n", __LINE__);
268                         error_reported++;
269                   }
270                 }
271               }
272               if (Vflag) printf("\n");
273             }
274
275             /* Timestamp checking, part 2 */
276             if (stat(test_file, &statbuf)){
277               fprintf(stdout, 
278                       "Error: unable to stat the test file; %s (after write)\n", 
279                       test_file);
280             }
281             else {
282 #ifdef __sgi
283               if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
284               (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
285               (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
286               (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
287               (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
288               (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
289 #else
290               if ((statbuf.st_atime == checkbuf.st_atime) &&
291               (statbuf.st_mtime == checkbuf.st_mtime) &&
292               (statbuf.st_ctime == checkbuf.st_ctime))
293 #endif
294                 {
295                 if (Vflag) {
296                   printf("Report: time stamp unchanged by read\n");
297                 }
298               }
299               else {
300                 printf("Error: time stamp changed by read\n");
301               }
302             }
303           } /* for (j=0; j<OFF_MAX; j+=OFF_STEP) */
304         } /* for(i=0; i<LEN_MAX; i+=LEN_STEP) */
305         
306         /* File deletion loop*/
307         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
308           for(j=0; j<OFF_MAX; j+=OFF_STEP) {
309             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
310                     dir_name, i, j);
311             sprintf(command, "rm %s\n", test_file); 
312             system(command);
313           }
314         }
315         
316         /*************************************\
317         |* Correct-input testing complete.   *|
318         |* Beginning improper-input testing. *|
319         \*************************************/
320         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
321                 dir_name);
322         sprintf(command, "cp %s %s\n", ls_path, test_file); 
323         system(command);
324
325         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
326           fprintf(stderr, "can't get handle for %s; bypassing errno tests\n",
327                   test_file);
328         }
329         else {
330
331           /* Try writing a character waaaaaay up in the millions range */
332           sprintf(bufp, "%c", ch);
333           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
334                              (1000000*(unsigned int)(ch)), 1, bufp)==-1){
335             printf("Error invis-writing %s at byte %u million: %s\n", 
336                    (char*)bufp, (unsigned int)ch, ERR_NAME);
337           }
338           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
339                                  (1000000*(unsigned int)(ch)), 1, bufp)==-1){
340             printf("Error invis-reading at byte %u million: %s\n",
341                    (unsigned int)ch, ERR_NAME);
342           }
343           else if (((char*)bufp)[0]!=ch) {
344             printf("Error: wanted to read %c and instead got %s.\n",
345                    ch, (char*)bufp);
346           }
347           else if (Vflag) {
348             printf("Report: \"%c\" was written and \"%s\" was read "
349                    "at byte %d million.\n", ch, (char*)bufp, ch);
350           }
351
352 #ifdef __sgi
353           /* Try writing a character in the 2 gigabyte (2^31) range */
354           sprintf(bufp, "%c", ch);
355           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
356                              2147840000, 1, bufp)==-1){
357             printf("Error invis-writing %s at 2 gigabytes: %s\n", 
358                    (char*)bufp, ERR_NAME);
359           }
360           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
361                                  2147840000, 1, bufp)==-1){
362             printf("Error invis-reading at 2 gigabytes: %s\n",
363                    ERR_NAME);
364           }
365           else if (((char*)bufp)[0]!=ch) {
366             printf("Error: wanted to read %c and instead got %s.\n",
367                    ch, (char*)bufp);
368           }
369           else if (Vflag) {
370             printf("Report: \"%c\" was written and \"%s\" was read "
371                    "at 2147840000 bytes\n\t(a bit over 2 gigabytes).\n", 
372                    ch, (char*)bufp);
373           }
374 #endif
375
376           printf("\t(errno subtests beginning...)\n");
377           /**** WRITE tests ****/
378           /*---------------------------------------------------------*/
379           EXCLTEST("write", hanp, hlen, test_token, 
380                    dm_write_invis(sid, hanp, hlen, test_token,
381                                   0, 0, 13, "write test 1"))
382           /*---------------------------------------------------------*/
383             if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
384             fprintf(stderr, 
385                     "Cannot create a test handle (%s); skipping EBADF test\n",
386                     ERR_NAME);
387           }
388           else {
389             ((char *) test_vp)[hlen/2]++;
390             ERRTEST(EBADF,
391                     "write",
392                     dm_write_invis(sid, test_vp, hlen, DM_NO_TOKEN,
393                                    0, 0, 0, bufp))
394             ERRTEST(EBADF,
395                     "read",
396                     dm_read_invis(sid, test_vp, hlen, DM_NO_TOKEN,
397                                   0, 0, bufp))
398             dm_handle_free(test_vp, hlen);
399           }
400
401           /*---------------------------------------------------------*/
402           ERRTEST(EBADF,
403                   "write",
404                   dm_write_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
405                                  0, 0, 0, NULL))
406           /*---------------------------------------------------------*/
407           ERRTEST(EFAULT,
408                   "write",
409                   dm_write_invis(sid, NULL, hlen, DM_NO_TOKEN,
410                                  0, 0, 0, NULL))
411           /*---------------------------------------------------------*/
412 #if 0
413           PROBLEM: write_invis refuses to produce EINVAL for 
414           lengths that will not fit in a dm_size_t.
415
416           ERRTEST(EINVAL,
417                   "(bad length) write",
418                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
419                                  0, 4096, (long long)0xFFFFFFFFFFFFFFFFLL,
420                                  "write invalid length test"))
421 #endif
422           /*---------------------------------------------------------*/
423 #if 0
424           PROBLEM (somewhat fixed): A signal is sent, rather than EFBIG.
425           Presumably, this signal is needed to comply with...something.
426           If this is uncommented, the program will abort here, with the 
427           error message "exceeded file size limit". 
428
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 #endif
436           /*---------------------------------------------------------*/
437 #ifdef VERITAS_21
438           ERRTEST(EINVAL,
439                   "(bad offset) write",
440                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
441                                  0, (dm_size_t) ULONG_MAX, 5,
442                                  "write invalid offset test"))
443 #else
444 #ifndef linux
445           ERRTEST(EINVAL,
446                   "(bad offset) write",
447                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
448                                  0, (dm_size_t) ULONGLONG_MAX, 5,
449                                  "write invalid offset test"))
450 #endif
451 #endif
452
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 #ifdef  VERITAS_21
477           ERRTEST(EINVAL,
478                   "(bad offset) read",
479                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
480                                 ULONG_MAX, 5, bufp));
481 #else
482 #ifndef linux
483           ERRTEST(EINVAL,
484                   "(bad offset) read",
485                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
486                                 ULONGLONG_MAX, 5, bufp));
487 #endif
488 #endif
489
490           /*---------------------------------------------------------*/
491           ERRTEST(EINVAL,
492                   "(bad sid) read",
493                   dm_read_invis(-100, hanp, hlen, DM_NO_TOKEN,
494                                 0, 5, bufp))
495           /*---------------------------------------------------------*/
496           printf("\t(errno subtests complete!)\n");
497         }
498         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
499                 dir_name);
500         sprintf(command, "rm %s \n", test_file); 
501         system(command);
502
503         printf("Invisible read/write tests complete.\n");
504
505         dm_handle_free(hanp, hlen);
506         exit(0);
507 }