]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testipp.c
34de16461cf2b5f679f667c06dae08ac82c4fa94
[thirdparty/cups.git] / cups / testipp.c
1 /*
2 * "$Id$"
3 *
4 * IPP test program for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 by Easy Software Products.
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
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
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>
37 #include <cups/string.h>
38 #include <errno.h>
39 #include "ipp.h"
40 #ifdef WIN32
41 # include <io.h>
42 #else
43 # include <unistd.h>
44 # include <fcntl.h>
45 #endif /* WIN32 */
46
47
48 /*
49 * Local globals...
50 */
51
52 int rpos; /* Current position in buffer */
53 ipp_uchar_t wbuffer[8192]; /* Write buffer */
54 int wused; /* Number of bytes in buffer */
55 ipp_uchar_t collection[] = /* Collection buffer */
56 {
57 0x01, 0x01, /* IPP version */
58 0x00, 0x02, /* Print-Job operation */
59 0x00, 0x00, 0x00, 0x01, /* Request ID */
60
61 IPP_TAG_OPERATION,
62
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',
69
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',
77
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',
85
86 IPP_TAG_JOB, /* job group tag */
87
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 */
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 */
110 0x00, 0x00, /* No name */
111 0x00, 0x00, /* No value */
112
113 IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
114 0x00, 0x00, /* No name */
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',
133 IPP_TAG_END_COLLECTION, /* endCollection tag */
134 0x00, 0x00, /* No name */
135 0x00, 0x00, /* No value */
136
137 IPP_TAG_END /* end tag */
138 };
139
140
141 /*
142 * Local functions...
143 */
144
145 void hex_dump(const char *title, ipp_uchar_t *buffer, int bytes);
146 void print_attributes(ipp_t *ipp, int indent);
147 ssize_t read_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
148 ssize_t write_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
149
150
151 /*
152 * 'main()' - Main entry.
153 */
154
155 int /* O - Exit status */
156 main(int argc, /* I - Number of command-line arguments */
157 char *argv[]) /* I - Command-line arguments */
158 {
159 ipp_t *cols[2]; /* Collections */
160 ipp_t *request; /* Request */
161 ipp_state_t state; /* State */
162 int length; /* Length of data */
163 int fd; /* File descriptor */
164 int i; /* Looping var */
165 int status; /* Status of tests (0 = success, 1 = fail) */
166
167
168 status = 0;
169
170 if (argc == 1)
171 {
172 /*
173 * Test request generation code...
174 */
175
176 printf("Create Sample Request: ");
177
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",
205 length, (int)sizeof(collection));
206 status = 1;
207 }
208 else
209 puts("PASS");
210
211 /*
212 * Write test #1...
213 */
214
215 printf("Write Sample to Memory: ");
216
217 wused = 0;
218 while ((state = ippWriteIO(wbuffer, write_cb, 1, NULL, request)) != IPP_DATA)
219 if (state == IPP_ERROR)
220 break;
221
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,
230 (int)sizeof(collection));
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");
244
245 ippDelete(request);
246
247 /*
248 * Read the data back in and confirm...
249 */
250
251 printf("Read Sample from Memory: ");
252
253 request = ippNew();
254 rpos = 0;
255
256 while ((state = ippReadIO(wbuffer, read_cb, 1, NULL, request)) != IPP_DATA)
257 if (state == IPP_ERROR)
258 break;
259
260 length = ippLength(request);
261
262 if (state != IPP_DATA)
263 {
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",
276 length, (int)sizeof(collection));
277 print_attributes(request, 8);
278 status = 1;
279 }
280 else
281 puts("PASS");
282
283 ippDelete(request);
284
285 /*
286 * Summarize...
287 */
288
289 putchar('\n');
290
291 if (status)
292 puts("Core IPP tests failed.");
293 else
294 puts("Core IPP tests passed.");
295 }
296 else
297 {
298 /*
299 * Read IPP files...
300 */
301
302 for (i = 1; i < argc; i ++)
303 {
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 }
324
325 ippDelete(request);
326 close(fd);
327 }
328 }
329
330 return (status);
331 }
332
333
334 /*
335 * 'hex_dump()' - Produce a hex dump of a buffer.
336 */
337
338 void
339 hex_dump(const char *title, /* I - Title */
340 ipp_uchar_t *buffer, /* I - Buffer to dump */
341 int bytes) /* I - Number of bytes */
342 {
343 int i, j; /* Looping vars */
344 int ch; /* Current ASCII char */
345
346
347 /*
348 * Show lines of 16 bytes at a time...
349 */
350
351 printf(" %s:\n", title);
352
353 for (i = 0; i < bytes; i += 16)
354 {
355 /*
356 * Show the offset...
357 */
358
359 printf(" %04x ", i);
360
361 /*
362 * Then up to 16 bytes in hex...
363 */
364
365 for (j = 0; j < 16; j ++)
366 if ((i + j) < bytes)
367 printf(" %02x", buffer[i + j]);
368 else
369 printf(" ");
370
371 /*
372 * Then the ASCII representation of the bytes...
373 */
374
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
393 /*
394 * 'print_attributes()' - Print the attributes in a request...
395 */
396
397 void
398 print_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 {
487 if ((attr->group_tag == IPP_TAG_ZERO && indent <= 8) || !attr->name)
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');
499 for (i = 4; i < indent; i ++)
500 putchar(' ');
501
502 printf("%s:\n\n", tags[group]);
503 }
504
505 for (i = 0; i < indent; i ++)
506 putchar(' ');
507
508 printf("%s (", attr->name);
509 if (attr->num_values > 1)
510 printf("1setOf ");
511 printf("%s):", tags[attr->value_tag]);
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
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
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 ++)
578 {
579 if (i)
580 putchar('\n');
581 print_attributes(val->collection, indent + 4);
582 }
583 break;
584
585 default :
586 printf("UNKNOWN (%d values)\n", attr->num_values);
587 break;
588 }
589 }
590 }
591
592
593 /*
594 * 'read_cb()' - Read data from a buffer.
595 */
596
597 ssize_t /* O - Number of bytes read */
598 read_cb(void *data, /* I - Data */
599 ipp_uchar_t *buffer, /* O - Buffer to read */
600 size_t bytes) /* I - Number of bytes to read */
601 {
602 int count; /* Number of bytes */
603
604
605 /*
606 * Copy bytes from the data buffer to the read buffer...
607 */
608
609 for (count = bytes; count > 0 && rpos < wused; count --, rpos ++)
610 *buffer++ = wbuffer[rpos];
611
612 /*
613 * Return the number of bytes read...
614 */
615
616 return (bytes - count);
617 }
618
619
620 /*
621 * 'write_cb()' - Write data into a buffer.
622 */
623
624 ssize_t /* O - Number of bytes written */
625 write_cb(void *data, /* I - Data */
626 ipp_uchar_t *buffer, /* I - Buffer to write */
627 size_t bytes) /* I - Number of bytes to write */
628 {
629 int count; /* Number of bytes */
630
631
632 /*
633 * Loop until all bytes are written...
634 */
635
636 for (count = bytes; count > 0 && wused < sizeof(wbuffer); count --, wused ++)
637 wbuffer[wused] = *buffer++;
638
639 /*
640 * Return the number of bytes written...
641 */
642
643 return (bytes - count);
644 }
645
646
647 /*
648 * End of "$Id$".
649 */