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