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