]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/testipp.c
File cleanup.
[thirdparty/cups.git] / cups / testipp.c
CommitLineData
7856bac0 1/*
c9d3f842 2 * "$Id$"
7856bac0 3 *
4 * IPP test program for the Common UNIX Printing System (CUPS).
5 *
c9d3f842 6 * Copyright 1997-2005 by Easy Software Products.
7856bac0 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
c9d3f842 18 * Hollywood, Maryland 20636 USA
7856bac0 19 *
c4dcf3cc 20 * Voice: (301) 373-9600
7856bac0 21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * main() - Main entry.
29 */
30
31/*
32 * Include necessary headers...
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
265fb4a4 37#include <cups/string.h>
38#include <errno.h>
7856bac0 39#include "ipp.h"
265fb4a4 40#ifdef WIN32
41# include <io.h>
42#else
43# include <unistd.h>
44# include <fcntl.h>
45#endif /* WIN32 */
7856bac0 46
47
48/*
49 * Local globals...
50 */
51
52int rpos; /* Current position in buffer */
53ipp_uchar_t wbuffer[8192]; /* Write buffer */
54int wused; /* Number of bytes in buffer */
55ipp_uchar_t collection[] = /* Collection buffer */
56 {
57 0x01, 0x01, /* IPP version */
58 0x00, 0x02, /* Print-Job operation */
59 0x00, 0x00, 0x00, 0x01, /* Request ID */
b1b45888 60
dd63ebe2 61 IPP_TAG_OPERATION,
b1b45888 62
dd63ebe2 63 IPP_TAG_CHARSET,
64 0x00, 0x12, /* Name length + name */
65 'a','t','t','r','i','b','u','t','e','s','-',
66 'c','h','a','r','s','e','t',
67 0x00, 0x05, /* Value length + value */
68 'u','t','f','-','8',
b1b45888 69
dd63ebe2 70 IPP_TAG_LANGUAGE,
71 0x00, 0x1b, /* Name length + name */
72 'a','t','t','r','i','b','u','t','e','s','-',
73 'n','a','t','u','r','a','l','-','l','a','n',
74 'g','u','a','g','e',
75 0x00, 0x02, /* Value length + value */
76 'e','n',
b1b45888 77
dd63ebe2 78 IPP_TAG_URI,
79 0x00, 0x0b, /* Name length + name */
80 'p','r','i','n','t','e','r','-','u','r','i',
81 0x00, 0x1c, /* Value length + value */
82 'i','p','p',':','/','/','l','o','c','a','l',
83 'h','o','s','t','/','p','r','i','n','t','e',
84 'r','s','/','f','o','o',
b1b45888 85
7856bac0 86 IPP_TAG_JOB, /* job group tag */
b1b45888 87
7856bac0 88 IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
89 0x00, 0x09, /* Name length + name */
90 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l',
91 0x00, 0x00, /* No value */
b1b45888 92 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
93 0x00, 0x00, /* No name */
94 0x00, 0x0b, /* Value length + value */
95 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
96 IPP_TAG_KEYWORD, /* keyword tag */
97 0x00, 0x00, /* No name */
98 0x00, 0x04, /* Value length + value */
99 'b', 'l', 'u', 'e',
100
101 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
102 0x00, 0x00, /* No name */
103 0x00, 0x0a, /* Value length + value */
104 'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
105 IPP_TAG_KEYWORD, /* keyword tag */
106 0x00, 0x00, /* No name */
107 0x00, 0x05, /* Value length + value */
108 'p', 'l', 'a', 'i', 'n',
109 IPP_TAG_END_COLLECTION, /* endCollection tag */
7856bac0 110 0x00, 0x00, /* No name */
b1b45888 111 0x00, 0x00, /* No value */
112
113 IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
7856bac0 114 0x00, 0x00, /* No name */
b1b45888 115 0x00, 0x00, /* No value */
116 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
117 0x00, 0x00, /* No name */
118 0x00, 0x0b, /* Value length + value */
119 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
120 IPP_TAG_KEYWORD, /* keyword tag */
121 0x00, 0x00, /* No name */
122 0x00, 0x05, /* Value length + value */
123 'p', 'l', 'a', 'i', 'd',
124
125 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
126 0x00, 0x00, /* No name */
127 0x00, 0x0a, /* Value length + value */
128 'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
129 IPP_TAG_KEYWORD, /* keyword tag */
130 0x00, 0x00, /* No name */
131 0x00, 0x06, /* Value length + value */
132 'g', 'l', 'o', 's', 's', 'y',
7856bac0 133 IPP_TAG_END_COLLECTION, /* endCollection tag */
134 0x00, 0x00, /* No name */
135 0x00, 0x00, /* No value */
b1b45888 136
7856bac0 137 IPP_TAG_END /* end tag */
138 };
139
140
141/*
142 * Local functions...
143 */
144
b1b45888 145void hex_dump(const char *title, ipp_uchar_t *buffer, int bytes);
265fb4a4 146void print_attributes(ipp_t *ipp, int indent);
00a1fad8 147ssize_t read_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
148ssize_t write_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
7856bac0 149
150
151/*
152 * 'main()' - Main entry.
153 */
154
155int /* O - Exit status */
156main(int argc, /* I - Number of command-line arguments */
157 char *argv[]) /* I - Command-line arguments */
158{
b1b45888 159 ipp_t *cols[2]; /* Collections */
7856bac0 160 ipp_t *request; /* Request */
161 ipp_state_t state; /* State */
9cc4a1c4 162 int length; /* Length of data */
265fb4a4 163 int fd; /* File descriptor */
164 int i; /* Looping var */
b1b45888 165 int status; /* Status of tests (0 = success, 1 = fail) */
7856bac0 166
167
b1b45888 168 status = 0;
7856bac0 169
b1b45888 170 if (argc == 1)
171 {
172 /*
173 * Test request generation code...
174 */
dd63ebe2 175
b1b45888 176 printf("Create Sample Request: ");
7856bac0 177
b1b45888 178 request = ippNew();
179 request->request.op.version[0] = 0x01;
180 request->request.op.version[1] = 0x01;
181 request->request.op.operation_id = IPP_PRINT_JOB;
182 request->request.op.request_id = 1;
183
184 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
185 "attributes-charset", NULL, "utf-8");
186 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
187 "attributes-natural-language", NULL, "en");
188 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
189 "printer-uri", NULL, "ipp://localhost/printers/foo");
190
191 cols[0] = ippNew();
192 ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "blue");
193 ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "plain");
194
195 cols[1] = ippNew();
196 ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "plaid");
197 ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "glossy");
198
199 ippAddCollections(request, IPP_TAG_JOB, "media-col", 2, (const ipp_t **)cols);
200
201 length = ippLength(request);
202 if (length != sizeof(collection))
203 {
204 printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
5969280f 205 length, (int)sizeof(collection));
b1b45888 206 status = 1;
207 }
208 else
209 puts("PASS");
9cc4a1c4 210
b1b45888 211 /*
212 * Write test #1...
213 */
7856bac0 214
b1b45888 215 printf("Write Sample to Memory: ");
7856bac0 216
b1b45888 217 wused = 0;
218 while ((state = ippWriteIO(wbuffer, write_cb, 1, NULL, request)) != IPP_DATA)
219 if (state == IPP_ERROR)
220 break;
7856bac0 221
b1b45888 222 if (state != IPP_DATA)
223 {
224 printf("FAIL - %d bytes written.\n", wused);
225 status = 1;
226 }
227 else if (wused != sizeof(collection))
228 {
229 printf("FAIL - wrote %d bytes, expected %d bytes!\n", wused,
5969280f 230 (int)sizeof(collection));
b1b45888 231 hex_dump("Bytes Written", wbuffer, wused);
232 hex_dump("Baseline", collection, sizeof(collection));
233 status = 1;
234 }
235 else if (memcmp(wbuffer, collection, wused))
236 {
237 puts("FAIL - output does not match baseline!");
238 hex_dump("Bytes Written", wbuffer, wused);
239 hex_dump("Baseline", collection, sizeof(collection));
240 status = 1;
241 }
242 else
243 puts("PASS");
7856bac0 244
b1b45888 245 ippDelete(request);
7856bac0 246
b1b45888 247 /*
248 * Read the data back in and confirm...
249 */
7856bac0 250
b1b45888 251 printf("Read Sample from Memory: ");
7856bac0 252
b1b45888 253 request = ippNew();
254 rpos = 0;
7856bac0 255
b1b45888 256 while ((state = ippReadIO(wbuffer, read_cb, 1, NULL, request)) != IPP_DATA)
257 if (state == IPP_ERROR)
258 break;
7856bac0 259
b1b45888 260 length = ippLength(request);
265fb4a4 261
b1b45888 262 if (state != IPP_DATA)
265fb4a4 263 {
b1b45888 264 printf("FAIL - %d bytes read.\n", rpos);
265 status = 1;
266 }
267 else if (rpos != wused)
268 {
269 printf("FAIL - read %d bytes, expected %d bytes!\n", rpos, wused);
270 print_attributes(request, 8);
271 status = 1;
272 }
273 else if (length != sizeof(collection))
274 {
275 printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
5969280f 276 length, (int)sizeof(collection));
b1b45888 277 print_attributes(request, 8);
278 status = 1;
265fb4a4 279 }
b1b45888 280 else
281 puts("PASS");
265fb4a4 282
b1b45888 283 ippDelete(request);
265fb4a4 284
b1b45888 285 /*
286 * Summarize...
287 */
288
289 putchar('\n');
290
291 if (status)
292 puts("Core IPP tests failed.");
265fb4a4 293 else
b1b45888 294 puts("Core IPP tests passed.");
295 }
296 else
297 {
298 /*
299 * Read IPP files...
300 */
301
302 for (i = 1; i < argc; i ++)
265fb4a4 303 {
b1b45888 304 if ((fd = open(argv[i], O_RDONLY)) < 0)
305 {
306 printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
307 status = 1;
308 continue;
309 }
310
311 request = ippNew();
312 while ((state = ippReadFile(fd, request)) == IPP_ATTRIBUTE);
313
314 if (state != IPP_DATA)
315 {
316 printf("Error reading IPP message from \"%s\"!\n", argv[i]);
317 status = 1;
318 }
319 else
320 {
321 printf("\n%s:\n", argv[i]);
322 print_attributes(request, 4);
323 }
265fb4a4 324
b1b45888 325 ippDelete(request);
326 close(fd);
327 }
265fb4a4 328 }
329
b1b45888 330 return (status);
7856bac0 331}
332
333
265fb4a4 334/*
335 * 'hex_dump()' - Produce a hex dump of a buffer.
336 */
337
7856bac0 338void
b1b45888 339hex_dump(const char *title, /* I - Title */
340 ipp_uchar_t *buffer, /* I - Buffer to dump */
265fb4a4 341 int bytes) /* I - Number of bytes */
7856bac0 342{
265fb4a4 343 int i, j; /* Looping vars */
344 int ch; /* Current ASCII char */
345
7856bac0 346
265fb4a4 347 /*
348 * Show lines of 16 bytes at a time...
349 */
7856bac0 350
b1b45888 351 printf(" %s:\n", title);
352
7856bac0 353 for (i = 0; i < bytes; i += 16)
354 {
265fb4a4 355 /*
356 * Show the offset...
357 */
358
b1b45888 359 printf(" %04x ", i);
7856bac0 360
265fb4a4 361 /*
362 * Then up to 16 bytes in hex...
363 */
364
7856bac0 365 for (j = 0; j < 16; j ++)
366 if ((i + j) < bytes)
367 printf(" %02x", buffer[i + j]);
368 else
369 printf(" ");
370
265fb4a4 371 /*
372 * Then the ASCII representation of the bytes...
373 */
374
7856bac0 375 putchar(' ');
376 putchar(' ');
377
378 for (j = 0; j < 16 && (i + j) < bytes; j ++)
379 {
380 ch = buffer[i + j] & 127;
381
382 if (ch < ' ' || ch == 127)
383 putchar('.');
384 else
385 putchar(ch);
386 }
387
388 putchar('\n');
389 }
390}
391
392
265fb4a4 393/*
394 * 'print_attributes()' - Print the attributes in a request...
395 */
396
397void
398print_attributes(ipp_t *ipp, /* I - IPP request */
399 int indent) /* I - Indentation */
400{
401 int i; /* Looping var */
402 ipp_tag_t group; /* Current group */
403 ipp_attribute_t *attr; /* Current attribute */
404 ipp_value_t *val; /* Current value */
405 static const char * const tags[] = /* Value/group tag strings */
406 {
407 "reserved-00",
408 "operation-attributes-tag",
409 "job-attributes-tag",
410 "end-of-attributes-tag",
411 "printer-attributes-tag",
412 "unsupported-attributes-tag",
413 "subscription-attributes-tag",
414 "event-attributes-tag",
415 "reserved-08",
416 "reserved-09",
417 "reserved-0A",
418 "reserved-0B",
419 "reserved-0C",
420 "reserved-0D",
421 "reserved-0E",
422 "reserved-0F",
423 "unsupported",
424 "default",
425 "unknown",
426 "no-value",
427 "reserved-14",
428 "not-settable",
429 "delete-attr",
430 "admin-define",
431 "reserved-18",
432 "reserved-19",
433 "reserved-1A",
434 "reserved-1B",
435 "reserved-1C",
436 "reserved-1D",
437 "reserved-1E",
438 "reserved-1F",
439 "reserved-20",
440 "integer",
441 "boolean",
442 "enum",
443 "reserved-24",
444 "reserved-25",
445 "reserved-26",
446 "reserved-27",
447 "reserved-28",
448 "reserved-29",
449 "reserved-2a",
450 "reserved-2b",
451 "reserved-2c",
452 "reserved-2d",
453 "reserved-2e",
454 "reserved-2f",
455 "octetString",
456 "dateTime",
457 "resolution",
458 "rangeOfInteger",
459 "begCollection",
460 "textWithLanguage",
461 "nameWithLanguage",
462 "endCollection",
463 "reserved-38",
464 "reserved-39",
465 "reserved-3a",
466 "reserved-3b",
467 "reserved-3c",
468 "reserved-3d",
469 "reserved-3e",
470 "reserved-3f",
471 "reserved-40",
472 "textWithoutLanguage",
473 "nameWithoutLanguage",
474 "reserved-43",
475 "keyword",
476 "uri",
477 "uriScheme",
478 "charset",
479 "naturalLanguage",
480 "mimeMediaType",
481 "memberName"
482 };
483
484
485 for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
486 {
b1b45888 487 if ((attr->group_tag == IPP_TAG_ZERO && indent <= 8) || !attr->name)
265fb4a4 488 {
489 group = IPP_TAG_ZERO;
490 putchar('\n');
491 continue;
492 }
493
494 if (group != attr->group_tag)
495 {
496 group = attr->group_tag;
497
498 putchar('\n');
b1b45888 499 for (i = 4; i < indent; i ++)
265fb4a4 500 putchar(' ');
501
b696f4e3 502 printf("%s:\n\n", tags[group]);
265fb4a4 503 }
504
505 for (i = 0; i < indent; i ++)
506 putchar(' ');
507
b1b45888 508 printf("%s (", attr->name);
509 if (attr->num_values > 1)
510 printf("1setOf ");
511 printf("%s):", tags[attr->value_tag]);
265fb4a4 512
513 switch (attr->value_tag)
514 {
515 case IPP_TAG_ENUM :
516 case IPP_TAG_INTEGER :
517 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
518 printf(" %d", val->integer);
519 putchar('\n');
520 break;
521
522 case IPP_TAG_BOOLEAN :
523 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
524 printf(" %s", val->boolean ? "true" : "false");
525 putchar('\n');
526 break;
527
b696f4e3 528 case IPP_TAG_RANGE :
529 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
530 printf(" %d-%d", val->range.lower, val->range.upper);
531 putchar('\n');
532 break;
533
534 case IPP_TAG_DATE :
535 {
536 time_t vtime; /* Date/Time value */
537 struct tm *vdate; /* Date info */
538 char vstring[256]; /* Formatted time */
539
540 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
541 {
542 vtime = ippDateToTime(val->date);
543 vdate = localtime(&vtime);
544 strftime(vstring, sizeof(vstring), "%c", vdate);
545 printf(" (%s)", vstring);
546 }
547 }
548 putchar('\n');
549 break;
550
551 case IPP_TAG_RESOLUTION :
552 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
553 printf(" %dx%d%s", val->resolution.xres, val->resolution.yres,
554 val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpc");
555 putchar('\n');
556 break;
557
265fb4a4 558 case IPP_TAG_STRING :
559 case IPP_TAG_TEXTLANG :
560 case IPP_TAG_NAMELANG :
561 case IPP_TAG_TEXT :
562 case IPP_TAG_NAME :
563 case IPP_TAG_KEYWORD :
564 case IPP_TAG_URI :
565 case IPP_TAG_URISCHEME :
566 case IPP_TAG_CHARSET :
567 case IPP_TAG_LANGUAGE :
568 case IPP_TAG_MIMETYPE :
569 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
570 printf(" \"%s\"", val->string.text);
571 putchar('\n');
572 break;
573
574 case IPP_TAG_BEGIN_COLLECTION :
575 putchar('\n');
576
577 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
b1b45888 578 {
579 if (i)
580 putchar('\n');
265fb4a4 581 print_attributes(val->collection, indent + 4);
b1b45888 582 }
265fb4a4 583 break;
584
585 default :
b1b45888 586 printf("UNKNOWN (%d values)\n", attr->num_values);
265fb4a4 587 break;
588 }
265fb4a4 589 }
590}
591
592
593/*
594 * 'read_cb()' - Read data from a buffer.
595 */
596
00a1fad8 597ssize_t /* O - Number of bytes read */
265fb4a4 598read_cb(void *data, /* I - Data */
599 ipp_uchar_t *buffer, /* O - Buffer to read */
00a1fad8 600 size_t bytes) /* I - Number of bytes to read */
7856bac0 601{
265fb4a4 602 int count; /* Number of bytes */
7856bac0 603
604
265fb4a4 605 /*
606 * Copy bytes from the data buffer to the read buffer...
607 */
608
7856bac0 609 for (count = bytes; count > 0 && rpos < wused; count --, rpos ++)
610 *buffer++ = wbuffer[rpos];
611
265fb4a4 612 /*
613 * Return the number of bytes read...
614 */
615
7856bac0 616 return (bytes - count);
617}
618
619
265fb4a4 620/*
621 * 'write_cb()' - Write data into a buffer.
622 */
623
00a1fad8 624ssize_t /* O - Number of bytes written */
265fb4a4 625write_cb(void *data, /* I - Data */
626 ipp_uchar_t *buffer, /* I - Buffer to write */
00a1fad8 627 size_t bytes) /* I - Number of bytes to write */
7856bac0 628{
265fb4a4 629 int count; /* Number of bytes */
630
7856bac0 631
265fb4a4 632 /*
633 * Loop until all bytes are written...
634 */
7856bac0 635
636 for (count = bytes; count > 0 && wused < sizeof(wbuffer); count --, wused ++)
637 wbuffer[wused] = *buffer++;
638
265fb4a4 639 /*
640 * Return the number of bytes written...
641 */
7856bac0 642
643 return (bytes - count);
644}
645
646
647/*
c9d3f842 648 * End of "$Id$".
7856bac0 649 */