Revert manifest to default one
[external/cups.git] / cups / testfile.c
1 /*
2  * "$Id: testfile.c 9793 2011-05-20 03:49:49Z mike $"
3  *
4  *   File test program for CUPS.
5  *
6  *   Copyright 2007-2011 by Apple Inc.
7  *   Copyright 1997-2007 by Easy Software Products.
8  *
9  *   These coded instructions, statements, and computer programs are the
10  *   property of Apple Inc. and are protected by Federal copyright
11  *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
12  *   which should have been included with this file.  If this file is
13  *   file is missing or damaged, see the license at "http://www.cups.org/".
14  *
15  *   This file is subject to the Apple OS-Developed Software exception.
16  *
17  * Contents:
18  *
19  *   main()             - Main entry.
20  *   count_lines()      - Count the number of lines in a file.
21  *   random_tests()     - Do random access tests.
22  *   read_write_tests() - Perform read/write tests.
23  */
24
25 /*
26  * Include necessary headers...
27  */
28
29 #include "string-private.h"
30 #include "debug-private.h"
31 #include "file.h"
32 #include <stdlib.h>
33 #include <time.h>
34 #ifdef HAVE_LIBZ
35 #  include <zlib.h>
36 #endif /* HAVE_LIBZ */
37 #ifdef WIN32
38 #  include <io.h>
39 #else
40 #  include <unistd.h>
41 #endif /* WIN32 */
42 #include <fcntl.h>
43
44
45 /*
46  * Local functions...
47  */
48
49 static int      count_lines(cups_file_t *fp);
50 static int      random_tests(void);
51 static int      read_write_tests(int compression);
52
53
54 /*
55  * 'main()' - Main entry.
56  */
57
58 int                                     /* O - Exit status */
59 main(int  argc,                         /* I - Number of command-line arguments */
60      char *argv[])                      /* I - Command-line arguments */
61 {
62   int           status;                 /* Exit status */
63   char          filename[1024];         /* Filename buffer */
64   cups_file_t   *fp;                    /* File pointer */
65 #ifndef WIN32
66   int           fds[2];                 /* Open file descriptors */
67   cups_file_t   *fdfile;                /* File opened with cupsFileOpenFd() */
68 #endif /* !WIN32 */
69   int           count;                  /* Number of lines in file */
70
71
72   if (argc == 1)
73   {
74    /*
75     * Do uncompressed file tests...
76     */
77
78     status = read_write_tests(0);
79
80 #ifdef HAVE_LIBZ
81    /*
82     * Do compressed file tests...
83     */
84
85     putchar('\n');
86
87     status += read_write_tests(1);
88 #endif /* HAVE_LIBZ */
89
90    /*
91     * Do uncompressed random I/O tests...
92     */
93
94     status += random_tests();
95
96 #ifndef WIN32
97    /*
98     * Test fdopen and close without reading...
99     */
100
101     pipe(fds);
102     close(fds[1]);
103
104     fputs("\ncupsFileOpenFd(fd, \"r\"): ", stdout);
105     fflush(stdout);
106
107     if ((fdfile = cupsFileOpenFd(fds[0], "r")) == NULL)
108     {
109       puts("FAIL");
110       status ++;
111     }
112     else
113     {
114      /*
115       * Able to open file, now close without reading.  If we don't return
116       * before the alarm fires, that is a failure and we will crash on the
117       * alarm signal...
118       */
119
120       puts("PASS");
121       fputs("cupsFileClose(no read): ", stdout);
122       fflush(stdout);
123
124       alarm(5);
125       cupsFileClose(fdfile);
126       alarm(0);
127
128       puts("PASS");
129     }
130 #endif /* !WIN32 */
131
132    /*
133     * Count lines in psglyphs, rewind, then count again.
134     */
135
136     fputs("\ncupsFileOpen(\"../data/psglyphs\", \"r\"): ", stdout);
137
138     if ((fp = cupsFileOpen("../data/psglyphs", "r")) == NULL)
139     {
140       puts("FAIL");
141       status ++;
142     }
143     else
144     {
145       puts("PASS");
146       fputs("cupsFileGets: ", stdout);
147
148       if ((count = count_lines(fp)) != 1051)
149       {
150         printf("FAIL (got %d lines, expected 1051)\n", count);
151         status ++;
152       }
153       else
154       {
155         puts("PASS");
156         fputs("cupsFileRewind: ", stdout);
157
158         if (cupsFileRewind(fp) != 0)
159         {
160           puts("FAIL");
161           status ++;
162         }
163         else
164         {
165           puts("PASS");
166           fputs("cupsFileGets: ", stdout);
167
168           if ((count = count_lines(fp)) != 1051)
169           {
170             printf("FAIL (got %d lines, expected 1051)\n", count);
171             status ++;
172           }
173           else
174             puts("PASS");
175         }
176       }
177
178       cupsFileClose(fp);
179     }
180
181    /*
182     * Test path functions...
183     */
184
185     fputs("\ncupsFileFind: ", stdout);
186 #ifdef WIN32
187     if (cupsFileFind("notepad.exe", "C:/WINDOWS", 1, filename, sizeof(filename)) &&
188         cupsFileFind("notepad.exe", "C:/WINDOWS;C:/WINDOWS/SYSTEM32", 1, filename, sizeof(filename)))
189 #else
190     if (cupsFileFind("cat", "/bin", 1, filename, sizeof(filename)) &&
191         cupsFileFind("cat", "/bin:/usr/bin", 1, filename, sizeof(filename)))
192 #endif /* WIN32 */
193       printf("PASS (%s)\n", filename);
194     else
195     {
196       puts("FAIL");
197       status ++;
198     }
199
200    /*
201     * Summarize the results and return...
202     */
203
204     if (!status)
205       puts("\nALL TESTS PASSED!");
206     else
207       printf("\n%d TEST(S) FAILED!\n", status);
208   }
209   else
210   {
211    /*
212     * Cat the filename on the command-line...
213     */
214
215     char        line[1024];             /* Line from file */
216
217     if ((fp = cupsFileOpen(argv[1], "r")) == NULL)
218     {
219       perror(argv[1]);
220       status = 1;
221     }
222     else
223     {
224       status = 0;
225
226       while (cupsFileGets(fp, line, sizeof(line)))
227         puts(line);
228
229       if (!cupsFileEOF(fp))
230         perror(argv[1]);
231
232       cupsFileClose(fp);
233     }
234   }
235
236   return (status);
237 }
238
239
240 /*
241  * 'count_lines()' - Count the number of lines in a file.
242  */
243
244 static int                              /* O - Number of lines */
245 count_lines(cups_file_t *fp)            /* I - File to read from */
246 {
247   int   count;                          /* Number of lines */
248   char  line[1024];                     /* Line buffer */
249
250
251   for (count = 0; cupsFileGets(fp, line, sizeof(line)); count ++);
252
253   return (count);
254 }
255
256
257 /*
258  * 'random_tests()' - Do random access tests.
259  */
260
261 static int                              /* O - Status */
262 random_tests(void)
263 {
264   int           status,                 /* Status of tests */
265                 pass,                   /* Current pass */
266                 count,                  /* Number of records read */
267                 record,                 /* Current record */
268                 num_records;            /* Number of records */
269   ssize_t       pos,                    /* Position in file */
270                 expected;               /* Expected position in file */
271   cups_file_t   *fp;                    /* File */
272   char          buffer[512];            /* Data buffer */
273
274
275  /*
276   * Run 4 passes, each time appending to a data file and then reopening the
277   * file for reading to validate random records in the file.
278   */
279
280   for (status = 0, pass = 0; pass < 4; pass ++)
281   {
282    /*
283     * cupsFileOpen(append)
284     */
285
286     printf("\ncupsFileOpen(append %d): ", pass);
287
288     if ((fp = cupsFileOpen("testfile.dat", "a")) == NULL)
289     {
290       printf("FAIL (%s)\n", strerror(errno));
291       status ++;
292       break;
293     }
294     else
295       puts("PASS");
296
297    /*
298     * cupsFileTell()
299     */
300
301     expected = 256 * sizeof(buffer) * pass;
302
303     fputs("cupsFileTell(): ", stdout);
304     if ((pos = cupsFileTell(fp)) != expected)
305     {
306       printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
307              CUPS_LLCAST pos, CUPS_LLCAST expected);
308       status ++;
309       break;
310     }
311     else
312       puts("PASS");
313
314    /*
315     * cupsFileWrite()
316     */
317
318     fputs("cupsFileWrite(256 512-byte records): ", stdout);
319     for (record = 0; record < 256; record ++)
320     {
321       memset(buffer, record, sizeof(buffer));
322       if (cupsFileWrite(fp, buffer, sizeof(buffer)) < sizeof(buffer))
323         break;
324     }
325
326     if (record < 256)
327     {
328       printf("FAIL (%d: %s)\n", record, strerror(errno));
329       status ++;
330       break;
331     }
332     else
333       puts("PASS");
334
335    /*
336     * cupsFileTell()
337     */
338
339     expected += 256 * sizeof(buffer);
340
341     fputs("cupsFileTell(): ", stdout);
342     if ((pos = cupsFileTell(fp)) != expected)
343     {
344       printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
345              CUPS_LLCAST pos, CUPS_LLCAST expected);
346       status ++;
347       break;
348     }
349     else
350       puts("PASS");
351
352     cupsFileClose(fp);
353
354    /*
355     * cupsFileOpen(read)
356     */
357
358     printf("\ncupsFileOpen(read %d): ", pass);
359
360     if ((fp = cupsFileOpen("testfile.dat", "r")) == NULL)
361     {
362       printf("FAIL (%s)\n", strerror(errno));
363       status ++;
364       break;
365     }
366     else
367       puts("PASS");
368
369    /*
370     * cupsFileSeek, cupsFileRead
371     */
372
373     fputs("cupsFileSeek(), cupsFileRead(): ", stdout);
374
375     for (num_records = (pass + 1) * 256, count = (pass + 1) * 256,
376              record = CUPS_RAND() % num_records;
377          count > 0;
378          count --, record = (record + (CUPS_RAND() & 31) - 16 + num_records) %
379                             num_records)
380     {
381      /*
382       * The last record is always the first...
383       */
384
385       if (count == 1)
386         record = 0;
387
388      /*
389       * Try reading the data for the specified record, and validate the
390       * contents...
391       */
392
393       expected = sizeof(buffer) * record;
394
395       if ((pos = cupsFileSeek(fp, expected)) != expected)
396       {
397         printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
398                CUPS_LLCAST pos, CUPS_LLCAST expected);
399         status ++;
400         break;
401       }
402       else
403       {
404         if (cupsFileRead(fp, buffer, sizeof(buffer)) != sizeof(buffer))
405         {
406           printf("FAIL (%s)\n", strerror(errno));
407           status ++;
408           break;
409         }
410         else if ((buffer[0] & 255) != (record & 255) ||
411                  memcmp(buffer, buffer + 1, sizeof(buffer) - 1))
412         {
413           printf("FAIL (Bad Data - %d instead of %d)\n", buffer[0] & 255,
414                  record & 255);
415           status ++;
416           break;
417         }
418       }
419     }
420
421     if (count == 0)
422       puts("PASS");
423
424     cupsFileClose(fp);
425   }
426
427  /*
428   * Remove the test file...
429   */
430
431   unlink("testfile.dat");
432
433  /*
434   * Return the test status...
435   */
436
437   return (status);
438 }
439
440
441 /*
442  * 'read_write_tests()' - Perform read/write tests.
443  */
444
445 static int                              /* O - Status */
446 read_write_tests(int compression)       /* I - Use compression? */
447 {
448   int           i;                      /* Looping var */
449   cups_file_t   *fp;                    /* File */
450   int           status;                 /* Exit status */
451   char          line[1024],             /* Line from file */
452                 *value;                 /* Directive value from line */
453   int           linenum;                /* Line number */
454   unsigned char readbuf[8192],          /* Read buffer */
455                 writebuf[8192];         /* Write buffer */
456   int           byte;                   /* Byte from file */
457   off_t         length;                 /* Length of file */
458   static const char *partial_line = "partial line";
459                                         /* Partial line */
460
461
462  /*
463   * No errors so far...
464   */
465
466   status = 0;
467
468  /*
469   * Initialize the write buffer with random data...
470   */
471
472   CUPS_SRAND((unsigned)time(NULL));
473
474   for (i = 0; i < (int)sizeof(writebuf); i ++)
475     writebuf[i] = CUPS_RAND();
476
477  /*
478   * cupsFileOpen(write)
479   */
480
481   printf("cupsFileOpen(write%s): ", compression ? " compressed" : "");
482
483   fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat",
484                     compression ? "w9" : "w");
485   if (fp)
486   {
487     puts("PASS");
488
489    /*
490     * cupsFileCompression()
491     */
492
493     fputs("cupsFileCompression(): ", stdout);
494
495     if (cupsFileCompression(fp) == compression)
496       puts("PASS");
497     else
498     {
499       printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
500              compression);
501       status ++;
502     }
503
504    /*
505     * cupsFilePuts()
506     */
507
508     fputs("cupsFilePuts(): ", stdout);
509
510     if (cupsFilePuts(fp, "# Hello, World\n") > 0)
511       puts("PASS");
512     else
513     {
514       printf("FAIL (%s)\n", strerror(errno));
515       status ++;
516     }
517
518    /*
519     * cupsFilePrintf()
520     */
521
522     fputs("cupsFilePrintf(): ", stdout);
523
524     for (i = 0; i < 1000; i ++)
525       if (cupsFilePrintf(fp, "TestLine %03d\n", i) < 0)
526         break;
527
528     if (i >= 1000)
529       puts("PASS");
530     else
531     {
532       printf("FAIL (%s)\n", strerror(errno));
533       status ++;
534     }
535
536    /*
537     * cupsFilePutChar()
538     */
539
540     fputs("cupsFilePutChar(): ", stdout);
541
542     for (i = 0; i < 256; i ++)
543       if (cupsFilePutChar(fp, i) < 0)
544         break;
545
546     if (i >= 256)
547       puts("PASS");
548     else
549     {
550       printf("FAIL (%s)\n", strerror(errno));
551       status ++;
552     }
553
554    /*
555     * cupsFileWrite()
556     */
557
558     fputs("cupsFileWrite(): ", stdout);
559
560     for (i = 0; i < 10000; i ++)
561       if (cupsFileWrite(fp, (char *)writebuf, sizeof(writebuf)) < 0)
562         break;
563
564     if (i >= 10000)
565       puts("PASS");
566     else
567     {
568       printf("FAIL (%s)\n", strerror(errno));
569       status ++;
570     }
571
572    /*
573     * cupsFilePuts() with partial line...
574     */
575
576     fputs("cupsFilePuts(\"partial line\"): ", stdout);
577
578     if (cupsFilePuts(fp, partial_line) > 0)
579       puts("PASS");
580     else
581     {
582       printf("FAIL (%s)\n", strerror(errno));
583       status ++;
584     }
585
586    /*
587     * cupsFileTell()
588     */
589
590     fputs("cupsFileTell(): ", stdout);
591
592     if ((length = cupsFileTell(fp)) == 81933283)
593       puts("PASS");
594     else
595     {
596       printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
597       status ++;
598     }
599
600    /*
601     * cupsFileClose()
602     */
603
604     fputs("cupsFileClose(): ", stdout);
605
606     if (!cupsFileClose(fp))
607       puts("PASS");
608     else
609     {
610       printf("FAIL (%s)\n", strerror(errno));
611       status ++;
612     }
613   }
614   else
615   {
616     printf("FAIL (%s)\n", strerror(errno));
617     status ++;
618   }
619
620  /*
621   * cupsFileOpen(read)
622   */
623
624   fputs("\ncupsFileOpen(read): ", stdout);
625
626   fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat", "r");
627   if (fp)
628   {
629     puts("PASS");
630
631    /*
632     * cupsFileGets()
633     */
634
635     fputs("cupsFileGets(): ", stdout);
636
637     if (cupsFileGets(fp, line, sizeof(line)))
638     {
639       if (line[0] == '#')
640         puts("PASS");
641       else
642       {
643         printf("FAIL (Got line \"%s\", expected comment line)\n", line);
644         status ++;
645       }
646     }
647     else
648     {
649       printf("FAIL (%s)\n", strerror(errno));
650       status ++;
651     }
652
653    /*
654     * cupsFileCompression()
655     */
656
657     fputs("cupsFileCompression(): ", stdout);
658
659     if (cupsFileCompression(fp) == compression)
660       puts("PASS");
661     else
662     {
663       printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
664              compression);
665       status ++;
666     }
667
668    /*
669     * cupsFileGetConf()
670     */
671
672     linenum = 1;
673
674     fputs("cupsFileGetConf(): ", stdout);
675
676     for (i = 0; i < 1000; i ++)
677       if (!cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
678         break;
679       else if (_cups_strcasecmp(line, "TestLine") || !value || atoi(value) != i ||
680                linenum != (i + 2))
681         break;
682
683     if (i >= 1000)
684       puts("PASS");
685     else if (line[0])
686     {
687       printf("FAIL (Line %d, directive \"%s\", value \"%s\")\n", linenum,
688              line, value ? value : "(null)");
689       status ++;
690     }
691     else
692     {
693       printf("FAIL (%s)\n", strerror(errno));
694       status ++;
695     }
696
697    /*
698     * cupsFileGetChar()
699     */
700
701     fputs("cupsFileGetChar(): ", stdout);
702
703     for (i = 0; i < 256; i ++)
704       if ((byte = cupsFileGetChar(fp)) != i)
705         break;
706
707     if (i >= 256)
708       puts("PASS");
709     else if (byte >= 0)
710     {
711       printf("FAIL (Got %d, expected %d)\n", byte, i);
712       status ++;
713     }
714     else
715     {
716       printf("FAIL (%s)\n", strerror(errno));
717       status ++;
718     }
719
720    /*
721     * cupsFileRead()
722     */
723
724     fputs("cupsFileRead(): ", stdout);
725
726     for (i = 0; i < 10000; i ++)
727       if ((byte = cupsFileRead(fp, (char *)readbuf, sizeof(readbuf))) < 0)
728         break;
729       else if (memcmp(readbuf, writebuf, sizeof(readbuf)))
730         break;
731
732     if (i >= 10000)
733       puts("PASS");
734     else if (byte > 0)
735     {
736       printf("FAIL (Pass %d, ", i);
737
738       for (i = 0; i < (int)sizeof(readbuf); i ++)
739         if (readbuf[i] != writebuf[i])
740           break;
741
742       printf("match failed at offset %d - got %02X, expected %02X)\n",
743              i, readbuf[i], writebuf[i]);
744     }
745     else
746     {
747       printf("FAIL (%s)\n", strerror(errno));
748       status ++;
749     }
750
751    /*
752     * cupsFileGetChar() with partial line...
753     */
754
755     fputs("cupsFileGetChar(partial line): ", stdout);
756
757     for (i = 0; i < (int)strlen(partial_line); i ++)
758       if ((byte = cupsFileGetChar(fp)) < 0)
759         break;
760       else if (byte != partial_line[i])
761         break;
762
763     if (!partial_line[i])
764       puts("PASS");
765     else
766     {
767       printf("FAIL (got '%c', expected '%c')\n", byte, partial_line[i]);
768       status ++;
769     }
770
771    /*
772     * cupsFileTell()
773     */
774
775     fputs("cupsFileTell(): ", stdout);
776
777     if ((length = cupsFileTell(fp)) == 81933283)
778       puts("PASS");
779     else
780     {
781       printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
782       status ++;
783     }
784
785    /*
786     * cupsFileClose()
787     */
788
789     fputs("cupsFileClose(): ", stdout);
790
791     if (!cupsFileClose(fp))
792       puts("PASS");
793     else
794     {
795       printf("FAIL (%s)\n", strerror(errno));
796       status ++;
797     }
798   }
799   else
800   {
801     printf("FAIL (%s)\n", strerror(errno));
802     status ++;
803   }
804
805  /*
806   * Remove the test file...
807   */
808
809   unlink(compression ? "testfile.dat.gz" : "testfile.dat");
810
811  /*
812   * Return the test status...
813   */
814
815   return (status);
816 }
817
818
819 /*
820  * End of "$Id: testfile.c 9793 2011-05-20 03:49:49Z mike $".
821  */