]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testfile.c
6543e0a2f9e6ee5e016e1b984edc4ce128ba9b46
[thirdparty/cups.git] / cups / testfile.c
1 /*
2 * "$Id: testfile.c 11558 2014-02-06 18:33:34Z msweet $"
3 *
4 * File test program for CUPS.
5 *
6 * Copyright 2007-2014 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[1024]; /* Line from file */
209
210 if ((fp = cupsFileOpen(argv[1], "r")) == NULL)
211 {
212 perror(argv[1]);
213 status = 1;
214 }
215 else
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 }
228
229 return (status);
230 }
231
232
233 /*
234 * 'count_lines()' - Count the number of lines in a file.
235 */
236
237 static int /* O - Number of lines */
238 count_lines(cups_file_t *fp) /* I - File to read from */
239 {
240 int count; /* Number of lines */
241 char line[1024]; /* Line buffer */
242
243
244 for (count = 0; cupsFileGets(fp, line, sizeof(line)); count ++);
245
246 return (count);
247 }
248
249
250 /*
251 * 'random_tests()' - Do random access tests.
252 */
253
254 static int /* O - Status */
255 random_tests(void)
256 {
257 int status, /* Status of tests */
258 pass, /* Current pass */
259 count, /* Number of records read */
260 record, /* Current record */
261 num_records; /* Number of records */
262 off_t pos; /* Position in file */
263 ssize_t expected; /* Expected position in file */
264 cups_file_t *fp; /* File */
265 char buffer[512]; /* Data buffer */
266
267
268 /*
269 * Run 4 passes, each time appending to a data file and then reopening the
270 * file for reading to validate random records in the file.
271 */
272
273 for (status = 0, pass = 0; pass < 4; pass ++)
274 {
275 /*
276 * cupsFileOpen(append)
277 */
278
279 printf("\ncupsFileOpen(append %d): ", pass);
280
281 if ((fp = cupsFileOpen("testfile.dat", "a")) == NULL)
282 {
283 printf("FAIL (%s)\n", strerror(errno));
284 status ++;
285 break;
286 }
287 else
288 puts("PASS");
289
290 /*
291 * cupsFileTell()
292 */
293
294 expected = 256 * (ssize_t)sizeof(buffer) * pass;
295
296 fputs("cupsFileTell(): ", stdout);
297 if ((pos = cupsFileTell(fp)) != (off_t)expected)
298 {
299 printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
300 CUPS_LLCAST pos, CUPS_LLCAST expected);
301 status ++;
302 break;
303 }
304 else
305 puts("PASS");
306
307 /*
308 * cupsFileWrite()
309 */
310
311 fputs("cupsFileWrite(256 512-byte records): ", stdout);
312 for (record = 0; record < 256; record ++)
313 {
314 memset(buffer, record, sizeof(buffer));
315 if (cupsFileWrite(fp, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer))
316 break;
317 }
318
319 if (record < 256)
320 {
321 printf("FAIL (%d: %s)\n", record, strerror(errno));
322 status ++;
323 break;
324 }
325 else
326 puts("PASS");
327
328 /*
329 * cupsFileTell()
330 */
331
332 expected += 256 * (ssize_t)sizeof(buffer);
333
334 fputs("cupsFileTell(): ", stdout);
335 if ((pos = cupsFileTell(fp)) != (off_t)expected)
336 {
337 printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
338 CUPS_LLCAST pos, CUPS_LLCAST expected);
339 status ++;
340 break;
341 }
342 else
343 puts("PASS");
344
345 cupsFileClose(fp);
346
347 /*
348 * cupsFileOpen(read)
349 */
350
351 printf("\ncupsFileOpen(read %d): ", pass);
352
353 if ((fp = cupsFileOpen("testfile.dat", "r")) == NULL)
354 {
355 printf("FAIL (%s)\n", strerror(errno));
356 status ++;
357 break;
358 }
359 else
360 puts("PASS");
361
362 /*
363 * cupsFileSeek, cupsFileRead
364 */
365
366 fputs("cupsFileSeek(), cupsFileRead(): ", stdout);
367
368 for (num_records = (pass + 1) * 256, count = (pass + 1) * 256, record = ((int)CUPS_RAND() & 65535) % num_records;
369 count > 0;
370 count --, record = (record + ((int)CUPS_RAND() & 31) - 16 + num_records) % num_records)
371 {
372 /*
373 * The last record is always the first...
374 */
375
376 if (count == 1)
377 record = 0;
378
379 /*
380 * Try reading the data for the specified record, and validate the
381 * contents...
382 */
383
384 expected = (ssize_t)sizeof(buffer) * record;
385
386 if ((pos = cupsFileSeek(fp, expected)) != expected)
387 {
388 printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
389 CUPS_LLCAST pos, CUPS_LLCAST expected);
390 status ++;
391 break;
392 }
393 else
394 {
395 if (cupsFileRead(fp, buffer, sizeof(buffer)) != sizeof(buffer))
396 {
397 printf("FAIL (%s)\n", strerror(errno));
398 status ++;
399 break;
400 }
401 else if ((buffer[0] & 255) != (record & 255) ||
402 memcmp(buffer, buffer + 1, sizeof(buffer) - 1))
403 {
404 printf("FAIL (Bad Data - %d instead of %d)\n", buffer[0] & 255,
405 record & 255);
406 status ++;
407 break;
408 }
409 }
410 }
411
412 if (count == 0)
413 puts("PASS");
414
415 cupsFileClose(fp);
416 }
417
418 /*
419 * Remove the test file...
420 */
421
422 unlink("testfile.dat");
423
424 /*
425 * Return the test status...
426 */
427
428 return (status);
429 }
430
431
432 /*
433 * 'read_write_tests()' - Perform read/write tests.
434 */
435
436 static int /* O - Status */
437 read_write_tests(int compression) /* I - Use compression? */
438 {
439 int i; /* Looping var */
440 cups_file_t *fp; /* File */
441 int status; /* Exit status */
442 char line[1024], /* Line from file */
443 *value; /* Directive value from line */
444 int linenum; /* Line number */
445 unsigned char readbuf[8192], /* Read buffer */
446 writebuf[8192]; /* Write buffer */
447 int byte; /* Byte from file */
448 ssize_t bytes; /* Number of bytes read/written */
449 off_t length; /* Length of file */
450 static const char *partial_line = "partial line";
451 /* Partial line */
452
453
454 /*
455 * No errors so far...
456 */
457
458 status = 0;
459
460 /*
461 * Initialize the write buffer with random data...
462 */
463
464 CUPS_SRAND((unsigned)time(NULL));
465
466 for (i = 0; i < (int)sizeof(writebuf); i ++)
467 writebuf[i] = (unsigned char)CUPS_RAND();
468
469 /*
470 * cupsFileOpen(write)
471 */
472
473 printf("cupsFileOpen(write%s): ", compression ? " compressed" : "");
474
475 fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat",
476 compression ? "w9" : "w");
477 if (fp)
478 {
479 puts("PASS");
480
481 /*
482 * cupsFileCompression()
483 */
484
485 fputs("cupsFileCompression(): ", stdout);
486
487 if (cupsFileCompression(fp) == compression)
488 puts("PASS");
489 else
490 {
491 printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
492 compression);
493 status ++;
494 }
495
496 /*
497 * cupsFilePuts()
498 */
499
500 fputs("cupsFilePuts(): ", stdout);
501
502 if (cupsFilePuts(fp, "# Hello, World\n") > 0)
503 puts("PASS");
504 else
505 {
506 printf("FAIL (%s)\n", strerror(errno));
507 status ++;
508 }
509
510 /*
511 * cupsFilePrintf()
512 */
513
514 fputs("cupsFilePrintf(): ", stdout);
515
516 for (i = 0; i < 1000; i ++)
517 if (cupsFilePrintf(fp, "TestLine %03d\n", i) < 0)
518 break;
519
520 if (i >= 1000)
521 puts("PASS");
522 else
523 {
524 printf("FAIL (%s)\n", strerror(errno));
525 status ++;
526 }
527
528 /*
529 * cupsFilePutChar()
530 */
531
532 fputs("cupsFilePutChar(): ", stdout);
533
534 for (i = 0; i < 256; i ++)
535 if (cupsFilePutChar(fp, i) < 0)
536 break;
537
538 if (i >= 256)
539 puts("PASS");
540 else
541 {
542 printf("FAIL (%s)\n", strerror(errno));
543 status ++;
544 }
545
546 /*
547 * cupsFileWrite()
548 */
549
550 fputs("cupsFileWrite(): ", stdout);
551
552 for (i = 0; i < 10000; i ++)
553 if (cupsFileWrite(fp, (char *)writebuf, sizeof(writebuf)) < 0)
554 break;
555
556 if (i >= 10000)
557 puts("PASS");
558 else
559 {
560 printf("FAIL (%s)\n", strerror(errno));
561 status ++;
562 }
563
564 /*
565 * cupsFilePuts() with partial line...
566 */
567
568 fputs("cupsFilePuts(\"partial line\"): ", stdout);
569
570 if (cupsFilePuts(fp, partial_line) > 0)
571 puts("PASS");
572 else
573 {
574 printf("FAIL (%s)\n", strerror(errno));
575 status ++;
576 }
577
578 /*
579 * cupsFileTell()
580 */
581
582 fputs("cupsFileTell(): ", stdout);
583
584 if ((length = cupsFileTell(fp)) == 81933283)
585 puts("PASS");
586 else
587 {
588 printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
589 status ++;
590 }
591
592 /*
593 * cupsFileClose()
594 */
595
596 fputs("cupsFileClose(): ", stdout);
597
598 if (!cupsFileClose(fp))
599 puts("PASS");
600 else
601 {
602 printf("FAIL (%s)\n", strerror(errno));
603 status ++;
604 }
605 }
606 else
607 {
608 printf("FAIL (%s)\n", strerror(errno));
609 status ++;
610 }
611
612 /*
613 * cupsFileOpen(read)
614 */
615
616 fputs("\ncupsFileOpen(read): ", stdout);
617
618 fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat", "r");
619 if (fp)
620 {
621 puts("PASS");
622
623 /*
624 * cupsFileGets()
625 */
626
627 fputs("cupsFileGets(): ", stdout);
628
629 if (cupsFileGets(fp, line, sizeof(line)))
630 {
631 if (line[0] == '#')
632 puts("PASS");
633 else
634 {
635 printf("FAIL (Got line \"%s\", expected comment line)\n", line);
636 status ++;
637 }
638 }
639 else
640 {
641 printf("FAIL (%s)\n", strerror(errno));
642 status ++;
643 }
644
645 /*
646 * cupsFileCompression()
647 */
648
649 fputs("cupsFileCompression(): ", stdout);
650
651 if (cupsFileCompression(fp) == compression)
652 puts("PASS");
653 else
654 {
655 printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
656 compression);
657 status ++;
658 }
659
660 /*
661 * cupsFileGetConf()
662 */
663
664 linenum = 1;
665
666 fputs("cupsFileGetConf(): ", stdout);
667
668 for (i = 0, value = NULL; i < 1000; i ++)
669 if (!cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
670 break;
671 else if (_cups_strcasecmp(line, "TestLine") || !value || atoi(value) != i ||
672 linenum != (i + 2))
673 break;
674
675 if (i >= 1000)
676 puts("PASS");
677 else if (line[0])
678 {
679 printf("FAIL (Line %d, directive \"%s\", value \"%s\")\n", linenum,
680 line, value ? value : "(null)");
681 status ++;
682 }
683 else
684 {
685 printf("FAIL (%s)\n", strerror(errno));
686 status ++;
687 }
688
689 /*
690 * cupsFileGetChar()
691 */
692
693 fputs("cupsFileGetChar(): ", stdout);
694
695 for (i = 0, byte = 0; i < 256; i ++)
696 if ((byte = cupsFileGetChar(fp)) != i)
697 break;
698
699 if (i >= 256)
700 puts("PASS");
701 else if (byte >= 0)
702 {
703 printf("FAIL (Got %d, expected %d)\n", byte, i);
704 status ++;
705 }
706 else
707 {
708 printf("FAIL (%s)\n", strerror(errno));
709 status ++;
710 }
711
712 /*
713 * cupsFileRead()
714 */
715
716 fputs("cupsFileRead(): ", stdout);
717
718 for (i = 0, bytes = 0; i < 10000; i ++)
719 if ((bytes = cupsFileRead(fp, (char *)readbuf, sizeof(readbuf))) < 0)
720 break;
721 else if (memcmp(readbuf, writebuf, sizeof(readbuf)))
722 break;
723
724 if (i >= 10000)
725 puts("PASS");
726 else if (bytes > 0)
727 {
728 printf("FAIL (Pass %d, ", i);
729
730 for (i = 0; i < (int)sizeof(readbuf); i ++)
731 if (readbuf[i] != writebuf[i])
732 break;
733
734 printf("match failed at offset %d - got %02X, expected %02X)\n",
735 i, readbuf[i], writebuf[i]);
736 }
737 else
738 {
739 printf("FAIL (%s)\n", strerror(errno));
740 status ++;
741 }
742
743 /*
744 * cupsFileGetChar() with partial line...
745 */
746
747 fputs("cupsFileGetChar(partial line): ", stdout);
748
749 for (i = 0; i < (int)strlen(partial_line); i ++)
750 if ((byte = cupsFileGetChar(fp)) < 0)
751 break;
752 else if (byte != partial_line[i])
753 break;
754
755 if (!partial_line[i])
756 puts("PASS");
757 else
758 {
759 printf("FAIL (got '%c', expected '%c')\n", byte, partial_line[i]);
760 status ++;
761 }
762
763 /*
764 * cupsFileTell()
765 */
766
767 fputs("cupsFileTell(): ", stdout);
768
769 if ((length = cupsFileTell(fp)) == 81933283)
770 puts("PASS");
771 else
772 {
773 printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
774 status ++;
775 }
776
777 /*
778 * cupsFileClose()
779 */
780
781 fputs("cupsFileClose(): ", stdout);
782
783 if (!cupsFileClose(fp))
784 puts("PASS");
785 else
786 {
787 printf("FAIL (%s)\n", strerror(errno));
788 status ++;
789 }
790 }
791 else
792 {
793 printf("FAIL (%s)\n", strerror(errno));
794 status ++;
795 }
796
797 /*
798 * Remove the test file...
799 */
800
801 unlink(compression ? "testfile.dat.gz" : "testfile.dat");
802
803 /*
804 * Return the test status...
805 */
806
807 return (status);
808 }
809
810
811 /*
812 * End of "$Id: testfile.c 11558 2014-02-06 18:33:34Z msweet $".
813 */