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