]>
git.ipfire.org Git - thirdparty/cups.git/blob - test/ipptest.c
2 * "$Id: ipptest.c 7847 2008-08-19 04:22:14Z mike $"
4 * IPP test command for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2009 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_token() - Get a token from a file.
20 * print_attr() - Print an attribute on the screen.
21 * usage() - Show program usage.
25 * Include necessary headers...
30 #include <cups/string.h>
34 #include <cups/cups.h>
35 #include <cups/language.h>
42 int Verbosity
= 0; /* Show all attributes? */
49 int do_tests(const char *, const char *);
50 ipp_op_t
ippOpValue(const char *);
51 ipp_status_t
ippErrorValue(const char *);
52 char *get_token(FILE *, char *, int, int *linenum
);
53 void print_attr(ipp_attribute_t
*);
54 void print_col(ipp_t
*col
);
55 void usage(const char *option
);
59 * 'main()' - Parse options and do tests.
62 int /* O - Exit status */
63 main(int argc
, /* I - Number of command-line arguments */
64 char *argv
[]) /* I - Command-line arguments */
66 int i
; /* Looping var */
67 int status
; /* Status of tests... */
68 const char *uri
; /* URI to use */
69 const char *testfile
; /* Test file to use */
70 int interval
; /* Test interval */
76 * testipp URL testfile
84 for (i
= 1; i
< argc
; i
++)
86 if (argv
[i
][0] == '-')
88 if (!strcmp(argv
[i
], "-v"))
90 else if (!strcmp(argv
[i
], "-d"))
99 else if (!strcmp(argv
[i
], "-i"))
106 interval
= atoi(argv
[i
]);
111 else if (!strncmp(argv
[i
], "ipp://", 6) ||
112 !strncmp(argv
[i
], "http://", 7) ||
113 !strncmp(argv
[i
], "https://", 8))
119 if (!testfile
&& uri
)
133 if (!do_tests(uri
, testfile
))
138 if (!uri
|| !testfile
)
142 * Loop if the interval is set...
150 do_tests(uri
, testfile
);
163 * 'do_tests()' - Do tests as specified in the test file.
166 int /* 1 = success, 0 = failure */
167 do_tests(const char *uri
, /* I - URI to connect on */
168 const char *testfile
) /* I - Test file to use */
170 int i
; /* Looping var */
171 int linenum
; /* Current line number */
172 int version
; /* IPP version number to use */
173 http_t
*http
; /* HTTP connection to server */
174 char scheme
[HTTP_MAX_URI
], /* URI scheme */
175 userpass
[HTTP_MAX_URI
], /* username:password */
176 server
[HTTP_MAX_URI
], /* Server */
177 resource
[HTTP_MAX_URI
]; /* Resource path */
178 int port
; /* Port number */
179 FILE *fp
; /* Test file */
180 char token
[1024], /* Token from file */
181 *tokenptr
, /* Pointer into token */
182 temp
[1024], /* Temporary string */
183 *tempptr
; /* Pointer into temp string */
184 ipp_t
*request
; /* IPP request */
185 ipp_t
*response
; /* IPP response */
186 ipp_op_t op
; /* Operation */
187 ipp_tag_t group
; /* Current group */
188 ipp_tag_t value
; /* Current value type */
189 ipp_attribute_t
*attrptr
; /* Attribute pointer */
190 char attr
[128]; /* Attribute name */
191 int num_statuses
; /* Number of valid status codes */
192 ipp_status_t statuses
[100]; /* Valid status codes */
193 int num_expects
; /* Number of expected attributes */
194 char *expects
[100]; /* Expected attributes */
195 int num_displayed
; /* Number of displayed attributes */
196 char *displayed
[100]; /* Displayed attributes */
197 char name
[1024]; /* Name of test */
198 char filename
[1024]; /* Filename */
199 int pass
; /* Did we pass the test? */
200 int job_id
; /* Job ID from last operation */
201 int subscription_id
; /* Subscription ID from last operation */
205 * Open the test file...
208 if ((fp
= fopen(testfile
, "r")) == NULL
)
210 printf("Unable to open test file %s - %s\n", testfile
, strerror(errno
));
215 * Connect to the server...
218 httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, scheme
, sizeof(scheme
), userpass
,
219 sizeof(userpass
), server
, sizeof(server
), &port
, resource
,
221 if ((http
= httpConnect(server
, port
)) == NULL
)
223 printf("Unable to connect to %s on port %d - %s\n", server
, port
,
233 printf("\"%s\":\n", testfile
);
240 while (get_token(fp
, token
, sizeof(token
), &linenum
) != NULL
)
243 * Expect an open brace...
246 if (strcmp(token
, "{"))
248 printf("Unexpected token %s seen on line %d - aborting test!\n", token
,
255 * Initialize things...
258 httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, scheme
, sizeof(scheme
), userpass
,
259 sizeof(userpass
), server
, sizeof(server
), &port
, resource
,
264 group
= IPP_TAG_ZERO
;
270 strcpy(name
, testfile
);
271 if (strrchr(name
, '.') != NULL
)
272 *strrchr(name
, '.') = '\0';
275 * Parse until we see a close brace...
278 while (get_token(fp
, token
, sizeof(token
), &linenum
) != NULL
)
280 if (!strcmp(token
, "}"))
282 else if (!strcasecmp(token
, "NAME"))
288 get_token(fp
, name
, sizeof(name
), &linenum
);
290 else if (!strcasecmp(token
, "VERSION"))
293 * IPP version number for test...
296 int major
, minor
; /* Major/minor IPP version */
299 get_token(fp
, temp
, sizeof(temp
), &linenum
);
300 if (sscanf(temp
, "%d.%d", &major
, &minor
) == 2 &&
301 major
>= 0 && minor
>= 0 && minor
< 10)
302 version
= major
* 10 + minor
;
305 printf("Bad version %s seen on line %d - aborting test!\n", token
,
312 else if (!strcasecmp(token
, "RESOURCE"))
318 get_token(fp
, resource
, sizeof(resource
), &linenum
);
320 else if (!strcasecmp(token
, "OPERATION"))
326 get_token(fp
, token
, sizeof(token
), &linenum
);
327 op
= ippOpValue(token
);
329 else if (!strcasecmp(token
, "GROUP"))
335 get_token(fp
, token
, sizeof(token
), &linenum
);
336 value
= ippTagValue(token
);
339 ippAddSeparator(request
);
343 else if (!strcasecmp(token
, "DELAY"))
346 * Delay before operation...
351 get_token(fp
, token
, sizeof(token
), &linenum
);
352 if ((delay
= atoi(token
)) > 0)
355 else if (!strcasecmp(token
, "ATTR"))
361 get_token(fp
, token
, sizeof(token
), &linenum
);
362 value
= ippTagValue(token
);
363 get_token(fp
, attr
, sizeof(attr
), &linenum
);
364 get_token(fp
, temp
, sizeof(temp
), &linenum
);
366 token
[sizeof(token
) - 1] = '\0';
368 for (tempptr
= temp
, tokenptr
= token
;
369 *tempptr
&& tokenptr
< (token
+ sizeof(token
) - 1);)
373 * Substitute a string/number...
376 if (!strncasecmp(tempptr
+ 1, "uri", 3))
378 strlcpy(tokenptr
, uri
, sizeof(token
) - (tokenptr
- token
));
381 else if (!strncasecmp(tempptr
+ 1, "scheme", 6) ||
382 !strncasecmp(tempptr
+ 1, "method", 6))
384 strlcpy(tokenptr
, scheme
, sizeof(token
) - (tokenptr
- token
));
387 else if (!strncasecmp(tempptr
+ 1, "username", 8))
389 strlcpy(tokenptr
, userpass
, sizeof(token
) - (tokenptr
- token
));
392 else if (!strncasecmp(tempptr
+ 1, "hostname", 8))
394 strlcpy(tokenptr
, server
, sizeof(token
) - (tokenptr
- token
));
397 else if (!strncasecmp(tempptr
+ 1, "port", 4))
399 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
403 else if (!strncasecmp(tempptr
+ 1, "resource", 8))
405 strlcpy(tokenptr
, resource
, sizeof(token
) - (tokenptr
- token
));
408 else if (!strncasecmp(tempptr
+ 1, "job-id", 6))
410 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
414 else if (!strncasecmp(tempptr
+ 1, "notify-subscription-id", 22))
416 snprintf(tokenptr
, sizeof(token
) - (tokenptr
- token
),
417 "%d", subscription_id
);
420 else if (!strncasecmp(tempptr
+ 1, "user", 4))
422 strlcpy(tokenptr
, cupsUser(), sizeof(token
) - (tokenptr
- token
));
425 else if (!strncasecmp(tempptr
+ 1, "ENV[", 4))
427 char *end
; /* End of $ENV[name] */
430 if ((end
= strchr(tempptr
+ 5, ']')) != NULL
)
434 getenv(tempptr
+ 5) ? getenv(tempptr
+ 5) : tempptr
+ 5,
435 sizeof(token
) - (tokenptr
- token
));
440 *tokenptr
++ = *tempptr
++;
446 *tokenptr
++ = *tempptr
++;
450 tokenptr
+= strlen(tokenptr
);
454 *tokenptr
++ = *tempptr
++;
460 case IPP_TAG_BOOLEAN
:
461 if (!strcasecmp(token
, "true"))
462 ippAddBoolean(request
, group
, attr
, 1);
464 ippAddBoolean(request
, group
, attr
, atoi(token
));
467 case IPP_TAG_INTEGER
:
469 ippAddInteger(request
, group
, value
, attr
, atoi(token
));
472 case IPP_TAG_RESOLUTION
:
473 puts(" ERROR: resolution tag not yet supported!");
477 puts(" ERROR: range tag not yet supported!");
481 if (!strchr(token
, ','))
482 ippAddString(request
, group
, value
, attr
, NULL
, token
);
486 * Multiple string values...
489 int num_values
; /* Number of values */
490 char *values
[100], /* Values */
491 *ptr
; /* Pointer to next value */
497 for (ptr
= strchr(token
, ','); ptr
; ptr
= strchr(ptr
, ','))
500 values
[num_values
] = ptr
;
504 ippAddStrings(request
, group
, value
, attr
, num_values
,
505 NULL
, (const char **)values
);
510 else if (!strcasecmp(token
, "FILE"))
516 get_token(fp
, filename
, sizeof(filename
), &linenum
);
518 else if (!strcasecmp(token
, "STATUS") &&
519 num_statuses
< (int)(sizeof(statuses
) / sizeof(statuses
[0])))
525 get_token(fp
, token
, sizeof(token
), &linenum
);
526 statuses
[num_statuses
] = ippErrorValue(token
);
529 else if (!strcasecmp(token
, "EXPECT") &&
530 num_expects
< (int)(sizeof(expects
) / sizeof(expects
[0])))
533 * Expected attributes...
536 get_token(fp
, token
, sizeof(token
), &linenum
);
537 expects
[num_expects
] = strdup(token
);
540 else if (!strcasecmp(token
, "DISPLAY") &&
541 num_displayed
< (int)(sizeof(displayed
) / sizeof(displayed
[0])))
544 * Display attributes...
547 get_token(fp
, token
, sizeof(token
), &linenum
);
548 displayed
[num_displayed
] = strdup(token
);
553 printf("Unexpected token %s seen on line %d - aborting test!\n", token
,
562 * Submit the IPP request...
565 request
->request
.op
.version
[0] = version
/ 10;
566 request
->request
.op
.version
[1] = version
% 10;
567 request
->request
.op
.operation_id
= op
;
568 request
->request
.op
.request_id
= 1;
572 printf("%s:\n", ippOpString(op
));
574 for (attrptr
= request
->attrs
; attrptr
; attrptr
= attrptr
->next
)
578 printf(" %-60.60s [", name
);
582 response
= cupsDoFileRequest(http
, request
, resource
, filename
);
584 response
= cupsDoIORequest(http
, request
, resource
, -1,
587 if (response
== NULL
)
591 curtime
= time(NULL
);
594 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
595 cupsLastErrorString(), ctime(&curtime
));
600 if ((attrptr
= ippFindAttribute(response
, "job-id",
601 IPP_TAG_INTEGER
)) != NULL
)
602 job_id
= attrptr
->values
[0].integer
;
604 if ((attrptr
= ippFindAttribute(response
, "notify-subscription-id",
605 IPP_TAG_INTEGER
)) != NULL
)
606 subscription_id
= attrptr
->values
[0].integer
;
608 for (i
= 0; i
< num_statuses
; i
++)
609 if (response
->request
.status
.status_code
== statuses
[i
])
612 if (i
== num_statuses
&& num_statuses
> 0)
616 for (i
= 0; i
< num_expects
; i
++)
617 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
627 printf(" RECEIVED: %lu bytes in response\n",
628 (unsigned long)ippLength(response
));
632 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
635 else if (num_displayed
> 0)
637 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
640 for (i
= 0; i
< num_displayed
; i
++)
641 if (!strcmp(displayed
[i
], attrptr
->name
))
652 printf(" RECEIVED: %lu bytes in response\n",
653 (unsigned long)ippLength(response
));
655 for (i
= 0; i
< num_statuses
; i
++)
656 if (response
->request
.status
.status_code
== statuses
[i
])
659 if (i
== num_statuses
&& num_statuses
> 0)
662 printf(" status-code = %04x (%s)\n",
663 cupsLastError(), ippErrorString(cupsLastError()));
665 for (i
= 0; i
< num_expects
; i
++)
666 if (ippFindAttribute(response
, expects
[i
], IPP_TAG_ZERO
) == NULL
)
667 printf(" EXPECTED: %s\n", expects
[i
]);
669 for (attrptr
= response
->attrs
; attrptr
!= NULL
; attrptr
= attrptr
->next
)
676 for (i
= 0; i
< num_expects
; i
++)
691 * 'get_token()' - Get a token from a file.
694 char * /* O - Token from file or NULL on EOF */
695 get_token(FILE *fp
, /* I - File to read from */
696 char *buf
, /* I - Buffer to read into */
697 int buflen
, /* I - Length of buffer */
698 int *linenum
) /* IO - Current line number */
700 int ch
, /* Character from file */
701 quote
; /* Quoting character */
702 char *bufptr
, /* Pointer into buffer */
703 *bufend
; /* End of buffer */
712 while (isspace(ch
= getc(fp
)))
724 else if (ch
== '\'' || ch
== '\"')
732 bufend
= buf
+ buflen
- 1;
734 while ((ch
= getc(fp
)) != EOF
)
737 else if (bufptr
< bufend
)
749 while ((ch
= getc(fp
)) != EOF
)
758 * Whitespace delimited text...
764 bufend
= buf
+ buflen
- 1;
766 while ((ch
= getc(fp
)) != EOF
)
767 if (isspace(ch
) || ch
== '#')
769 else if (bufptr
< bufend
)
783 * 'print_attr()' - Print an attribute on the screen.
787 print_attr(ipp_attribute_t
*attr
) /* I - Attribute to print */
789 int i
; /* Looping var */
792 if (attr
->name
== NULL
)
794 puts(" -- separator --");
798 printf(" %s (%s%s) = ", attr
->name
,
799 attr
->num_values
> 1 ? "1setOf " : "",
800 ippTagString(attr
->value_tag
));
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
);
855 case IPP_TAG_BEGIN_COLLECTION
:
856 for (i
= 0; i
< attr
->num_values
; i
++)
861 print_col(attr
->values
[i
].collection
);
866 break; /* anti-compiler-warning-code */
874 * 'print_col()' - Print a collection attribute on the screen.
878 print_col(ipp_t
*col
) /* I - Collection attribute to print */
880 int i
; /* Looping var */
881 ipp_attribute_t
*attr
; /* Current attribute in collection */
885 for (attr
= col
->attrs
; attr
; attr
= attr
->next
)
887 printf("%s(%s%s)=", attr
->name
, attr
->num_values
> 1 ? "1setOf " : "",
888 ippTagString(attr
->value_tag
));
890 switch (attr
->value_tag
)
892 case IPP_TAG_INTEGER
:
894 for (i
= 0; i
< attr
->num_values
; i
++)
895 printf("%d ", attr
->values
[i
].integer
);
898 case IPP_TAG_BOOLEAN
:
899 for (i
= 0; i
< attr
->num_values
; i
++)
900 if (attr
->values
[i
].boolean
)
906 case IPP_TAG_NOVALUE
:
911 for (i
= 0; i
< attr
->num_values
; i
++)
912 printf("%d-%d ", attr
->values
[i
].range
.lower
,
913 attr
->values
[i
].range
.upper
);
916 case IPP_TAG_RESOLUTION
:
917 for (i
= 0; i
< attr
->num_values
; i
++)
918 printf("%dx%d%s ", attr
->values
[i
].resolution
.xres
,
919 attr
->values
[i
].resolution
.yres
,
920 attr
->values
[i
].resolution
.units
== IPP_RES_PER_INCH
?
924 case IPP_TAG_STRING
:
927 case IPP_TAG_KEYWORD
:
928 case IPP_TAG_CHARSET
:
930 case IPP_TAG_MIMETYPE
:
931 case IPP_TAG_LANGUAGE
:
932 for (i
= 0; i
< attr
->num_values
; i
++)
933 printf("\"%s\" ", attr
->values
[i
].string
.text
);
936 case IPP_TAG_TEXTLANG
:
937 case IPP_TAG_NAMELANG
:
938 for (i
= 0; i
< attr
->num_values
; i
++)
939 printf("\"%s\",%s ", attr
->values
[i
].string
.text
,
940 attr
->values
[i
].string
.charset
);
943 case IPP_TAG_BEGIN_COLLECTION
:
944 for (i
= 0; i
< attr
->num_values
; i
++)
946 print_col(attr
->values
[i
].collection
);
952 break; /* anti-compiler-warning-code */
961 * 'usage()' - Show program usage.
965 usage(const char *option
) /* I - Option string or NULL */
968 fprintf(stderr
, "ipptest: Unknown option \"%s\"!\n", option
);
970 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr
);
971 fputs("Options:\n", stderr
);
973 fputs("-i N Repeat the last test file once every N seconds.\n", stderr
);
974 fputs("-v Show all attributes in response, even on success.\n", stderr
);
981 * End of "$Id: ipptest.c 7847 2008-08-19 04:22:14Z mike $".