blob: aa119ace90176d30b3ce1219f3b1aa837ef9c3ef [file] [log] [blame]
/*
* "$Id: testipp.c 6649 2007-07-11 21:46:42Z mike $"
*
* IPP test program for the Common UNIX Printing System (CUPS).
*
* Copyright 2007 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
* which should have been included with this file. If this file is
* file is missing or damaged, see the license at "http://www.cups.org/".
*
* This file is subject to the Apple OS-Developed Software exception.
*
* Contents:
*
* main() - Main entry.
*/
/*
* Include necessary headers...
*/
#include <stdio.h>
#include <stdlib.h>
#include <cups/string.h>
#include <errno.h>
#include "ipp-private.h"
#ifdef WIN32
# include <io.h>
#else
# include <unistd.h>
# include <fcntl.h>
#endif /* WIN32 */
/*
* Local globals...
*/
int rpos; /* Current position in buffer */
ipp_uchar_t wbuffer[8192]; /* Write buffer */
int wused; /* Number of bytes in buffer */
ipp_uchar_t collection[] = /* Collection buffer */
{
0x01, 0x01, /* IPP version */
0x00, 0x02, /* Print-Job operation */
0x00, 0x00, 0x00, 0x01, /* Request ID */
IPP_TAG_OPERATION,
IPP_TAG_CHARSET,
0x00, 0x12, /* Name length + name */
'a','t','t','r','i','b','u','t','e','s','-',
'c','h','a','r','s','e','t',
0x00, 0x05, /* Value length + value */
'u','t','f','-','8',
IPP_TAG_LANGUAGE,
0x00, 0x1b, /* Name length + name */
'a','t','t','r','i','b','u','t','e','s','-',
'n','a','t','u','r','a','l','-','l','a','n',
'g','u','a','g','e',
0x00, 0x02, /* Value length + value */
'e','n',
IPP_TAG_URI,
0x00, 0x0b, /* Name length + name */
'p','r','i','n','t','e','r','-','u','r','i',
0x00, 0x1c, /* Value length + value */
'i','p','p',':','/','/','l','o','c','a','l',
'h','o','s','t','/','p','r','i','n','t','e',
'r','s','/','f','o','o',
IPP_TAG_JOB, /* job group tag */
IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
0x00, 0x09, /* Name length + name */
'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l',
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x04, /* Value length + value */
'b', 'l', 'u', 'e',
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x05, /* Value length + value */
'p', 'l', 'a', 'i', 'n',
IPP_TAG_END_COLLECTION, /* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x05, /* Value length + value */
'p', 'l', 'a', 'i', 'd',
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x06, /* Value length + value */
'g', 'l', 'o', 's', 's', 'y',
IPP_TAG_END_COLLECTION, /* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_END /* end tag */
};
/*
* Local functions...
*/
void hex_dump(const char *title, ipp_uchar_t *buffer, int bytes);
void print_attributes(ipp_t *ipp, int indent);
ssize_t read_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
ssize_t write_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
/*
* 'main()' - Main entry.
*/
int /* O - Exit status */
main(int argc, /* I - Number of command-line arguments */
char *argv[]) /* I - Command-line arguments */
{
ipp_t *cols[2]; /* Collections */
ipp_t *request; /* Request */
ipp_state_t state; /* State */
int length; /* Length of data */
int fd; /* File descriptor */
int i; /* Looping var */
int status; /* Status of tests (0 = success, 1 = fail) */
status = 0;
if (argc == 1)
{
/*
* Test request generation code...
*/
printf("Create Sample Request: ");
request = ippNew();
request->request.op.version[0] = 0x01;
request->request.op.version[1] = 0x01;
request->request.op.operation_id = IPP_PRINT_JOB;
request->request.op.request_id = 1;
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
"attributes-charset", NULL, "utf-8");
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, "en");
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, "ipp://localhost/printers/foo");
cols[0] = ippNew();
ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "blue");
ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "plain");
cols[1] = ippNew();
ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "plaid");
ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "glossy");
ippAddCollections(request, IPP_TAG_JOB, "media-col", 2, (const ipp_t **)cols);
length = ippLength(request);
if (length != sizeof(collection))
{
printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
length, (int)sizeof(collection));
status = 1;
}
else
puts("PASS");
/*
* Write test #1...
*/
printf("Write Sample to Memory: ");
wused = 0;
while ((state = ippWriteIO(wbuffer, write_cb, 1, NULL, request)) != IPP_DATA)
if (state == IPP_ERROR)
break;
if (state != IPP_DATA)
{
printf("FAIL - %d bytes written.\n", wused);
status = 1;
}
else if (wused != sizeof(collection))
{
printf("FAIL - wrote %d bytes, expected %d bytes!\n", wused,
(int)sizeof(collection));
hex_dump("Bytes Written", wbuffer, wused);
hex_dump("Baseline", collection, sizeof(collection));
status = 1;
}
else if (memcmp(wbuffer, collection, wused))
{
puts("FAIL - output does not match baseline!");
hex_dump("Bytes Written", wbuffer, wused);
hex_dump("Baseline", collection, sizeof(collection));
status = 1;
}
else
puts("PASS");
ippDelete(request);
/*
* Read the data back in and confirm...
*/
printf("Read Sample from Memory: ");
request = ippNew();
rpos = 0;
while ((state = ippReadIO(wbuffer, read_cb, 1, NULL, request)) != IPP_DATA)
if (state == IPP_ERROR)
break;
length = ippLength(request);
if (state != IPP_DATA)
{
printf("FAIL - %d bytes read.\n", rpos);
status = 1;
}
else if (rpos != wused)
{
printf("FAIL - read %d bytes, expected %d bytes!\n", rpos, wused);
print_attributes(request, 8);
status = 1;
}
else if (length != sizeof(collection))
{
printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
length, (int)sizeof(collection));
print_attributes(request, 8);
status = 1;
}
else
puts("PASS");
ippDelete(request);
/*
* Test _ippFindOption() private API...
*/
fputs("_ippFindOption(\"printer-type\"): ", stdout);
if (_ippFindOption("printer-type"))
puts("PASS");
else
{
puts("FAIL");
status = 1;
}
/*
* Summarize...
*/
putchar('\n');
if (status)
puts("Core IPP tests failed.");
else
puts("Core IPP tests passed.");
}
else
{
/*
* Read IPP files...
*/
for (i = 1; i < argc; i ++)
{
if ((fd = open(argv[i], O_RDONLY)) < 0)
{
printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
status = 1;
continue;
}
request = ippNew();
while ((state = ippReadFile(fd, request)) == IPP_ATTRIBUTE);
if (state != IPP_DATA)
{
printf("Error reading IPP message from \"%s\"!\n", argv[i]);
status = 1;
}
else
{
printf("\n%s:\n", argv[i]);
print_attributes(request, 4);
}
ippDelete(request);
close(fd);
}
}
return (status);
}
/*
* 'hex_dump()' - Produce a hex dump of a buffer.
*/
void
hex_dump(const char *title, /* I - Title */
ipp_uchar_t *buffer, /* I - Buffer to dump */
int bytes) /* I - Number of bytes */
{
int i, j; /* Looping vars */
int ch; /* Current ASCII char */
/*
* Show lines of 16 bytes at a time...
*/
printf(" %s:\n", title);
for (i = 0; i < bytes; i += 16)
{
/*
* Show the offset...
*/
printf(" %04x ", i);
/*
* Then up to 16 bytes in hex...
*/
for (j = 0; j < 16; j ++)
if ((i + j) < bytes)
printf(" %02x", buffer[i + j]);
else
printf(" ");
/*
* Then the ASCII representation of the bytes...
*/
putchar(' ');
putchar(' ');
for (j = 0; j < 16 && (i + j) < bytes; j ++)
{
ch = buffer[i + j] & 127;
if (ch < ' ' || ch == 127)
putchar('.');
else
putchar(ch);
}
putchar('\n');
}
}
/*
* 'print_attributes()' - Print the attributes in a request...
*/
void
print_attributes(ipp_t *ipp, /* I - IPP request */
int indent) /* I - Indentation */
{
int i; /* Looping var */
ipp_tag_t group; /* Current group */
ipp_attribute_t *attr; /* Current attribute */
ipp_value_t *val; /* Current value */
static const char * const tags[] = /* Value/group tag strings */
{
"reserved-00",
"operation-attributes-tag",
"job-attributes-tag",
"end-of-attributes-tag",
"printer-attributes-tag",
"unsupported-attributes-tag",
"subscription-attributes-tag",
"event-attributes-tag",
"reserved-08",
"reserved-09",
"reserved-0A",
"reserved-0B",
"reserved-0C",
"reserved-0D",
"reserved-0E",
"reserved-0F",
"unsupported",
"default",
"unknown",
"no-value",
"reserved-14",
"not-settable",
"delete-attr",
"admin-define",
"reserved-18",
"reserved-19",
"reserved-1A",
"reserved-1B",
"reserved-1C",
"reserved-1D",
"reserved-1E",
"reserved-1F",
"reserved-20",
"integer",
"boolean",
"enum",
"reserved-24",
"reserved-25",
"reserved-26",
"reserved-27",
"reserved-28",
"reserved-29",
"reserved-2a",
"reserved-2b",
"reserved-2c",
"reserved-2d",
"reserved-2e",
"reserved-2f",
"octetString",
"dateTime",
"resolution",
"rangeOfInteger",
"begCollection",
"textWithLanguage",
"nameWithLanguage",
"endCollection",
"reserved-38",
"reserved-39",
"reserved-3a",
"reserved-3b",
"reserved-3c",
"reserved-3d",
"reserved-3e",
"reserved-3f",
"reserved-40",
"textWithoutLanguage",
"nameWithoutLanguage",
"reserved-43",
"keyword",
"uri",
"uriScheme",
"charset",
"naturalLanguage",
"mimeMediaType",
"memberName"
};
for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
{
if ((attr->group_tag == IPP_TAG_ZERO && indent <= 8) || !attr->name)
{
group = IPP_TAG_ZERO;
putchar('\n');
continue;
}
if (group != attr->group_tag)
{
group = attr->group_tag;
putchar('\n');
for (i = 4; i < indent; i ++)
putchar(' ');
printf("%s:\n\n", tags[group]);
}
for (i = 0; i < indent; i ++)
putchar(' ');
printf("%s (", attr->name);
if (attr->num_values > 1)
printf("1setOf ");
printf("%s):", tags[attr->value_tag]);
switch (attr->value_tag)
{
case IPP_TAG_ENUM :
case IPP_TAG_INTEGER :
for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
printf(" %d", val->integer);
putchar('\n');
break;
case IPP_TAG_BOOLEAN :
for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
printf(" %s", val->boolean ? "true" : "false");
putchar('\n');
break;
case IPP_TAG_RANGE :
for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
printf(" %d-%d", val->range.lower, val->range.upper);
putchar('\n');
break;
case IPP_TAG_DATE :
{
time_t vtime; /* Date/Time value */
struct tm *vdate; /* Date info */
char vstring[256]; /* Formatted time */
for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
{
vtime = ippDateToTime(val->date);
vdate = localtime(&vtime);
strftime(vstring, sizeof(vstring), "%c", vdate);
printf(" (%s)", vstring);
}
}
putchar('\n');
break;
case IPP_TAG_RESOLUTION :
for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
printf(" %dx%d%s", val->resolution.xres, val->resolution.yres,
val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpc");
putchar('\n');
break;
case IPP_TAG_STRING :
case IPP_TAG_TEXTLANG :
case IPP_TAG_NAMELANG :
case IPP_TAG_TEXT :
case IPP_TAG_NAME :
case IPP_TAG_KEYWORD :
case IPP_TAG_URI :
case IPP_TAG_URISCHEME :
case IPP_TAG_CHARSET :
case IPP_TAG_LANGUAGE :
case IPP_TAG_MIMETYPE :
for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
printf(" \"%s\"", val->string.text);
putchar('\n');
break;
case IPP_TAG_BEGIN_COLLECTION :
putchar('\n');
for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
{
if (i)
putchar('\n');
print_attributes(val->collection, indent + 4);
}
break;
default :
printf("UNKNOWN (%d values)\n", attr->num_values);
break;
}
}
}
/*
* 'read_cb()' - Read data from a buffer.
*/
ssize_t /* O - Number of bytes read */
read_cb(void *data, /* I - Data */
ipp_uchar_t *buffer, /* O - Buffer to read */
size_t bytes) /* I - Number of bytes to read */
{
int count; /* Number of bytes */
/*
* Copy bytes from the data buffer to the read buffer...
*/
for (count = bytes; count > 0 && rpos < wused; count --, rpos ++)
*buffer++ = wbuffer[rpos];
/*
* Return the number of bytes read...
*/
return (bytes - count);
}
/*
* 'write_cb()' - Write data into a buffer.
*/
ssize_t /* O - Number of bytes written */
write_cb(void *data, /* I - Data */
ipp_uchar_t *buffer, /* I - Buffer to write */
size_t bytes) /* I - Number of bytes to write */
{
int count; /* Number of bytes */
/*
* Loop until all bytes are written...
*/
for (count = bytes; count > 0 && wused < sizeof(wbuffer); count --, wused ++)
wbuffer[wused] = *buffer++;
/*
* Return the number of bytes written...
*/
return (bytes - count);
}
/*
* End of "$Id: testipp.c 6649 2007-07-11 21:46:42Z mike $".
*/