]>
git.ipfire.org Git - thirdparty/cups.git/blob - test/ipptest.c
2 * "$Id: ipptest.c 5037 2006-02-01 15:19:59Z 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;
514 for (attrptr
= request
->attrs
; attrptr
; attrptr
= attrptr
->next
)
518 printf(" %-60.60s [", name
);
522 response
= cupsDoFileRequest(http
, request
, resource
, filename
);
524 response
= cupsDoRequest(http
, request
, resource
);
526 if (response
== NULL
)
530 curtime
= time(NULL
);
533 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
534 ippErrorString(cupsLastError()), ctime(&curtime
));
539 if ((attrptr
= ippFindAttribute(response
, "job-id",
540 IPP_TAG_INTEGER
)) != NULL
)
541 job_id
= attrptr
->values
[0].integer
;
543 if ((attrptr
= ippFindAttribute(response
, "notify-subscription-id",
544 IPP_TAG_INTEGER
)) != NULL
)
545 subscription_id
= attrptr
->values
[0].integer
;
547 for (i
= 0; i
< num_statuses
; i
++)
548 if (response
->request
.status
.status_code
== statuses
[i
])
551 if (i
== num_statuses
&& num_statuses
> 0)
555 for (i
= 0; i
< num_expects
; i
++)
556 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
566 printf(" RECEIVED: %lu bytes in response\n",
567 (unsigned long)ippLength(response
));
571 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
574 else if (num_displayed
> 0)
576 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
579 for (i
= 0; i
< num_displayed
; i
++)
580 if (!strcmp(displayed
[i
], attrptr
->name
))
591 printf(" RECEIVED: %lu bytes in response\n",
592 (unsigned long)ippLength(response
));
594 for (i
= 0; i
< num_statuses
; i
++)
595 if (response
->request
.status
.status_code
== statuses
[i
])
598 if (i
== num_statuses
&& num_statuses
> 0)
601 printf(" status-code = %04x (%s)\n",
602 response
->request
.status
.status_code
,
603 ippErrorString(response
->request
.status
.status_code
));
605 for (i
= 0; i
< num_expects
; i
++)
606 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
607 printf(" EXPECTED: %s\n", expects
[i
]);
609 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
616 for (i
= 0; i
< num_expects
; i
++)
631 * 'get_tag()' - Get an IPP value or group tag from a name...
634 ipp_tag_t
/* O - Value/group tag */
635 get_tag(const char *name
) /* I - Name of value/group tag */
637 int i
; /* Looping var */
638 static const char * const names
[] =
639 { /* Value/group tag names */
640 "zero", "operation", "job", "end", "printer",
641 "unsupported-group", "subscription", "event-notification",
643 "", "", "", "unsupported-value", "default",
644 "unknown", "novalue", "", "notsettable",
645 "deleteattr", "anyvalue", "", "", "", "", "", "",
646 "", "", "", "integer", "boolean", "enum", "", "",
647 "", "", "", "", "", "", "", "", "", "", "string",
648 "date", "resolution", "range", "collection",
649 "textlang", "namelang", "", "", "", "", "", "", "",
650 "", "", "", "text", "name", "", "keyword", "uri",
651 "urischeme", "charset", "language", "mimetype"
655 for (i
= 0; i
< (sizeof(names
) / sizeof(names
[0])); i
++)
656 if (!strcasecmp(name
, names
[i
]))
657 return ((ipp_tag_t
)i
);
659 return (IPP_TAG_ZERO
);
664 * 'get_token()' - Get a token from a file.
667 char * /* O - Token from file or NULL on EOF */
668 get_token(FILE *fp
, /* I - File to read from */
669 char *buf
, /* I - Buffer to read into */
670 int buflen
, /* I - Length of buffer */
671 int *linenum
) /* IO - Current line number */
673 int ch
, /* Character from file */
674 quote
; /* Quoting character */
675 char *bufptr
, /* Pointer into buffer */
676 *bufend
; /* End of buffer */
685 while (isspace(ch
= getc(fp
)))
697 else if (ch
== '\'' || ch
== '\"')
705 bufend
= buf
+ buflen
- 1;
707 while ((ch
= getc(fp
)) != EOF
)
710 else if (bufptr
< bufend
)
722 while ((ch
= getc(fp
)) != EOF
)
731 * Whitespace delimited text...
737 bufend
= buf
+ buflen
- 1;
739 while ((ch
= getc(fp
)) != EOF
)
740 if (isspace(ch
) || ch
== '#')
742 else if (bufptr
< bufend
)
756 * 'print_attr()' - Print an attribute on the screen.
760 print_attr(ipp_attribute_t
*attr
) /* I - Attribute to print */
762 int i
; /* Looping var */
765 if (attr
->name
== NULL
)
767 puts(" -- separator --");
771 printf(" %s = ", attr
->name
);
773 switch (attr
->value_tag
)
775 case IPP_TAG_INTEGER
:
777 for (i
= 0; i
< attr
->num_values
; i
++)
778 printf("%d ", attr
->values
[i
].integer
);
781 case IPP_TAG_BOOLEAN
:
782 for (i
= 0; i
< attr
->num_values
; i
++)
783 if (attr
->values
[i
].boolean
)
789 case IPP_TAG_NOVALUE
:
794 for (i
= 0; i
< attr
->num_values
; i
++)
795 printf("%d-%d ", attr
->values
[i
].range
.lower
,
796 attr
->values
[i
].range
.upper
);
799 case IPP_TAG_RESOLUTION
:
800 for (i
= 0; i
< attr
->num_values
; i
++)
801 printf("%dx%d%s ", attr
->values
[i
].resolution
.xres
,
802 attr
->values
[i
].resolution
.yres
,
803 attr
->values
[i
].resolution
.units
== IPP_RES_PER_INCH
?
807 case IPP_TAG_STRING
:
810 case IPP_TAG_KEYWORD
:
811 case IPP_TAG_CHARSET
:
813 case IPP_TAG_MIMETYPE
:
814 case IPP_TAG_LANGUAGE
:
815 for (i
= 0; i
< attr
->num_values
; i
++)
816 printf("\"%s\" ", attr
->values
[i
].string
.text
);
819 case IPP_TAG_TEXTLANG
:
820 case IPP_TAG_NAMELANG
:
821 for (i
= 0; i
< attr
->num_values
; i
++)
822 printf("\"%s\",%s ", attr
->values
[i
].string
.text
,
823 attr
->values
[i
].string
.charset
);
827 break; /* anti-compiler-warning-code */
835 * 'usage()' - Show program usage.
839 usage(const char *option
) /* I - Option string or NULL */
842 fprintf(stderr
, "ipptest: Unknown option \"%s\"!\n", option
);
844 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr
);
845 fputs("Options:\n", stderr
);
847 fputs("-v Show all attributes in response, even on success.\n", stderr
);
854 * End of "$Id: ipptest.c 5037 2006-02-01 15:19:59Z mike $".