• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
main(int argc,char * argv[])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 */
count_lines(cups_file_t * fp)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 */
random_tests(void)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 */
read_write_tests(int compression)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