6f8657ed689a869e16ebdddd435f3f2e1298c55c
[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 = (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 (((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 (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
320                              (1000000*(unsigned int)(ch)), 1, bufp)==-1){
321             printf("Error invis-writing %s at byte %u million: %s\n", 
322                    (char*)bufp, (unsigned int)ch, ERR_NAME);
323           }
324           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
325                                  (1000000*(unsigned int)(ch)), 1, bufp)==-1){
326             printf("Error invis-reading at byte %u million: %s\n",
327                    (unsigned int)ch, ERR_NAME);
328           }
329           else if (((char*)bufp)[0]!=ch) {
330             printf("Error: wanted to read %c and instead got %s.\n",
331                    ch, (char*)bufp);
332           }
333           else if (Vflag) {
334             printf("Report: \"%c\" was written and \"%s\" was read "
335                    "at byte %d million.\n", ch, (char*)bufp, ch);
336           }
337
338 #ifdef __sgi
339           /* Try writing a character in the 2 gigabyte (2^31) range */
340           sprintf(bufp, "%c", ch);
341           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
342                              2147840000, 1, bufp)==-1){
343             printf("Error invis-writing %s at 2 gigabytes: %s\n", 
344                    (char*)bufp, ERR_NAME);
345           }
346           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
347                                  2147840000, 1, bufp)==-1){
348             printf("Error invis-reading at 2 gigabytes: %s\n",
349                    ERR_NAME);
350           }
351           else if (((char*)bufp)[0]!=ch) {
352             printf("Error: wanted to read %c and instead got %s.\n",
353                    ch, (char*)bufp);
354           }
355           else if (Vflag) {
356             printf("Report: \"%c\" was written and \"%s\" was read "
357                    "at 2147840000 bytes\n\t(a bit over 2 gigabytes).\n", 
358                    ch, (char*)bufp);
359           }
360 #endif
361
362           printf("\t(errno subtests beginning...)\n");
363           /**** WRITE tests ****/
364           /*---------------------------------------------------------*/
365           EXCLTEST("write", hanp, hlen, test_token, 
366                    dm_write_invis(sid, hanp, hlen, test_token,
367                                   0, 0, 13, "write test 1"))
368           /*---------------------------------------------------------*/
369             if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
370             fprintf(stderr, 
371                     "Cannot create a test handle (%s); skipping EBADF test\n",
372                     ERR_NAME);
373           }
374           else {
375             ((char *) test_vp)[hlen/2]++;
376             ERRTEST(EBADF,
377                     "write",
378                     dm_write_invis(sid, test_vp, hlen, DM_NO_TOKEN,
379                                    0, 0, 0, bufp))
380             ERRTEST(EBADF,
381                     "read",
382                     dm_read_invis(sid, test_vp, hlen, DM_NO_TOKEN,
383                                   0, 0, bufp))
384             dm_handle_free(test_vp, hlen);
385           }
386
387           /*---------------------------------------------------------*/
388           ERRTEST(EBADF,
389                   "write",
390                   dm_write_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
391                                  0, 0, 0, NULL))
392           /*---------------------------------------------------------*/
393           ERRTEST(EFAULT,
394                   "write",
395                   dm_write_invis(sid, NULL, hlen, DM_NO_TOKEN,
396                                  0, 0, 0, NULL))
397           /*---------------------------------------------------------*/
398 #if 0
399           PROBLEM: write_invis refuses to produce EINVAL for 
400           lengths that will not fit in a dm_size_t.
401
402           ERRTEST(EINVAL,
403                   "(bad length) write",
404                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
405                                  0, 4096, (long long)0xFFFFFFFFFFFFFFFFLL,
406                                  "write invalid length test"))
407 #endif
408           /*---------------------------------------------------------*/
409 #if 0
410           PROBLEM (somewhat fixed): A signal is sent, rather than EFBIG.
411           Presumably, this signal is needed to comply with...something.
412           If this is uncommented, the program will abort here, with the 
413           error message "exceeded file size limit". 
414
415           ERRTEST(EFBIG,
416                   "write",
417                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
418                                  0, (long long)0xFFFFFFFFFFLL, 
419                                  (long long)0xFFFFFFFFFFLL,
420                                  "foo foo foo"))
421 #endif
422           /*---------------------------------------------------------*/
423 #ifdef VERITAS_21
424           ERRTEST(EINVAL,
425                   "(bad offset) write",
426                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
427                                  0, (dm_size_t) ULONG_MAX, 5,
428                                  "write invalid offset test"))
429 #else
430 #ifndef linux
431           ERRTEST(EINVAL,
432                   "(bad offset) write",
433                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
434                                  0, (dm_size_t) ULONGLONG_MAX, 5,
435                                  "write invalid offset test"))
436 #endif
437 #endif
438
439           /*---------------------------------------------------------*/
440           ERRTEST(EINVAL,
441                   "(bad sid) write",
442                   dm_write_invis(-100, hanp, hlen, DM_NO_TOKEN,
443                                  0, 0, 26, "write invalid offset test"))
444
445
446           /**** READ tests ****/
447           /*---------------------------------------------------------*/
448           SHAREDTEST("read", hanp, hlen, test_token,
449                      dm_read_invis(sid, hanp, hlen, test_token, 
450                                    0, 13, bufp))
451           /*---------------------------------------------------------*/
452           ERRTEST(EBADF,
453                   "read",
454                   dm_read_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
455                                  0, 0, bufp))
456           /*---------------------------------------------------------*/
457           ERRTEST(EFAULT,
458                   "read",
459                   dm_read_invis(sid, NULL, hlen, DM_NO_TOKEN,
460                                  0, 0, bufp))
461           /*---------------------------------------------------------*/
462 #ifdef  VERITAS_21
463           ERRTEST(EINVAL,
464                   "(bad offset) read",
465                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
466                                 ULONG_MAX, 5, bufp));
467 #else
468 #ifndef linux
469           ERRTEST(EINVAL,
470                   "(bad offset) read",
471                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
472                                 ULONGLONG_MAX, 5, bufp));
473 #endif
474 #endif
475
476           /*---------------------------------------------------------*/
477           ERRTEST(EINVAL,
478                   "(bad sid) read",
479                   dm_read_invis(-100, hanp, hlen, DM_NO_TOKEN,
480                                 0, 5, bufp))
481           /*---------------------------------------------------------*/
482           printf("\t(errno subtests complete!)\n");
483         }
484         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
485                 dir_name);
486         sprintf(command, "rm %s \n", test_file); 
487         system(command);
488
489         printf("Invisible read/write tests complete.\n");
490
491         dm_handle_free(hanp, hlen);
492         exit(0);
493 }