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