]>
git.ipfire.org Git - thirdparty/cups.git/blob - test/ipptest.c
2 * "$Id: ipptest.c 6649 2007-07-11 21:46:42Z mike $"
4 * IPP test command for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
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/".
17 * main() - Parse options and do tests.
18 * do_tests() - Do tests as specified in the test file.
19 * get_tag() - Get an IPP value or group tag from a name...
20 * get_token() - Get a token from a file.
21 * print_attr() - Print an attribute on the screen.
22 * usage() - Show program usage.
26 * Include necessary headers...
31 #include <cups/string.h>
35 #include <cups/cups.h>
36 #include <cups/language.h>
43 int Verbosity
= 0; /* Show all attributes? */
44 const char * const TagNames
[] =
45 { /* Value/group tag names */
47 "operation", /* 0x01 */
51 "unsupported-group", /* 0x05 */
52 "subscription", /* 0x06 */
53 "event-notification", /* 0x07 */
54 "", "", "", "", "", "", "", "",
55 "unsupported-value", /* 0x10 */
60 "notsettable", /* 0x15 */
61 "deleteattr", /* 0x16 */
62 "anyvalue", /* 0x17 */
63 "", "", "", "", "", "", "", "", "",
67 "", "", "", "", "", "", "", "", "", "", "", "",
70 "resolution", /* 0x32 */
72 "collection", /* 0x34 */
73 "textlang", /* 0x35 */
74 "namelang", /* 0x36 */
75 "", "", "", "", "", "", "", "", "", "",
81 "urischeme", /* 0x46 */
83 "language", /* 0x48 */
94 int do_tests(const char *, const char *);
95 ipp_op_t
ippOpValue(const char *);
96 ipp_status_t
ippErrorValue(const char *);
97 ipp_tag_t
get_tag(const char *);
98 const char *get_tag_string(ipp_tag_t tag
);
99 char *get_token(FILE *, char *, int, int *linenum
);
100 void print_attr(ipp_attribute_t
*);
101 void usage(const char *option
);
105 * 'main()' - Parse options and do tests.
108 int /* O - Exit status */
109 main(int argc
, /* I - Number of command-line arguments */
110 char *argv
[]) /* I - Command-line arguments */
112 int i
; /* Looping var */
113 int status
; /* Status of tests... */
114 const char *uri
; /* URI to use */
115 const char *testfile
; /* Test file to use */
116 int interval
; /* Test interval */
122 * testipp URL testfile
130 for (i
= 1; i
< argc
; i
++)
132 if (argv
[i
][0] == '-')
134 if (!strcmp(argv
[i
], "-v"))
136 else if (!strcmp(argv
[i
], "-d"))
145 else if (!strcmp(argv
[i
], "-i"))
152 interval
= atoi(argv
[i
]);
157 else if (!strncmp(argv
[i
], "ipp://", 6) ||
158 !strncmp(argv
[i
], "http://", 7) ||
159 !strncmp(argv
[i
], "https://", 8))
165 if (!testfile
&& uri
)
179 if (!do_tests(uri
, testfile
))
184 if (!uri
|| !testfile
)
188 * Loop if the interval is set...
196 do_tests(uri
, testfile
);
209 * 'do_tests()' - Do tests as specified in the test file.
212 int /* 1 = success, 0 = failure */
213 do_tests(const char *uri
, /* I - URI to connect on */
214 const char *testfile
) /* I - Test file to use */
216 int i
; /* Looping var */
217 int linenum
; /* Current line number */
218 int version
; /* IPP version number to use */
219 http_t
*http
; /* HTTP connection to server */
220 char method
[HTTP_MAX_URI
], /* URI method */
221 userpass
[HTTP_MAX_URI
], /* username:password */
222 server
[HTTP_MAX_URI
], /* Server */
223 resource
[HTTP_MAX_URI
]; /* Resource path */
224 int port
; /* Port number */
225 FILE *fp
; /* Test file */
226 char token
[1024], /* Token from file */
227 *tokenptr
, /* Pointer into token */
228 temp
[1024], /* Temporary string */
229 *tempptr
; /* Pointer into temp string */
230 ipp_t
*request
; /* IPP request */
231 ipp_t
*response
; /* IPP response */
232 ipp_op_t op
; /* Operation */
233 ipp_tag_t group
; /* Current group */
234 ipp_tag_t value
; /* Current value type */
235 ipp_attribute_t
*attrptr
; /* Attribute pointer */
236 char attr
[128]; /* Attribute name */
237 int num_statuses
; /* Number of valid status codes */
238 ipp_status_t statuses
[100]; /* Valid status codes */
239 int num_expects
; /* Number of expected attributes */
240 char *expects
[100]; /* Expected attributes */
241 int num_displayed
; /* Number of displayed attributes */
242 char *displayed
[100]; /* Displayed attributes */
243 char name
[1024]; /* Name of test */
244 char filename
[1024]; /* Filename */
245 int pass
; /* Did we pass the test? */
246 int job_id
; /* Job ID from last operation */
247 int subscription_id
; /* Subscription ID from last operation */
251 * Open the test file...
254 if ((fp
= fopen(testfile
, "r")) == NULL
)
256 printf("Unable to open test file %s - %s\n", testfile
, strerror(errno
));
261 * Connect to the server...
264 httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, method
, sizeof(method
), userpass
,
265 sizeof(userpass
), server
, sizeof(server
), &port
, resource
,
267 if ((http
= httpConnect(server
, port
)) == NULL
)
269 printf("Unable to connect to %s on port %d - %s\n", server
, port
,
279 printf("\"%s\":\n", testfile
);
286 while (get_token(fp
, token
, sizeof(token
), &linenum
) != NULL
)
289 * Expect an open brace...
292 if (strcmp(token
, "{"))
294 printf("Unexpected token %s seen on line %d - aborting test!\n", token
,
301 * Initialize things...
304 httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, method
, sizeof(method
), userpass
,
305 sizeof(userpass
), server
, sizeof(server
), &port
, resource
,
310 group
= IPP_TAG_ZERO
;
311 value
= IPP_TAG_ZERO
;
317 strcpy(name
, testfile
);
318 if (strrchr(name
, '.') != NULL
)
319 *strrchr(name
, '.') = '\0';
322 * Parse until we see a close brace...
325 while (get_token(fp
, token
, sizeof(token
), &linenum
) != NULL
)
327 if (!strcmp(token
, "}"))
329 else if (!strcasecmp(token
, "NAME"))
335 get_token(fp
, name
, sizeof(name
), &linenum
);
337 else if (!strcasecmp(token
, "VERSION"))
340 * IPP version number for test...
343 get_token(fp
, temp
, sizeof(temp
), &linenum
);
344 sscanf(temp
, "%*d.%d", &version
);
346 else if (!strcasecmp(token
, "RESOURCE"))
352 get_token(fp
, resource
, sizeof(resource
), &linenum
);
354 else if (!strcasecmp(token
, "OPERATION"))
360 get_token(fp
, token
, sizeof(token
), &linenum
);
361 op
= ippOpValue(token
);
363 else if (!strcasecmp(token
, "GROUP"))
369 get_token(fp
, token
, sizeof(token
), &linenum
);
370 value
= get_tag(token
);
373 ippAddSeparator(request
);
377 else if (!strcasecmp(token
, "DELAY"))
380 * Delay before operation...
385 get_token(fp
, token
, sizeof(token
), &linenum
);
386 if ((delay
= atoi(token
)) > 0)
389 else if (!strcasecmp(token
, "ATTR"))
395 get_token(fp
, token
, sizeof(token
), &linenum
);
396 value
= get_tag(token
);
397 get_token(fp
, attr
, sizeof(attr
), &linenum
);
398 get_token(fp
, temp
, sizeof(temp
), &linenum
);
400 token
[sizeof(token
) - 1] = '\0';
402 for (tempptr
= temp
, tokenptr
= token
;
403 *tempptr
&& tokenptr
< (token
+ sizeof(token
) - 1);)
407 * Substitute a string/number...
410 if (!strncasecmp(tempptr
+ 1, "uri", 3))
412 strlcpy(tokenptr
, uri
, sizeof(token
) - (tokenptr
- token
));
415 else if (!strncasecmp(tempptr
+ 1, "method", 6))
417 strlcpy(tokenptr
, method
, sizeof(token
) - (tokenptr
- token
));
420 else if (!strncasecmp(tempptr
+ 1, "username", 8))
422 strlcpy(tokenptr
, userpass
, sizeof(token
) - (tokenptr
- token
));
425 else if (!strncasecmp(tempptr
+ 1, "hostname", 8))
427 strlcpy(tokenptr
, server
, sizeof(token
) - (tokenptr
- token
));
430 else if (!strncasecmp(tempptr
+ 1, "port", 4))
432 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
436 else if (!strncasecmp(tempptr
+ 1, "resource", 8))
438 strlcpy(tokenptr
, resource
, sizeof(token
) - (tokenptr
- token
));
441 else if (!strncasecmp(tempptr
+ 1, "job-id", 6))
443 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
447 else if (!strncasecmp(tempptr
+ 1, "notify-subscription-id", 22))
449 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
450 "%d", subscription_id
);
453 else if (!strncasecmp(tempptr
+ 1, "user", 4))
455 strlcpy(tokenptr
, cupsUser(), sizeof(token
) - (tokenptr
- token
));
458 else if (!strncasecmp(tempptr
+ 1, "ENV[", 4))
460 char *end
; /* End of $ENV[name] */
463 if ((end
= strchr(tempptr
+ 5, ']')) != NULL
)
467 getenv(tempptr
+ 5) ? getenv(tempptr
+ 5) : tempptr
+ 5,
468 sizeof(token
) - (tokenptr
- token
));
473 *tokenptr
++ = *tempptr
++;
479 *tokenptr
++ = *tempptr
++;
483 tokenptr
+= strlen(tokenptr
);
487 *tokenptr
++ = *tempptr
++;
493 case IPP_TAG_BOOLEAN
:
494 if (!strcasecmp(token
, "true"))
495 ippAddBoolean(request
, group
, attr
, 1);
497 ippAddBoolean(request
, group
, attr
, atoi(token
));
500 case IPP_TAG_INTEGER
:
502 ippAddInteger(request
, group
, value
, attr
, atoi(token
));
505 case IPP_TAG_RESOLUTION
:
506 puts(" ERROR: resolution tag not yet supported!");
510 puts(" ERROR: range tag not yet supported!");
514 if (!strchr(token
, ','))
515 ippAddString(request
, group
, value
, attr
, NULL
, token
);
519 * Multiple string values...
522 int num_values
; /* Number of values */
523 char *values
[100], /* Values */
524 *ptr
; /* Pointer to next value */
530 for (ptr
= strchr(token
, ','); ptr
; ptr
= strchr(ptr
, ','))
533 values
[num_values
] = ptr
;
537 ippAddStrings(request
, group
, value
, attr
, num_values
,
538 NULL
, (const char **)values
);
543 else if (!strcasecmp(token
, "FILE"))
549 get_token(fp
, filename
, sizeof(filename
), &linenum
);
551 else if (!strcasecmp(token
, "STATUS") &&
552 num_statuses
< (int)(sizeof(statuses
) / sizeof(statuses
[0])))
558 get_token(fp
, token
, sizeof(token
), &linenum
);
559 statuses
[num_statuses
] = ippErrorValue(token
);
562 else if (!strcasecmp(token
, "EXPECT") &&
563 num_expects
< (int)(sizeof(expects
) / sizeof(expects
[0])))
566 * Expected attributes...
569 get_token(fp
, token
, sizeof(token
), &linenum
);
570 expects
[num_expects
] = strdup(token
);
573 else if (!strcasecmp(token
, "DISPLAY") &&
574 num_displayed
< (int)(sizeof(displayed
) / sizeof(displayed
[0])))
577 * Display attributes...
580 get_token(fp
, token
, sizeof(token
), &linenum
);
581 displayed
[num_displayed
] = strdup(token
);
586 printf("Unexpected token %s seen on line %d - aborting test!\n", token
,
595 * Submit the IPP request...
598 request
->request
.op
.version
[1] = version
;
599 request
->request
.op
.operation_id
= op
;
600 request
->request
.op
.request_id
= 1;
604 printf("%s:\n", ippOpString(op
));
606 for (attrptr
= request
->attrs
; attrptr
; attrptr
= attrptr
->next
)
610 printf(" %-60.60s [", name
);
614 response
= cupsDoFileRequest(http
, request
, resource
, filename
);
616 response
= cupsDoIORequest(http
, request
, resource
, -1,
619 if (response
== NULL
)
623 curtime
= time(NULL
);
626 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
627 cupsLastErrorString(), ctime(&curtime
));
632 if ((attrptr
= ippFindAttribute(response
, "job-id",
633 IPP_TAG_INTEGER
)) != NULL
)
634 job_id
= attrptr
->values
[0].integer
;
636 if ((attrptr
= ippFindAttribute(response
, "notify-subscription-id",
637 IPP_TAG_INTEGER
)) != NULL
)
638 subscription_id
= attrptr
->values
[0].integer
;
640 for (i
= 0; i
< num_statuses
; i
++)
641 if (response
->request
.status
.status_code
== statuses
[i
])
644 if (i
== num_statuses
&& num_statuses
> 0)
648 for (i
= 0; i
< num_expects
; i
++)
649 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
659 printf(" RECEIVED: %lu bytes in response\n",
660 (unsigned long)ippLength(response
));
664 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
667 else if (num_displayed
> 0)
669 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
672 for (i
= 0; i
< num_displayed
; i
++)
673 if (!strcmp(displayed
[i
], attrptr
->name
))
684 printf(" RECEIVED: %lu bytes in response\n",
685 (unsigned long)ippLength(response
));
687 for (i
= 0; i
< num_statuses
; i
++)
688 if (response
->request
.status
.status_code
== statuses
[i
])
691 if (i
== num_statuses
&& num_statuses
> 0)
694 printf(" status-code = %04x (%s)\n",
695 cupsLastError(), ippErrorString(cupsLastError()));
697 for (i
= 0; i
< num_expects
; i
++)
698 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
699 printf(" EXPECTED: %s\n", expects
[i
]);
701 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
708 for (i
= 0; i
< num_expects
; i
++)
723 * 'get_tag()' - Get an IPP value or group tag from a name...
726 ipp_tag_t
/* O - Value/group tag */
727 get_tag(const char *name
) /* I - Name of value/group tag */
729 int i
; /* Looping var */
732 for (i
= 0; i
< (sizeof(TagNames
) / sizeof(TagNames
[0])); i
++)
733 if (!strcasecmp(name
, TagNames
[i
]))
734 return ((ipp_tag_t
)i
);
736 return (IPP_TAG_ZERO
);
741 * 'get_tag_string()' - Get the string associated with a tag.
744 const char * /* O - Tag name string */
745 get_tag_string(ipp_tag_t tag
) /* I - IPP tag */
747 if (tag
< (ipp_tag_t
)(sizeof(TagNames
) / sizeof(TagNames
[0])))
748 return (TagNames
[tag
]);
755 * 'get_token()' - Get a token from a file.
758 char * /* O - Token from file or NULL on EOF */
759 get_token(FILE *fp
, /* I - File to read from */
760 char *buf
, /* I - Buffer to read into */
761 int buflen
, /* I - Length of buffer */
762 int *linenum
) /* IO - Current line number */
764 int ch
, /* Character from file */
765 quote
; /* Quoting character */
766 char *bufptr
, /* Pointer into buffer */
767 *bufend
; /* End of buffer */
776 while (isspace(ch
= getc(fp
)))
788 else if (ch
== '\'' || ch
== '\"')
796 bufend
= buf
+ buflen
- 1;
798 while ((ch
= getc(fp
)) != EOF
)
801 else if (bufptr
< bufend
)
813 while ((ch
= getc(fp
)) != EOF
)
822 * Whitespace delimited text...
828 bufend
= buf
+ buflen
- 1;
830 while ((ch
= getc(fp
)) != EOF
)
831 if (isspace(ch
) || ch
== '#')
833 else if (bufptr
< bufend
)
847 * 'print_attr()' - Print an attribute on the screen.
851 print_attr(ipp_attribute_t
*attr
) /* I - Attribute to print */
853 int i
; /* Looping var */
856 if (attr
->name
== NULL
)
858 puts(" -- separator --");
862 printf(" %s (%s%s) = ", attr
->name
,
863 attr
->num_values
> 1 ? "1setOf " : "",
864 get_tag_string(attr
->value_tag
));
866 switch (attr
->value_tag
)
868 case IPP_TAG_INTEGER
:
870 for (i
= 0; i
< attr
->num_values
; i
++)
871 printf("%d ", attr
->values
[i
].integer
);
874 case IPP_TAG_BOOLEAN
:
875 for (i
= 0; i
< attr
->num_values
; i
++)
876 if (attr
->values
[i
].boolean
)
882 case IPP_TAG_NOVALUE
:
887 for (i
= 0; i
< attr
->num_values
; i
++)
888 printf("%d-%d ", attr
->values
[i
].range
.lower
,
889 attr
->values
[i
].range
.upper
);
892 case IPP_TAG_RESOLUTION
:
893 for (i
= 0; i
< attr
->num_values
; i
++)
894 printf("%dx%d%s ", attr
->values
[i
].resolution
.xres
,
895 attr
->values
[i
].resolution
.yres
,
896 attr
->values
[i
].resolution
.units
== IPP_RES_PER_INCH
?
900 case IPP_TAG_STRING
:
903 case IPP_TAG_KEYWORD
:
904 case IPP_TAG_CHARSET
:
906 case IPP_TAG_MIMETYPE
:
907 case IPP_TAG_LANGUAGE
:
908 for (i
= 0; i
< attr
->num_values
; i
++)
909 printf("\"%s\" ", attr
->values
[i
].string
.text
);
912 case IPP_TAG_TEXTLANG
:
913 case IPP_TAG_NAMELANG
:
914 for (i
= 0; i
< attr
->num_values
; i
++)
915 printf("\"%s\",%s ", attr
->values
[i
].string
.text
,
916 attr
->values
[i
].string
.charset
);
920 break; /* anti-compiler-warning-code */
928 * 'usage()' - Show program usage.
932 usage(const char *option
) /* I - Option string or NULL */
935 fprintf(stderr
, "ipptest: Unknown option \"%s\"!\n", option
);
937 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr
);
938 fputs("Options:\n", stderr
);
940 fputs("-i N Repeat the last test file once every N seconds.\n", stderr
);
941 fputs("-v Show all attributes in response, even on success.\n", stderr
);
948 * End of "$Id: ipptest.c 6649 2007-07-11 21:46:42Z mike $".