You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

815 lines
16 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* File test program for CUPS.
*
* Copyright © 2007-2018 by Apple Inc.
* Copyright © 1997-2007 by Easy Software Products.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
* information.
*/
/*
* Include necessary headers...
*/
#include "string-private.h"
#include "debug-private.h"
#include "file.h"
#include <stdlib.h>
#include <time.h>
#ifdef _WIN32
# include <io.h>
#else
# include <unistd.h>
#endif /* _WIN32 */
#include <fcntl.h>
/*
* Local functions...
*/
static int count_lines(cups_file_t *fp);
static int random_tests(void);
static int read_write_tests(int compression);
/*
* 'main()' - Main entry.
*/
int /* O - Exit status */
main(int argc, /* I - Number of command-line arguments */
char *argv[]) /* I - Command-line arguments */
{
int status; /* Exit status */
char filename[1024]; /* Filename buffer */
cups_file_t *fp; /* File pointer */
#ifndef _WIN32
int fds[2]; /* Open file descriptors */
cups_file_t *fdfile; /* File opened with cupsFileOpenFd() */
#endif /* !_WIN32 */
int count; /* Number of lines in file */
if (argc == 1)
{
/*
* Do uncompressed file tests...
*/
status = read_write_tests(0);
#ifdef HAVE_LIBZ
/*
* Do compressed file tests...
*/
putchar('\n');
status += read_write_tests(1);
#endif /* HAVE_LIBZ */
/*
* Do uncompressed random I/O tests...
*/
status += random_tests();
#ifndef _WIN32
/*
* Test fdopen and close without reading...
*/
pipe(fds);
close(fds[1]);
fputs("\ncupsFileOpenFd(fd, \"r\"): ", stdout);
fflush(stdout);
if ((fdfile = cupsFileOpenFd(fds[0], "r")) == NULL)
{
puts("FAIL");
status ++;
}
else
{
/*
* Able to open file, now close without reading. If we don't return
* before the alarm fires, that is a failure and we will crash on the
* alarm signal...
*/
puts("PASS");
fputs("cupsFileClose(no read): ", stdout);
fflush(stdout);
alarm(5);
cupsFileClose(fdfile);
alarm(0);
puts("PASS");
}
#endif /* !_WIN32 */
/*
* Count lines in test file, rewind, then count again.
*/
fputs("\ncupsFileOpen(\"testfile.txt\", \"r\"): ", stdout);
if ((fp = cupsFileOpen("testfile.txt", "r")) == NULL)
{
puts("FAIL");
status ++;
}
else
{
puts("PASS");
fputs("cupsFileGets: ", stdout);
if ((count = count_lines(fp)) != 477)
{
printf("FAIL (got %d lines, expected 477)\n", count);
status ++;
}
else
{
puts("PASS");
fputs("cupsFileRewind: ", stdout);
if (cupsFileRewind(fp) != 0)
{
puts("FAIL");
status ++;
}
else
{
puts("PASS");
fputs("cupsFileGets: ", stdout);
if ((count = count_lines(fp)) != 477)
{
printf("FAIL (got %d lines, expected 477)\n", count);
status ++;
}
else
puts("PASS");
}
}
cupsFileClose(fp);
}
/*
* Test path functions...
*/
fputs("\ncupsFileFind: ", stdout);
#ifdef _WIN32
if (cupsFileFind("notepad.exe", "C:/WINDOWS", 1, filename, sizeof(filename)) &&
cupsFileFind("notepad.exe", "C:/WINDOWS;C:/WINDOWS/SYSTEM32", 1, filename, sizeof(filename)))
#else
if (cupsFileFind("cat", "/bin", 1, filename, sizeof(filename)) &&
cupsFileFind("cat", "/bin:/usr/bin", 1, filename, sizeof(filename)))
#endif /* _WIN32 */
printf("PASS (%s)\n", filename);
else
{
puts("FAIL");
status ++;
}
/*
* Summarize the results and return...
*/
if (!status)
puts("\nALL TESTS PASSED!");
else
printf("\n%d TEST(S) FAILED!\n", status);
}
else
{
/*
* Cat the filename on the command-line...
*/
char line[8192]; /* Line from file */
if ((fp = cupsFileOpen(argv[1], "r")) == NULL)
{
perror(argv[1]);
status = 1;
}
else if (argc == 2)
{
status = 0;
while (cupsFileGets(fp, line, sizeof(line)))
puts(line);
if (!cupsFileEOF(fp))
perror(argv[1]);
cupsFileClose(fp);
}
else
{
status = 0;
ssize_t bytes;
while ((bytes = cupsFileRead(fp, line, sizeof(line))) > 0)
printf("%s: %d bytes\n", argv[1], (int)bytes);
if (cupsFileEOF(fp))
printf("%s: EOF\n", argv[1]);
else
perror(argv[1]);
cupsFileClose(fp);
}
}
return (status);
}
/*
* 'count_lines()' - Count the number of lines in a file.
*/
static int /* O - Number of lines */
count_lines(cups_file_t *fp) /* I - File to read from */
{
int count; /* Number of lines */
char line[1024]; /* Line buffer */
for (count = 0; cupsFileGets(fp, line, sizeof(line)); count ++);
return (count);
}
/*
* 'random_tests()' - Do random access tests.
*/
static int /* O - Status */
random_tests(void)
{
int status, /* Status of tests */
pass, /* Current pass */
count, /* Number of records read */
record, /* Current record */
num_records; /* Number of records */
off_t pos; /* Position in file */
ssize_t expected; /* Expected position in file */
cups_file_t *fp; /* File */
char buffer[512]; /* Data buffer */
/*
* Run 4 passes, each time appending to a data file and then reopening the
* file for reading to validate random records in the file.
*/
for (status = 0, pass = 0; pass < 4; pass ++)
{
/*
* cupsFileOpen(append)
*/
printf("\ncupsFileOpen(append %d): ", pass);
if ((fp = cupsFileOpen("testfile.dat", "a")) == NULL)
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
break;
}
else
puts("PASS");
/*
* cupsFileTell()
*/
expected = 256 * (ssize_t)sizeof(buffer) * pass;
fputs("cupsFileTell(): ", stdout);
if ((pos = cupsFileTell(fp)) != (off_t)expected)
{
printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
CUPS_LLCAST pos, CUPS_LLCAST expected);
status ++;
break;
}
else
puts("PASS");
/*
* cupsFileWrite()
*/
fputs("cupsFileWrite(256 512-byte records): ", stdout);
for (record = 0; record < 256; record ++)
{
memset(buffer, record, sizeof(buffer));
if (cupsFileWrite(fp, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer))
break;
}
if (record < 256)
{
printf("FAIL (%d: %s)\n", record, strerror(errno));
status ++;
break;
}
else
puts("PASS");
/*
* cupsFileTell()
*/
expected += 256 * (ssize_t)sizeof(buffer);
fputs("cupsFileTell(): ", stdout);
if ((pos = cupsFileTell(fp)) != (off_t)expected)
{
printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
CUPS_LLCAST pos, CUPS_LLCAST expected);
status ++;
break;
}
else
puts("PASS");
cupsFileClose(fp);
/*
* cupsFileOpen(read)
*/
printf("\ncupsFileOpen(read %d): ", pass);
if ((fp = cupsFileOpen("testfile.dat", "r")) == NULL)
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
break;
}
else
puts("PASS");
/*
* cupsFileSeek, cupsFileRead
*/
fputs("cupsFileSeek(), cupsFileRead(): ", stdout);
for (num_records = (pass + 1) * 256, count = (pass + 1) * 256, record = ((int)CUPS_RAND() & 65535) % num_records;
count > 0;
count --, record = (record + ((int)CUPS_RAND() & 31) - 16 + num_records) % num_records)
{
/*
* The last record is always the first...
*/
if (count == 1)
record = 0;
/*
* Try reading the data for the specified record, and validate the
* contents...
*/
expected = (ssize_t)sizeof(buffer) * record;
if ((pos = cupsFileSeek(fp, expected)) != expected)
{
printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
CUPS_LLCAST pos, CUPS_LLCAST expected);
status ++;
break;
}
else
{
if (cupsFileRead(fp, buffer, sizeof(buffer)) != sizeof(buffer))
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
break;
}
else if ((buffer[0] & 255) != (record & 255) ||
memcmp(buffer, buffer + 1, sizeof(buffer) - 1))
{
printf("FAIL (Bad Data - %d instead of %d)\n", buffer[0] & 255,
record & 255);
status ++;
break;
}
}
}
if (count == 0)
puts("PASS");
cupsFileClose(fp);
}
/*
* Remove the test file...
*/
unlink("testfile.dat");
/*
* Return the test status...
*/
return (status);
}
/*
* 'read_write_tests()' - Perform read/write tests.
*/
static int /* O - Status */
read_write_tests(int compression) /* I - Use compression? */
{
int i; /* Looping var */
cups_file_t *fp; /* File */
int status; /* Exit status */
char line[1024], /* Line from file */
*value; /* Directive value from line */
int linenum; /* Line number */
unsigned char readbuf[8192], /* Read buffer */
writebuf[8192]; /* Write buffer */
int byte; /* Byte from file */
ssize_t bytes; /* Number of bytes read/written */
off_t length; /* Length of file */
static const char *partial_line = "partial line";
/* Partial line */
/*
* No errors so far...
*/
status = 0;
/*
* Initialize the write buffer with random data...
*/
CUPS_SRAND((unsigned)time(NULL));
for (i = 0; i < (int)sizeof(writebuf); i ++)
writebuf[i] = (unsigned char)CUPS_RAND();
/*
* cupsFileOpen(write)
*/
printf("cupsFileOpen(write%s): ", compression ? " compressed" : "");
fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat",
compression ? "w9" : "w");
if (fp)
{
puts("PASS");
/*
* cupsFileCompression()
*/
fputs("cupsFileCompression(): ", stdout);
if (cupsFileCompression(fp) == compression)
puts("PASS");
else
{
printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
compression);
status ++;
}
/*
* cupsFilePuts()
*/
fputs("cupsFilePuts(): ", stdout);
if (cupsFilePuts(fp, "# Hello, World\n") > 0)
puts("PASS");
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFilePrintf()
*/
fputs("cupsFilePrintf(): ", stdout);
for (i = 0; i < 1000; i ++)
if (cupsFilePrintf(fp, "TestLine %03d\n", i) < 0)
break;
if (i >= 1000)
puts("PASS");
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFilePutChar()
*/
fputs("cupsFilePutChar(): ", stdout);
for (i = 0; i < 256; i ++)
if (cupsFilePutChar(fp, i) < 0)
break;
if (i >= 256)
puts("PASS");
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFileWrite()
*/
fputs("cupsFileWrite(): ", stdout);
for (i = 0; i < 10000; i ++)
if (cupsFileWrite(fp, (char *)writebuf, sizeof(writebuf)) < 0)
break;
if (i >= 10000)
puts("PASS");
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFilePuts() with partial line...
*/
fputs("cupsFilePuts(\"partial line\"): ", stdout);
if (cupsFilePuts(fp, partial_line) > 0)
puts("PASS");
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFileTell()
*/
fputs("cupsFileTell(): ", stdout);
if ((length = cupsFileTell(fp)) == 81933283)
puts("PASS");
else
{
printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
status ++;
}
/*
* cupsFileClose()
*/
fputs("cupsFileClose(): ", stdout);
if (!cupsFileClose(fp))
puts("PASS");
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
}
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFileOpen(read)
*/
fputs("\ncupsFileOpen(read): ", stdout);
fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat", "r");
if (fp)
{
puts("PASS");
/*
* cupsFileGets()
*/
fputs("cupsFileGets(): ", stdout);
if (cupsFileGets(fp, line, sizeof(line)))
{
if (line[0] == '#')
puts("PASS");
else
{
printf("FAIL (Got line \"%s\", expected comment line)\n", line);
status ++;
}
}
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFileCompression()
*/
fputs("cupsFileCompression(): ", stdout);
if (cupsFileCompression(fp) == compression)
puts("PASS");
else
{
printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
compression);
status ++;
}
/*
* cupsFileGetConf()
*/
linenum = 1;
fputs("cupsFileGetConf(): ", stdout);
for (i = 0, value = NULL; i < 1000; i ++)
if (!cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
break;
else if (_cups_strcasecmp(line, "TestLine") || !value || atoi(value) != i ||
linenum != (i + 2))
break;
if (i >= 1000)
puts("PASS");
else if (line[0])
{
printf("FAIL (Line %d, directive \"%s\", value \"%s\")\n", linenum,
line, value ? value : "(null)");
status ++;
}
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFileGetChar()
*/
fputs("cupsFileGetChar(): ", stdout);
for (i = 0, byte = 0; i < 256; i ++)
if ((byte = cupsFileGetChar(fp)) != i)
break;
if (i >= 256)
puts("PASS");
else if (byte >= 0)
{
printf("FAIL (Got %d, expected %d)\n", byte, i);
status ++;
}
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFileRead()
*/
fputs("cupsFileRead(): ", stdout);
for (i = 0, bytes = 0; i < 10000; i ++)
if ((bytes = cupsFileRead(fp, (char *)readbuf, sizeof(readbuf))) < 0)
break;
else if (memcmp(readbuf, writebuf, sizeof(readbuf)))
break;
if (i >= 10000)
puts("PASS");
else if (bytes > 0)
{
printf("FAIL (Pass %d, ", i);
for (i = 0; i < (int)sizeof(readbuf); i ++)
if (readbuf[i] != writebuf[i])
break;
printf("match failed at offset %d - got %02X, expected %02X)\n",
i, readbuf[i], writebuf[i]);
}
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* cupsFileGetChar() with partial line...
*/
fputs("cupsFileGetChar(partial line): ", stdout);
for (i = 0; i < (int)strlen(partial_line); i ++)
if ((byte = cupsFileGetChar(fp)) < 0)
break;
else if (byte != partial_line[i])
break;
if (!partial_line[i])
puts("PASS");
else
{
printf("FAIL (got '%c', expected '%c')\n", byte, partial_line[i]);
status ++;
}
/*
* cupsFileTell()
*/
fputs("cupsFileTell(): ", stdout);
if ((length = cupsFileTell(fp)) == 81933283)
puts("PASS");
else
{
printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
status ++;
}
/*
* cupsFileClose()
*/
fputs("cupsFileClose(): ", stdout);
if (!cupsFileClose(fp))
puts("PASS");
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
}
else
{
printf("FAIL (%s)\n", strerror(errno));
status ++;
}
/*
* Remove the test file...
*/
if (!status)
unlink(compression ? "testfile.dat.gz" : "testfile.dat");
/*
* Return the test status...
*/
return (status);
}