]> 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/*
f7deaa1a 2 * "$Id: testipp.c 5749 2006-07-18 18:36:09Z mike $"
ef416fc2 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>
8ca02f3c 39#include "ipp-private.h"
ef416fc2 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
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 */
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
145void hex_dump(const char *title, ipp_uchar_t *buffer, int bytes);
146void print_attributes(ipp_t *ipp, int indent);
a4d04587 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);
ef416fc2 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{
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
8ca02f3c 285 /*
286 * Test _ippFindOption() private API...
287 */
288
289 fputs("_ippFindOption(\"printer-type\"): ", stdout);
290 if (_ippFindOption("printer-type"))
291 puts("PASS");
292 else
293 {
294 puts("FAIL");
295 status = 1;
296 }
297
ef416fc2 298 /*
299 * Summarize...
300 */
301
302 putchar('\n');
303
304 if (status)
305 puts("Core IPP tests failed.");
306 else
307 puts("Core IPP tests passed.");
308 }
309 else
310 {
311 /*
312 * Read IPP files...
313 */
314
315 for (i = 1; i < argc; i ++)
316 {
317 if ((fd = open(argv[i], O_RDONLY)) < 0)
318 {
319 printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
320 status = 1;
321 continue;
322 }
323
324 request = ippNew();
325 while ((state = ippReadFile(fd, request)) == IPP_ATTRIBUTE);
326
327 if (state != IPP_DATA)
328 {
329 printf("Error reading IPP message from \"%s\"!\n", argv[i]);
330 status = 1;
331 }
332 else
333 {
334 printf("\n%s:\n", argv[i]);
335 print_attributes(request, 4);
336 }
337
338 ippDelete(request);
339 close(fd);
340 }
341 }
342
343 return (status);
344}
345
346
347/*
348 * 'hex_dump()' - Produce a hex dump of a buffer.
349 */
350
351void
352hex_dump(const char *title, /* I - Title */
353 ipp_uchar_t *buffer, /* I - Buffer to dump */
354 int bytes) /* I - Number of bytes */
355{
356 int i, j; /* Looping vars */
357 int ch; /* Current ASCII char */
358
359
360 /*
361 * Show lines of 16 bytes at a time...
362 */
363
364 printf(" %s:\n", title);
365
366 for (i = 0; i < bytes; i += 16)
367 {
368 /*
369 * Show the offset...
370 */
371
372 printf(" %04x ", i);
373
374 /*
375 * Then up to 16 bytes in hex...
376 */
377
378 for (j = 0; j < 16; j ++)
379 if ((i + j) < bytes)
380 printf(" %02x", buffer[i + j]);
381 else
382 printf(" ");
383
384 /*
385 * Then the ASCII representation of the bytes...
386 */
387
388 putchar(' ');
389 putchar(' ');
390
391 for (j = 0; j < 16 && (i + j) < bytes; j ++)
392 {
393 ch = buffer[i + j] & 127;
394
395 if (ch < ' ' || ch == 127)
396 putchar('.');
397 else
398 putchar(ch);
399 }
400
401 putchar('\n');
402 }
403}
404
405
406/*
407 * 'print_attributes()' - Print the attributes in a request...
408 */
409
410void
411print_attributes(ipp_t *ipp, /* I - IPP request */
412 int indent) /* I - Indentation */
413{
414 int i; /* Looping var */
415 ipp_tag_t group; /* Current group */
416 ipp_attribute_t *attr; /* Current attribute */
417 ipp_value_t *val; /* Current value */
418 static const char * const tags[] = /* Value/group tag strings */
419 {
420 "reserved-00",
421 "operation-attributes-tag",
422 "job-attributes-tag",
423 "end-of-attributes-tag",
424 "printer-attributes-tag",
425 "unsupported-attributes-tag",
426 "subscription-attributes-tag",
427 "event-attributes-tag",
428 "reserved-08",
429 "reserved-09",
430 "reserved-0A",
431 "reserved-0B",
432 "reserved-0C",
433 "reserved-0D",
434 "reserved-0E",
435 "reserved-0F",
436 "unsupported",
437 "default",
438 "unknown",
439 "no-value",
440 "reserved-14",
441 "not-settable",
442 "delete-attr",
443 "admin-define",
444 "reserved-18",
445 "reserved-19",
446 "reserved-1A",
447 "reserved-1B",
448 "reserved-1C",
449 "reserved-1D",
450 "reserved-1E",
451 "reserved-1F",
452 "reserved-20",
453 "integer",
454 "boolean",
455 "enum",
456 "reserved-24",
457 "reserved-25",
458 "reserved-26",
459 "reserved-27",
460 "reserved-28",
461 "reserved-29",
462 "reserved-2a",
463 "reserved-2b",
464 "reserved-2c",
465 "reserved-2d",
466 "reserved-2e",
467 "reserved-2f",
468 "octetString",
469 "dateTime",
470 "resolution",
471 "rangeOfInteger",
472 "begCollection",
473 "textWithLanguage",
474 "nameWithLanguage",
475 "endCollection",
476 "reserved-38",
477 "reserved-39",
478 "reserved-3a",
479 "reserved-3b",
480 "reserved-3c",
481 "reserved-3d",
482 "reserved-3e",
483 "reserved-3f",
484 "reserved-40",
485 "textWithoutLanguage",
486 "nameWithoutLanguage",
487 "reserved-43",
488 "keyword",
489 "uri",
490 "uriScheme",
491 "charset",
492 "naturalLanguage",
493 "mimeMediaType",
494 "memberName"
495 };
496
497
498 for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
499 {
500 if ((attr->group_tag == IPP_TAG_ZERO && indent <= 8) || !attr->name)
501 {
502 group = IPP_TAG_ZERO;
503 putchar('\n');
504 continue;
505 }
506
507 if (group != attr->group_tag)
508 {
509 group = attr->group_tag;
510
511 putchar('\n');
512 for (i = 4; i < indent; i ++)
513 putchar(' ');
514
515 printf("%s:\n\n", tags[group]);
516 }
517
518 for (i = 0; i < indent; i ++)
519 putchar(' ');
520
521 printf("%s (", attr->name);
522 if (attr->num_values > 1)
523 printf("1setOf ");
524 printf("%s):", tags[attr->value_tag]);
525
526 switch (attr->value_tag)
527 {
528 case IPP_TAG_ENUM :
529 case IPP_TAG_INTEGER :
530 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
531 printf(" %d", val->integer);
532 putchar('\n');
533 break;
534
535 case IPP_TAG_BOOLEAN :
536 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
537 printf(" %s", val->boolean ? "true" : "false");
538 putchar('\n');
539 break;
540
541 case IPP_TAG_RANGE :
542 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
543 printf(" %d-%d", val->range.lower, val->range.upper);
544 putchar('\n');
545 break;
546
547 case IPP_TAG_DATE :
548 {
549 time_t vtime; /* Date/Time value */
550 struct tm *vdate; /* Date info */
551 char vstring[256]; /* Formatted time */
552
553 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
554 {
555 vtime = ippDateToTime(val->date);
556 vdate = localtime(&vtime);
557 strftime(vstring, sizeof(vstring), "%c", vdate);
558 printf(" (%s)", vstring);
559 }
560 }
561 putchar('\n');
562 break;
563
564 case IPP_TAG_RESOLUTION :
565 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
566 printf(" %dx%d%s", val->resolution.xres, val->resolution.yres,
567 val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpc");
568 putchar('\n');
569 break;
570
571 case IPP_TAG_STRING :
572 case IPP_TAG_TEXTLANG :
573 case IPP_TAG_NAMELANG :
574 case IPP_TAG_TEXT :
575 case IPP_TAG_NAME :
576 case IPP_TAG_KEYWORD :
577 case IPP_TAG_URI :
578 case IPP_TAG_URISCHEME :
579 case IPP_TAG_CHARSET :
580 case IPP_TAG_LANGUAGE :
581 case IPP_TAG_MIMETYPE :
582 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
583 printf(" \"%s\"", val->string.text);
584 putchar('\n');
585 break;
586
587 case IPP_TAG_BEGIN_COLLECTION :
588 putchar('\n');
589
590 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
591 {
592 if (i)
593 putchar('\n');
594 print_attributes(val->collection, indent + 4);
595 }
596 break;
597
598 default :
599 printf("UNKNOWN (%d values)\n", attr->num_values);
600 break;
601 }
602 }
603}
604
605
606/*
607 * 'read_cb()' - Read data from a buffer.
608 */
609
a4d04587 610ssize_t /* O - Number of bytes read */
ef416fc2 611read_cb(void *data, /* I - Data */
612 ipp_uchar_t *buffer, /* O - Buffer to read */
a4d04587 613 size_t bytes) /* I - Number of bytes to read */
ef416fc2 614{
615 int count; /* Number of bytes */
616
617
618 /*
619 * Copy bytes from the data buffer to the read buffer...
620 */
621
622 for (count = bytes; count > 0 && rpos < wused; count --, rpos ++)
623 *buffer++ = wbuffer[rpos];
624
625 /*
626 * Return the number of bytes read...
627 */
628
629 return (bytes - count);
630}
631
632
633/*
634 * 'write_cb()' - Write data into a buffer.
635 */
636
a4d04587 637ssize_t /* O - Number of bytes written */
ef416fc2 638write_cb(void *data, /* I - Data */
639 ipp_uchar_t *buffer, /* I - Buffer to write */
a4d04587 640 size_t bytes) /* I - Number of bytes to write */
ef416fc2 641{
642 int count; /* Number of bytes */
643
644
645 /*
646 * Loop until all bytes are written...
647 */
648
649 for (count = bytes; count > 0 && wused < sizeof(wbuffer); count --, wused ++)
650 wbuffer[wused] = *buffer++;
651
652 /*
653 * Return the number of bytes written...
654 */
655
656 return (bytes - count);
657}
658
659
660/*
f7deaa1a 661 * End of "$Id: testipp.c 5749 2006-07-18 18:36:09Z mike $".
ef416fc2 662 */