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