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