]>
git.ipfire.org Git - thirdparty/cups.git/blob - test/ipptest.c
2 * "$Id: ipptest.c 5090 2006-02-08 17:08:01Z mike $"
4 * IPP test command for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Parse options and do tests.
27 * do_tests() - Do tests as specified in the test file.
28 * get_tag() - Get an IPP value or group tag from a name...
29 * get_token() - Get a token from a file.
30 * print_attr() - Print an attribute on the screen.
31 * usage() - Show program usage.
35 * Include necessary headers...
40 #include <cups/string.h>
44 #include <cups/cups.h>
45 #include <cups/language.h>
52 int Verbosity
= 0; /* Show all attributes? */
59 int do_tests(const char *, const char *);
60 ipp_op_t
ippOpValue(const char *);
61 ipp_status_t
ippErrorValue(const char *);
62 ipp_tag_t
get_tag(const char *);
63 char *get_token(FILE *, char *, int, int *linenum
);
64 void print_attr(ipp_attribute_t
*);
65 void usage(const char *option
);
69 * 'main()' - Parse options and do tests.
72 int /* O - Exit status */
73 main(int argc
, /* I - Number of command-line arguments */
74 char *argv
[]) /* I - Command-line arguments */
76 int i
; /* Looping var */
77 int status
; /* Status of tests... */
78 const char *uri
; /* URI to use */
79 const char *testfile
; /* Test file to use */
85 * testipp URL testfile
92 for (i
= 1; i
< argc
; i
++)
94 if (argv
[i
][0] == '-')
96 if (!strcmp(argv
[i
], "-v"))
101 else if (!strncmp(argv
[i
], "ipp://", 6) ||
102 !strncmp(argv
[i
], "http://", 7) ||
103 !strncmp(argv
[i
], "https://", 8))
109 if (!testfile
&& uri
)
123 if (!do_tests(uri
, testfile
))
128 if (!uri
|| !testfile
)
140 * 'do_tests()' - Do tests as specified in the test file.
143 int /* 1 = success, 0 = failure */
144 do_tests(const char *uri
, /* I - URI to connect on */
145 const char *testfile
) /* I - Test file to use */
147 int i
; /* Looping var */
148 int linenum
; /* Current line number */
149 int version
; /* IPP version number to use */
150 http_t
*http
; /* HTTP connection to server */
151 char method
[HTTP_MAX_URI
], /* URI method */
152 userpass
[HTTP_MAX_URI
], /* username:password */
153 server
[HTTP_MAX_URI
], /* Server */
154 resource
[HTTP_MAX_URI
]; /* Resource path */
155 int port
; /* Port number */
156 FILE *fp
; /* Test file */
157 char token
[1024], /* Token from file */
158 *tokenptr
, /* Pointer into token */
159 temp
[1024], /* Temporary string */
160 *tempptr
; /* Pointer into temp string */
161 ipp_t
*request
; /* IPP request */
162 ipp_t
*response
; /* IPP response */
163 ipp_op_t op
; /* Operation */
164 ipp_tag_t group
; /* Current group */
165 ipp_tag_t value
; /* Current value type */
166 ipp_attribute_t
*attrptr
; /* Attribute pointer */
167 char attr
[128]; /* Attribute name */
168 int num_statuses
; /* Number of valid status codes */
169 ipp_status_t statuses
[100]; /* Valid status codes */
170 int num_expects
; /* Number of expected attributes */
171 char *expects
[100]; /* Expected attributes */
172 int num_displayed
; /* Number of displayed attributes */
173 char *displayed
[100]; /* Displayed attributes */
174 char name
[1024]; /* Name of test */
175 char filename
[1024]; /* Filename */
176 int pass
; /* Did we pass the test? */
177 int job_id
; /* Job ID from last operation */
178 int subscription_id
; /* Subscription ID from last operation */
182 * Open the test file...
185 if ((fp
= fopen(testfile
, "r")) == NULL
)
187 printf("Unable to open test file %s - %s\n", testfile
, strerror(errno
));
192 * Connect to the server...
195 httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, method
, sizeof(method
), userpass
,
196 sizeof(userpass
), server
, sizeof(server
), &port
, resource
,
198 if ((http
= httpConnect(server
, port
)) == NULL
)
200 printf("Unable to connect to %s on port %d - %s\n", server
, port
,
209 printf("\"%s\":\n", testfile
);
216 while (get_token(fp
, token
, sizeof(token
), &linenum
) != NULL
)
219 * Expect an open brace...
222 if (strcmp(token
, "{"))
224 printf("Unexpected token %s seen on line %d - aborting test!\n", token
,
231 * Initialize things...
234 httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, method
, sizeof(method
), userpass
,
235 sizeof(userpass
), server
, sizeof(server
), &port
, resource
,
240 group
= IPP_TAG_ZERO
;
241 value
= IPP_TAG_ZERO
;
247 strcpy(name
, testfile
);
248 if (strrchr(name
, '.') != NULL
)
249 *strrchr(name
, '.') = '\0';
252 * Parse until we see a close brace...
255 while (get_token(fp
, token
, sizeof(token
), &linenum
) != NULL
)
257 if (!strcmp(token
, "}"))
259 else if (!strcasecmp(token
, "NAME"))
265 get_token(fp
, name
, sizeof(name
), &linenum
);
267 else if (!strcasecmp(token
, "VERSION"))
270 * IPP version number for test...
273 get_token(fp
, temp
, sizeof(temp
), &linenum
);
274 sscanf(temp
, "%*d.%d", &version
);
276 else if (!strcasecmp(token
, "RESOURCE"))
282 get_token(fp
, resource
, sizeof(resource
), &linenum
);
284 else if (!strcasecmp(token
, "OPERATION"))
290 get_token(fp
, token
, sizeof(token
), &linenum
);
291 op
= ippOpValue(token
);
293 else if (!strcasecmp(token
, "GROUP"))
299 get_token(fp
, token
, sizeof(token
), &linenum
);
300 value
= get_tag(token
);
303 ippAddSeparator(request
);
307 else if (!strcasecmp(token
, "DELAY"))
310 * Delay before operation...
315 get_token(fp
, token
, sizeof(token
), &linenum
);
316 if ((delay
= atoi(token
)) > 0)
319 else if (!strcasecmp(token
, "ATTR"))
325 get_token(fp
, token
, sizeof(token
), &linenum
);
326 value
= get_tag(token
);
327 get_token(fp
, attr
, sizeof(attr
), &linenum
);
328 get_token(fp
, temp
, sizeof(temp
), &linenum
);
330 token
[sizeof(token
) - 1] = '\0';
332 for (tempptr
= temp
, tokenptr
= token
;
333 *tempptr
&& tokenptr
< (token
+ sizeof(token
) - 1);)
337 * Substitute a string/number...
340 if (!strncasecmp(tempptr
+ 1, "uri", 3))
342 strlcpy(tokenptr
, uri
, sizeof(token
) - (tokenptr
- token
));
345 else if (!strncasecmp(tempptr
+ 1, "method", 6))
347 strlcpy(tokenptr
, method
, sizeof(token
) - (tokenptr
- token
));
350 else if (!strncasecmp(tempptr
+ 1, "username", 8))
352 strlcpy(tokenptr
, userpass
, sizeof(token
) - (tokenptr
- token
));
355 else if (!strncasecmp(tempptr
+ 1, "hostname", 8))
357 strlcpy(tokenptr
, server
, sizeof(token
) - (tokenptr
- token
));
360 else if (!strncasecmp(tempptr
+ 1, "port", 4))
362 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
366 else if (!strncasecmp(tempptr
+ 1, "resource", 8))
368 strlcpy(tokenptr
, resource
, sizeof(token
) - (tokenptr
- token
));
371 else if (!strncasecmp(tempptr
+ 1, "job-id", 6))
373 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
377 else if (!strncasecmp(tempptr
+ 1, "notify-subscription-id", 22))
379 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
380 "%d", subscription_id
);
383 else if (!strncasecmp(tempptr
+ 1, "user", 4))
385 strlcpy(tokenptr
, cupsUser(), sizeof(token
) - (tokenptr
- token
));
390 *tokenptr
++ = *tempptr
++;
394 tokenptr
+= strlen(tokenptr
);
398 *tokenptr
++ = *tempptr
++;
404 case IPP_TAG_BOOLEAN
:
405 if (!strcasecmp(token
, "true"))
406 ippAddBoolean(request
, group
, attr
, 1);
408 ippAddBoolean(request
, group
, attr
, atoi(token
));
411 case IPP_TAG_INTEGER
:
413 ippAddInteger(request
, group
, value
, attr
, atoi(token
));
416 case IPP_TAG_RESOLUTION
:
417 puts(" ERROR: resolution tag not yet supported!");
421 puts(" ERROR: range tag not yet supported!");
425 if (!strchr(token
, ','))
426 ippAddString(request
, group
, value
, attr
, NULL
, token
);
430 * Multiple string values...
433 int num_values
; /* Number of values */
434 char *values
[100], /* Values */
435 *ptr
; /* Pointer to next value */
441 for (ptr
= strchr(token
, ','); ptr
; ptr
= strchr(ptr
, ','))
444 values
[num_values
] = ptr
;
448 ippAddStrings(request
, group
, value
, attr
, num_values
,
449 NULL
, (const char **)values
);
454 else if (!strcasecmp(token
, "FILE"))
460 get_token(fp
, filename
, sizeof(filename
), &linenum
);
462 else if (!strcasecmp(token
, "STATUS") &&
463 num_statuses
< (int)(sizeof(statuses
) / sizeof(statuses
[0])))
469 get_token(fp
, token
, sizeof(token
), &linenum
);
470 statuses
[num_statuses
] = ippErrorValue(token
);
473 else if (!strcasecmp(token
, "EXPECT") &&
474 num_expects
< (int)(sizeof(expects
) / sizeof(expects
[0])))
477 * Expected attributes...
480 get_token(fp
, token
, sizeof(token
), &linenum
);
481 expects
[num_expects
] = strdup(token
);
484 else if (!strcasecmp(token
, "DISPLAY") &&
485 num_displayed
< (int)(sizeof(displayed
) / sizeof(displayed
[0])))
488 * Display attributes...
491 get_token(fp
, token
, sizeof(token
), &linenum
);
492 displayed
[num_displayed
] = strdup(token
);
497 printf("Unexpected token %s seen on line %d - aborting test!\n", token
,
506 * Submit the IPP request...
509 request
->request
.op
.version
[1] = version
;
510 request
->request
.op
.operation_id
= op
;
511 request
->request
.op
.request_id
= 1;
515 printf("%s:\n", ippOpString(op
));
517 for (attrptr
= request
->attrs
; attrptr
; attrptr
= attrptr
->next
)
521 printf(" %-60.60s [", name
);
525 response
= cupsDoFileRequest(http
, request
, resource
, filename
);
527 response
= cupsDoRequest(http
, request
, resource
);
529 if (response
== NULL
)
533 curtime
= time(NULL
);
536 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
537 cupsLastErrorString(), ctime(&curtime
));
542 if ((attrptr
= ippFindAttribute(response
, "job-id",
543 IPP_TAG_INTEGER
)) != NULL
)
544 job_id
= attrptr
->values
[0].integer
;
546 if ((attrptr
= ippFindAttribute(response
, "notify-subscription-id",
547 IPP_TAG_INTEGER
)) != NULL
)
548 subscription_id
= attrptr
->values
[0].integer
;
550 for (i
= 0; i
< num_statuses
; i
++)
551 if (response
->request
.status
.status_code
== statuses
[i
])
554 if (i
== num_statuses
&& num_statuses
> 0)
558 for (i
= 0; i
< num_expects
; i
++)
559 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
569 printf(" RECEIVED: %lu bytes in response\n",
570 (unsigned long)ippLength(response
));
574 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
577 else if (num_displayed
> 0)
579 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
582 for (i
= 0; i
< num_displayed
; i
++)
583 if (!strcmp(displayed
[i
], attrptr
->name
))
594 printf(" RECEIVED: %lu bytes in response\n",
595 (unsigned long)ippLength(response
));
597 for (i
= 0; i
< num_statuses
; i
++)
598 if (response
->request
.status
.status_code
== statuses
[i
])
601 if (i
== num_statuses
&& num_statuses
> 0)
604 printf(" status-code = %04x (%s)\n",
605 cupsLastError(), cupsLastErrorString());
607 for (i
= 0; i
< num_expects
; i
++)
608 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
609 printf(" EXPECTED: %s\n", expects
[i
]);
611 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
618 for (i
= 0; i
< num_expects
; i
++)
633 * 'get_tag()' - Get an IPP value or group tag from a name...
636 ipp_tag_t
/* O - Value/group tag */
637 get_tag(const char *name
) /* I - Name of value/group tag */
639 int i
; /* Looping var */
640 static const char * const names
[] =
641 { /* Value/group tag names */
643 "operation", /* 0x01 */
646 "printer", /* 0x04 */
647 "unsupported-group", /* 0x05 */
648 "subscription", /* 0x06 */
649 "event-notification", /* 0x07 */
650 "", "", "", "", "", "", "", "",
651 "unsupported-value", /* 0x10 */
652 "default", /* 0x11 */
653 "unknown", /* 0x12 */
654 "novalue", /* 0x13 */
656 "notsettable", /* 0x15 */
657 "deleteattr", /* 0x16 */
658 "anyvalue", /* 0x17 */
659 "", "", "", "", "", "", "", "", "",
660 "integer", /* 0x21 */
661 "boolean", /* 0x22 */
663 "", "", "", "", "", "", "", "", "", "", "", "",
666 "resolution", /* 0x32 */
668 "collection", /* 0x34 */
669 "textlang", /* 0x35 */
670 "namelang", /* 0x36 */
671 "", "", "", "", "", "", "", "", "", "",
675 "keyword", /* 0x44 */
677 "urischeme", /* 0x46 */
678 "charset", /* 0x47 */
679 "language", /* 0x48 */
680 "mimetype" /* 0x49 */
684 for (i
= 0; i
< (sizeof(names
) / sizeof(names
[0])); i
++)
685 if (!strcasecmp(name
, names
[i
]))
686 return ((ipp_tag_t
)i
);
688 return (IPP_TAG_ZERO
);
693 * 'get_token()' - Get a token from a file.
696 char * /* O - Token from file or NULL on EOF */
697 get_token(FILE *fp
, /* I - File to read from */
698 char *buf
, /* I - Buffer to read into */
699 int buflen
, /* I - Length of buffer */
700 int *linenum
) /* IO - Current line number */
702 int ch
, /* Character from file */
703 quote
; /* Quoting character */
704 char *bufptr
, /* Pointer into buffer */
705 *bufend
; /* End of buffer */
714 while (isspace(ch
= getc(fp
)))
726 else if (ch
== '\'' || ch
== '\"')
734 bufend
= buf
+ buflen
- 1;
736 while ((ch
= getc(fp
)) != EOF
)
739 else if (bufptr
< bufend
)
751 while ((ch
= getc(fp
)) != EOF
)
760 * Whitespace delimited text...
766 bufend
= buf
+ buflen
- 1;
768 while ((ch
= getc(fp
)) != EOF
)
769 if (isspace(ch
) || ch
== '#')
771 else if (bufptr
< bufend
)
785 * 'print_attr()' - Print an attribute on the screen.
789 print_attr(ipp_attribute_t
*attr
) /* I - Attribute to print */
791 int i
; /* Looping var */
794 if (attr
->name
== NULL
)
796 puts(" -- separator --");
800 printf(" %s = ", attr
->name
);
802 switch (attr
->value_tag
)
804 case IPP_TAG_INTEGER
:
806 for (i
= 0; i
< attr
->num_values
; i
++)
807 printf("%d ", attr
->values
[i
].integer
);
810 case IPP_TAG_BOOLEAN
:
811 for (i
= 0; i
< attr
->num_values
; i
++)
812 if (attr
->values
[i
].boolean
)
818 case IPP_TAG_NOVALUE
:
823 for (i
= 0; i
< attr
->num_values
; i
++)
824 printf("%d-%d ", attr
->values
[i
].range
.lower
,
825 attr
->values
[i
].range
.upper
);
828 case IPP_TAG_RESOLUTION
:
829 for (i
= 0; i
< attr
->num_values
; i
++)
830 printf("%dx%d%s ", attr
->values
[i
].resolution
.xres
,
831 attr
->values
[i
].resolution
.yres
,
832 attr
->values
[i
].resolution
.units
== IPP_RES_PER_INCH
?
836 case IPP_TAG_STRING
:
839 case IPP_TAG_KEYWORD
:
840 case IPP_TAG_CHARSET
:
842 case IPP_TAG_MIMETYPE
:
843 case IPP_TAG_LANGUAGE
:
844 for (i
= 0; i
< attr
->num_values
; i
++)
845 printf("\"%s\" ", attr
->values
[i
].string
.text
);
848 case IPP_TAG_TEXTLANG
:
849 case IPP_TAG_NAMELANG
:
850 for (i
= 0; i
< attr
->num_values
; i
++)
851 printf("\"%s\",%s ", attr
->values
[i
].string
.text
,
852 attr
->values
[i
].string
.charset
);
856 break; /* anti-compiler-warning-code */
864 * 'usage()' - Show program usage.
868 usage(const char *option
) /* I - Option string or NULL */
871 fprintf(stderr
, "ipptest: Unknown option \"%s\"!\n", option
);
873 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr
);
874 fputs("Options:\n", stderr
);
876 fputs("-v Show all attributes in response, even on success.\n", stderr
);
883 * End of "$Id: ipptest.c 5090 2006-02-08 17:08:01Z mike $".