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