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