]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/testcups.c
Update ipp documentation to reflect the behavior of configuring WiFi on IPP USB printers.
[thirdparty/cups.git] / cups / testcups.c
CommitLineData
09a101d6 1/*
7e86f2f6 2 * CUPS API test program for CUPS.
09a101d6 3 *
728fd810
MS
4 * Copyright © 2007-2018 by Apple Inc.
5 * Copyright © 2007 by Easy Software Products.
09a101d6 6 *
e3101897 7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
09a101d6 8 */
9
10/*
11 * Include necessary headers...
12 */
13
5489ad43 14#undef _CUPS_NO_DEPRECATED
728fd810 15#include "cups-private.h"
aaf19ab0 16#include "ppd.h"
71e16022 17#include <stdlib.h>
09a101d6 18
19
a4924f6c
MS
20/*
21 * Local functions...
22 */
23
24static int dests_equal(cups_dest_t *a, cups_dest_t *b);
dcb445bc 25static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest);
a4924f6c
MS
26static void show_diffs(cups_dest_t *a, cups_dest_t *b);
27
28
09a101d6 29/*
30 * 'main()' - Main entry.
31 */
32
33int /* O - Exit status */
34main(int argc, /* I - Number of command-line arguments */
35 char *argv[]) /* I - Command-line arguments */
36{
728fd810
MS
37 http_t *http, /* First HTTP connection */
38 *http2; /* Second HTTP connection */
09a101d6 39 int status = 0, /* Exit status */
a4924f6c 40 i, /* Looping var */
09a101d6 41 num_dests; /* Number of destinations */
42 cups_dest_t *dests, /* Destinations */
a4924f6c
MS
43 *dest, /* Current destination */
44 *named_dest; /* Current named destination */
ced9dda8
MS
45 const char *dest_name, /* Destination name */
46 *dval, /* Destination value */
47 *ppdfile; /* PPD file */
09a101d6 48 ppd_file_t *ppd; /* PPD file data */
49 int num_jobs; /* Number of jobs for queue */
50 cups_job_t *jobs; /* Jobs for queue */
51
a29fd7dd 52
dfd5680b
MS
53 if (argc > 1)
54 {
dcb445bc
MS
55 if (!strcmp(argv[1], "enum"))
56 {
a29fd7dd
MS
57 cups_ptype_t mask = CUPS_PRINTER_LOCAL,
58 /* Printer type mask */
59 type = CUPS_PRINTER_LOCAL;
60 /* Printer type */
61 int msec = 0; /* Timeout in milliseconds */
62
63
64 for (i = 2; i < argc; i ++)
65 if (isdigit(argv[i][0] & 255) || argv[i][0] == '.')
66 msec = (int)(atof(argv[i]) * 1000);
67 else if (!_cups_strcasecmp(argv[i], "bw"))
68 {
69 mask |= CUPS_PRINTER_BW;
70 type |= CUPS_PRINTER_BW;
71 }
72 else if (!_cups_strcasecmp(argv[i], "color"))
73 {
74 mask |= CUPS_PRINTER_COLOR;
75 type |= CUPS_PRINTER_COLOR;
76 }
77 else if (!_cups_strcasecmp(argv[i], "mono"))
78 {
79 mask |= CUPS_PRINTER_COLOR;
80 }
81 else if (!_cups_strcasecmp(argv[i], "duplex"))
82 {
83 mask |= CUPS_PRINTER_DUPLEX;
84 type |= CUPS_PRINTER_DUPLEX;
85 }
86 else if (!_cups_strcasecmp(argv[i], "simplex"))
87 {
88 mask |= CUPS_PRINTER_DUPLEX;
89 }
90 else if (!_cups_strcasecmp(argv[i], "staple"))
91 {
92 mask |= CUPS_PRINTER_STAPLE;
93 type |= CUPS_PRINTER_STAPLE;
94 }
95 else if (!_cups_strcasecmp(argv[i], "copies"))
96 {
97 mask |= CUPS_PRINTER_COPIES;
98 type |= CUPS_PRINTER_COPIES;
99 }
100 else if (!_cups_strcasecmp(argv[i], "collate"))
101 {
102 mask |= CUPS_PRINTER_COLLATE;
103 type |= CUPS_PRINTER_COLLATE;
104 }
105 else if (!_cups_strcasecmp(argv[i], "punch"))
106 {
107 mask |= CUPS_PRINTER_PUNCH;
108 type |= CUPS_PRINTER_PUNCH;
109 }
110 else if (!_cups_strcasecmp(argv[i], "cover"))
111 {
112 mask |= CUPS_PRINTER_COVER;
113 type |= CUPS_PRINTER_COVER;
114 }
115 else if (!_cups_strcasecmp(argv[i], "bind"))
116 {
117 mask |= CUPS_PRINTER_BIND;
118 type |= CUPS_PRINTER_BIND;
119 }
120 else if (!_cups_strcasecmp(argv[i], "sort"))
121 {
122 mask |= CUPS_PRINTER_SORT;
123 type |= CUPS_PRINTER_SORT;
124 }
125 else if (!_cups_strcasecmp(argv[i], "mfp"))
126 {
127 mask |= CUPS_PRINTER_MFP;
128 type |= CUPS_PRINTER_MFP;
129 }
130 else if (!_cups_strcasecmp(argv[i], "printer"))
131 {
132 mask |= CUPS_PRINTER_MFP;
133 }
134 else if (!_cups_strcasecmp(argv[i], "large"))
135 {
136 mask |= CUPS_PRINTER_LARGE;
137 type |= CUPS_PRINTER_LARGE;
138 }
139 else if (!_cups_strcasecmp(argv[i], "medium"))
140 {
141 mask |= CUPS_PRINTER_MEDIUM;
142 type |= CUPS_PRINTER_MEDIUM;
143 }
144 else if (!_cups_strcasecmp(argv[i], "small"))
145 {
146 mask |= CUPS_PRINTER_SMALL;
147 type |= CUPS_PRINTER_SMALL;
148 }
149 else
150 fprintf(stderr, "Unknown argument \"%s\" ignored...\n", argv[i]);
151
152 cupsEnumDests(CUPS_DEST_FLAGS_NONE, msec, NULL, type, mask, enum_cb, NULL);
dfd5680b 153 }
dcb445bc 154 else if (!strcmp(argv[1], "password"))
dfd5680b 155 {
dcb445bc
MS
156 const char *pass = cupsGetPassword("Password:");
157 /* Password string */
dfd5680b 158
dcb445bc
MS
159 if (pass)
160 printf("Password entered: %s\n", pass);
161 else
162 puts("No password entered.");
dfd5680b 163 }
4972f4fe
MS
164 else if (!strcmp(argv[1], "ppd") && argc == 3)
165 {
166 /*
167 * ./testcups ppd printer
168 */
169
170 http_status_t http_status; /* Status */
171 char buffer[1024]; /* PPD filename */
172 time_t modtime = 0; /* Last modified */
173
174 if ((http_status = cupsGetPPD3(CUPS_HTTP_DEFAULT, argv[2], &modtime,
175 buffer, sizeof(buffer))) != HTTP_STATUS_OK)
176 printf("Unable to get PPD: %d (%s)\n", (int)http_status,
177 cupsLastErrorString());
178 else
179 puts(buffer);
180 }
dcb445bc
MS
181 else if (!strcmp(argv[1], "print") && argc == 5)
182 {
183 /*
4972f4fe 184 * ./testcups print printer file interval
dcb445bc 185 */
aaf19ab0 186
dcb445bc
MS
187 int interval, /* Interval between writes */
188 job_id; /* Job ID */
189 cups_file_t *fp; /* Print file */
190 char buffer[16384]; /* Read/write buffer */
191 ssize_t bytes; /* Bytes read/written */
dfd5680b 192
dcb445bc
MS
193 if ((fp = cupsFileOpen(argv[3], "r")) == NULL)
194 {
195 printf("Unable to open \"%s\": %s\n", argv[2], strerror(errno));
196 return (1);
197 }
dfd5680b 198
dcb445bc
MS
199 if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, argv[2], "testcups", 0,
200 NULL)) <= 0)
201 {
202 printf("Unable to create print job on %s: %s\n", argv[1],
203 cupsLastErrorString());
204 return (1);
205 }
206
207 interval = atoi(argv[4]);
dfd5680b 208
dcb445bc 209 if (cupsStartDocument(CUPS_HTTP_DEFAULT, argv[1], job_id, argv[2],
cb7f98ee 210 CUPS_FORMAT_AUTO, 1) != HTTP_STATUS_CONTINUE)
dfd5680b 211 {
dcb445bc 212 puts("Unable to start document!");
dfd5680b
MS
213 return (1);
214 }
215
dcb445bc
MS
216 while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
217 {
218 printf("Writing %d bytes...\n", (int)bytes);
219
7e86f2f6 220 if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE)
dcb445bc
MS
221 {
222 puts("Unable to write bytes!");
223 return (1);
224 }
dfd5680b 225
dcb445bc 226 if (interval > 0)
7e86f2f6 227 sleep((unsigned)interval);
dcb445bc
MS
228 }
229
230 cupsFileClose(fp);
dfd5680b 231
cb7f98ee
MS
232 if (cupsFinishDocument(CUPS_HTTP_DEFAULT,
233 argv[1]) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
dcb445bc
MS
234 {
235 puts("Unable to finish document!");
236 return (1);
237 }
238 }
239 else
dfd5680b 240 {
dcb445bc
MS
241 puts("Usage:");
242 puts("");
243 puts("Run basic unit tests:");
244 puts("");
245 puts(" ./testcups");
246 puts("");
247 puts("Enumerate printers (for N seconds, -1 for indefinitely):");
248 puts("");
249 puts(" ./testcups enum [seconds]");
250 puts("");
251 puts("Ask for a password:");
252 puts("");
253 puts(" ./testcups password");
254 puts("");
4972f4fe
MS
255 puts("Get the PPD file:");
256 puts("");
257 puts(" ./testcups ppd printer");
258 puts("");
dcb445bc
MS
259 puts("Print a file (interval controls delay between buffers in seconds):");
260 puts("");
261 puts(" ./testcups print printer file interval");
dfd5680b
MS
262 return (1);
263 }
264
265 return (0);
266 }
267
728fd810
MS
268 /*
269 * _cupsConnect() connection reuse...
270 */
271
272 fputs("_cupsConnect: ", stdout);
273 http = _cupsConnect();
274 http2 = _cupsConnect();
275
276 if (http == http2)
277 {
278 puts("PASS");
279 }
280 else
281 {
282 puts("FAIL (different connections)");
283 return (1);
284 }
285
09a101d6 286 /*
287 * cupsGetDests()
288 */
289
290 fputs("cupsGetDests: ", stdout);
291 fflush(stdout);
292
293 num_dests = cupsGetDests(&dests);
294
295 if (num_dests == 0)
296 {
297 puts("FAIL");
298 return (1);
299 }
300 else
a4924f6c
MS
301 {
302 printf("PASS (%d dests)\n", num_dests);
303
304 for (i = num_dests, dest = dests; i > 0; i --, dest ++)
305 {
306 printf(" %s", dest->name);
307
308 if (dest->instance)
309 printf(" /%s", dest->instance);
310
311 if (dest->is_default)
312 puts(" ***DEFAULT***");
313 else
314 putchar('\n');
315 }
316 }
317
318 /*
319 * cupsGetDest(NULL)
320 */
321
322 fputs("cupsGetDest(NULL): ", stdout);
323 fflush(stdout);
324
325 if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
326 {
327 for (i = num_dests, dest = dests; i > 0; i --, dest ++)
328 if (dest->is_default)
329 break;
330
331 if (i)
332 {
333 status = 1;
334 puts("FAIL");
335 }
336 else
337 puts("PASS (no default)");
338
339 dest = NULL;
340 }
341 else
342 printf("PASS (%s)\n", dest->name);
343
344 /*
345 * cupsGetNamedDest(NULL, NULL, NULL)
346 */
347
348 fputs("cupsGetNamedDest(NULL, NULL, NULL): ", stdout);
349 fflush(stdout);
350
351 if ((named_dest = cupsGetNamedDest(NULL, NULL, NULL)) == NULL ||
352 !dests_equal(dest, named_dest))
353 {
354 if (!dest)
355 puts("PASS (no default)");
356 else if (named_dest)
357 {
358 puts("FAIL (different values)");
359 show_diffs(dest, named_dest);
360 status = 1;
361 }
362 else
363 {
364 puts("FAIL (no default)");
365 status = 1;
366 }
367 }
368 else
369 printf("PASS (%s)\n", named_dest->name);
370
371 if (named_dest)
372 cupsFreeDests(1, named_dest);
09a101d6 373
374 /*
375 * cupsGetDest(printer)
376 */
377
ced9dda8
MS
378 for (i = 0, dest_name = NULL; i < num_dests; i ++)
379 {
380 if ((dval = cupsGetOption("printer-is-temporary", dests[i].num_options, dest[i].options)) != NULL && !strcmp(dval, "false"))
381 {
382 dest_name = dests[i].name;
383 break;
384 }
385 }
386
387 printf("cupsGetDest(\"%s\"): ", dest_name ? dest_name : "(null)");
09a101d6 388 fflush(stdout);
389
ced9dda8 390 if ((dest = cupsGetDest(dest_name, NULL, num_dests, dests)) == NULL)
09a101d6 391 {
09a101d6 392 puts("FAIL");
91c84a35 393 return (1);
09a101d6 394 }
395 else
396 puts("PASS");
397
398 /*
a4924f6c 399 * cupsGetNamedDest(NULL, printer, instance)
09a101d6 400 */
401
a4924f6c
MS
402 printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name,
403 dest->instance ? dest->instance : "(null)");
09a101d6 404 fflush(stdout);
405
ced9dda8 406 if ((named_dest = cupsGetNamedDest(NULL, dest->name, dest->instance)) == NULL ||
a4924f6c 407 !dests_equal(dest, named_dest))
09a101d6 408 {
a4924f6c
MS
409 if (named_dest)
410 {
411 puts("FAIL (different values)");
412 show_diffs(dest, named_dest);
413 }
414 else
415 puts("FAIL (no destination)");
416
417
09a101d6 418 status = 1;
09a101d6 419 }
420 else
421 puts("PASS");
422
a4924f6c
MS
423 if (named_dest)
424 cupsFreeDests(1, named_dest);
425
09a101d6 426 /*
427 * cupsPrintFile()
428 */
429
430 fputs("cupsPrintFile: ", stdout);
431 fflush(stdout);
432
ced9dda8 433 if (cupsPrintFile(dest->name, "../test/testfile.pdf", "Test Page",
09a101d6 434 dest->num_options, dest->options) <= 0)
435 {
426c6a59 436 printf("FAIL (%s)\n", cupsLastErrorString());
1f0275e3 437 return (1);
09a101d6 438 }
439 else
440 puts("PASS");
441
442 /*
443 * cupsGetPPD(printer)
444 */
445
ced9dda8 446 fputs("cupsGetPPD: ", stdout);
09a101d6 447 fflush(stdout);
448
449 if ((ppdfile = cupsGetPPD(dest->name)) == NULL)
450 {
09a101d6 451 puts("FAIL");
452 }
453 else
454 {
455 puts("PASS");
456
457 /*
458 * ppdOpenFile()
459 */
460
ced9dda8 461 fputs("ppdOpenFile: ", stdout);
09a101d6 462 fflush(stdout);
463
464 if ((ppd = ppdOpenFile(ppdfile)) == NULL)
465 {
466 puts("FAIL");
467 return (1);
468 }
469 else
470 puts("PASS");
471
472 ppdClose(ppd);
473 unlink(ppdfile);
474 }
475
476 /*
477 * cupsGetJobs()
478 */
479
480 fputs("cupsGetJobs: ", stdout);
481 fflush(stdout);
482
483 num_jobs = cupsGetJobs(&jobs, NULL, 0, -1);
484
485 if (num_jobs == 0)
486 {
487 puts("FAIL");
488 return (1);
489 }
490 else
491 puts("PASS");
492
493 cupsFreeJobs(num_jobs, jobs);
494 cupsFreeDests(num_dests, dests);
495
496 return (status);
497}
498
499
a4924f6c
MS
500/*
501 * 'dests_equal()' - Determine whether two destinations are equal.
502 */
503
504static int /* O - 1 if equal, 0 if not equal */
505dests_equal(cups_dest_t *a, /* I - First destination */
506 cups_dest_t *b) /* I - Second destination */
507{
508 int i; /* Looping var */
509 cups_option_t *aoption; /* Current option */
510 const char *bval; /* Option value */
511
512
513 if (a == b)
514 return (1);
515
1f0275e3 516 if (!a || !b)
a4924f6c
MS
517 return (0);
518
88f9aafc 519 if (_cups_strcasecmp(a->name, b->name) ||
a4924f6c
MS
520 (a->instance && !b->instance) ||
521 (!a->instance && b->instance) ||
88f9aafc 522 (a->instance && _cups_strcasecmp(a->instance, b->instance)) ||
a4924f6c
MS
523 a->num_options != b->num_options)
524 return (0);
525
526 for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++)
527 if ((bval = cupsGetOption(aoption->name, b->num_options,
528 b->options)) == NULL ||
529 strcmp(aoption->value, bval))
530 return (0);
531
532 return (1);
533}
534
535
dcb445bc
MS
536/*
537 * 'enum_cb()' - Report additions and removals.
538 */
539
540static int /* O - 1 to continue, 0 to stop */
541enum_cb(void *user_data, /* I - User data (unused) */
542 unsigned flags, /* I - Destination flags */
543 cups_dest_t *dest) /* I - Destination */
544{
a29fd7dd
MS
545 int i; /* Looping var */
546 cups_option_t *option; /* Current option */
547
548
7e86f2f6
MS
549 (void)user_data;
550
dcb445bc 551 if (flags & CUPS_DEST_FLAGS_REMOVED)
a29fd7dd 552 printf("Removed '%s':\n", dest->name);
dcb445bc 553 else
a29fd7dd
MS
554 printf("Added '%s':\n", dest->name);
555
556 for (i = dest->num_options, option = dest->options; i > 0; i --, option ++)
557 printf(" %s=\"%s\"\n", option->name, option->value);
558
559 putchar('\n');
dcb445bc
MS
560
561 return (1);
562}
563
564
a4924f6c
MS
565/*
566 * 'show_diffs()' - Show differences between two destinations.
567 */
568
569static void
570show_diffs(cups_dest_t *a, /* I - First destination */
571 cups_dest_t *b) /* I - Second destination */
572{
573 int i; /* Looping var */
574 cups_option_t *aoption; /* Current option */
ced9dda8 575 cups_option_t *boption; /* Current option */
a4924f6c
MS
576 const char *bval; /* Option value */
577
578
579 if (!a || !b)
580 return;
581
ced9dda8
MS
582 puts(" Item cupsGetDest cupsGetNamedDest");
583 puts(" -------------------- ------------------------ ------------------------");
a4924f6c 584
88f9aafc 585 if (_cups_strcasecmp(a->name, b->name))
ced9dda8 586 printf(" name %-24.24s %-24.24s\n", a->name, b->name);
a4924f6c
MS
587
588 if ((a->instance && !b->instance) ||
589 (!a->instance && b->instance) ||
88f9aafc 590 (a->instance && _cups_strcasecmp(a->instance, b->instance)))
ced9dda8 591 printf(" instance %-24.24s %-24.24s\n",
a4924f6c
MS
592 a->instance ? a->instance : "(null)",
593 b->instance ? b->instance : "(null)");
594
595 if (a->num_options != b->num_options)
ced9dda8 596 printf(" num_options %-24d %-24d\n", a->num_options,
a4924f6c
MS
597 b->num_options);
598
599 for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++)
600 if ((bval = cupsGetOption(aoption->name, b->num_options,
601 b->options)) == NULL ||
602 strcmp(aoption->value, bval))
ced9dda8 603 printf(" %-20.20s %-24.24s %-24.24s\n", aoption->name,
a4924f6c 604 aoption->value, bval ? bval : "(null)");
ced9dda8
MS
605
606 for (i = b->num_options, boption = b->options; i > 0; i --, boption ++)
607 if (!cupsGetOption(boption->name, a->num_options, a->options))
608 printf(" %-20.20s %-24.24s %-24.24s\n", boption->name,
609 boption->value, "(null)");
a4924f6c 610}