]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testfile.c
dae50fa23847acec10d6d71b6ec5f17494efca48
[thirdparty/cups.git] / cups / testfile.c
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 * file is 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 }