1/* 2 * "$Id: testfile.c 11560 2014-02-06 20:10:19Z 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 42static int count_lines(cups_file_t *fp); 43static int random_tests(void); 44static int read_write_tests(int compression); 45 46 47/* 48 * 'main()' - Main entry. 49 */ 50 51int /* O - Exit status */ 52main(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 237static int /* O - Number of lines */ 238count_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 254static int /* O - Status */ 255random_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 436static int /* O - Status */ 437read_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 11560 2014-02-06 20:10:19Z msweet $". 813 */ 814