]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testppd.c
0e3668f54af2f0b3849eb1a4edbefd6c49a661e8
[thirdparty/cups.git] / cups / testppd.c
1 /*
2 * PPD test program for CUPS.
3 *
4 * Copyright 2007-2017 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
6 *
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8 */
9
10 /*
11 * Include necessary headers...
12 */
13
14 #undef _CUPS_NO_DEPRECATED
15 #include "cups-private.h"
16 #include "ppd-private.h"
17 #include <sys/stat.h>
18 #ifdef WIN32
19 # include <io.h>
20 #else
21 # include <unistd.h>
22 # include <fcntl.h>
23 #endif /* WIN32 */
24 #include <math.h>
25
26
27 /*
28 * Test data...
29 */
30
31 static const char *default_code =
32 "[{\n"
33 "%%BeginFeature: *InstalledDuplexer False\n"
34 "%%EndFeature\n"
35 "} stopped cleartomark\n"
36 "[{\n"
37 "%%BeginFeature: *PageRegion Letter\n"
38 "PageRegion=Letter\n"
39 "%%EndFeature\n"
40 "} stopped cleartomark\n"
41 "[{\n"
42 "%%BeginFeature: *InputSlot Tray\n"
43 "InputSlot=Tray\n"
44 "%%EndFeature\n"
45 "} stopped cleartomark\n"
46 "[{\n"
47 "%%BeginFeature: *OutputBin Tray1\n"
48 "OutputBin=Tray1\n"
49 "%%EndFeature\n"
50 "} stopped cleartomark\n"
51 "[{\n"
52 "%%BeginFeature: *MediaType Plain\n"
53 "MediaType=Plain\n"
54 "%%EndFeature\n"
55 "} stopped cleartomark\n"
56 "[{\n"
57 "%%BeginFeature: *IntOption None\n"
58 "%%EndFeature\n"
59 "} stopped cleartomark\n"
60 "[{\n"
61 "%%BeginFeature: *StringOption None\n"
62 "%%EndFeature\n"
63 "} stopped cleartomark\n";
64
65 static const char *custom_code =
66 "[{\n"
67 "%%BeginFeature: *InstalledDuplexer False\n"
68 "%%EndFeature\n"
69 "} stopped cleartomark\n"
70 "[{\n"
71 "%%BeginFeature: *InputSlot Tray\n"
72 "InputSlot=Tray\n"
73 "%%EndFeature\n"
74 "} stopped cleartomark\n"
75 "[{\n"
76 "%%BeginFeature: *MediaType Plain\n"
77 "MediaType=Plain\n"
78 "%%EndFeature\n"
79 "} stopped cleartomark\n"
80 "[{\n"
81 "%%BeginFeature: *OutputBin Tray1\n"
82 "OutputBin=Tray1\n"
83 "%%EndFeature\n"
84 "} stopped cleartomark\n"
85 "[{\n"
86 "%%BeginFeature: *IntOption None\n"
87 "%%EndFeature\n"
88 "} stopped cleartomark\n"
89 "[{\n"
90 "%%BeginFeature: *CustomStringOption True\n"
91 "(value\\0502\\051)\n"
92 "(value 1)\n"
93 "StringOption=Custom\n"
94 "%%EndFeature\n"
95 "} stopped cleartomark\n"
96 "[{\n"
97 "%%BeginFeature: *CustomPageSize True\n"
98 "400\n"
99 "500\n"
100 "0\n"
101 "0\n"
102 "0\n"
103 "PageSize=Custom\n"
104 "%%EndFeature\n"
105 "} stopped cleartomark\n";
106
107 static const char *default2_code =
108 "[{\n"
109 "%%BeginFeature: *InstalledDuplexer False\n"
110 "%%EndFeature\n"
111 "} stopped cleartomark\n"
112 "[{\n"
113 "%%BeginFeature: *InputSlot Tray\n"
114 "InputSlot=Tray\n"
115 "%%EndFeature\n"
116 "} stopped cleartomark\n"
117 "[{\n"
118 "%%BeginFeature: *Quality Normal\n"
119 "Quality=Normal\n"
120 "%%EndFeature\n"
121 "} stopped cleartomark\n"
122 "[{\n"
123 "%%BeginFeature: *IntOption None\n"
124 "%%EndFeature\n"
125 "} stopped cleartomark\n"
126 "[{\n"
127 "%%BeginFeature: *StringOption None\n"
128 "%%EndFeature\n"
129 "} stopped cleartomark\n";
130
131
132 /*
133 * 'main()' - Main entry.
134 */
135
136 int /* O - Exit status */
137 main(int argc, /* I - Number of command-line arguments */
138 char *argv[]) /* I - Command-line arguments */
139 {
140 int i; /* Looping var */
141 ppd_file_t *ppd; /* PPD file loaded from disk */
142 int status; /* Status of tests (0 = success, 1 = fail) */
143 int conflicts; /* Number of conflicts */
144 char *s; /* String */
145 char buffer[8192]; /* String buffer */
146 const char *text, /* Localized text */
147 *val; /* Option value */
148 int num_options; /* Number of options */
149 cups_option_t *options; /* Options */
150 ppd_size_t minsize, /* Minimum size */
151 maxsize, /* Maximum size */
152 *size; /* Current size */
153 ppd_attr_t *attr; /* Current attribute */
154 _ppd_cache_t *pc; /* PPD cache */
155
156
157 status = 0;
158
159 if (argc == 1)
160 {
161 /*
162 * Setup directories for locale stuff...
163 */
164
165 if (access("locale", 0))
166 {
167 mkdir("locale", 0777);
168 mkdir("locale/fr", 0777);
169 symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po");
170 mkdir("locale/zh_TW", 0777);
171 symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po");
172 }
173
174 putenv("LOCALEDIR=locale");
175 putenv("SOFTWARE=CUPS");
176
177 /*
178 * Do tests with test.ppd...
179 */
180
181 fputs("ppdOpenFile(test.ppd): ", stdout);
182
183 if ((ppd = _ppdOpenFile("test.ppd", _PPD_LOCALIZATION_ALL)) != NULL)
184 puts("PASS");
185 else
186 {
187 ppd_status_t err; /* Last error in file */
188 int line; /* Line number in file */
189
190
191 status ++;
192 err = ppdLastError(&line);
193
194 printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
195 }
196
197 fputs("ppdFindAttr(wildcard): ", stdout);
198 if ((attr = ppdFindAttr(ppd, "cupsTest", NULL)) == NULL)
199 {
200 status ++;
201 puts("FAIL (not found)");
202 }
203 else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
204 {
205 status ++;
206 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
207 }
208 else
209 puts("PASS");
210
211 fputs("ppdFindNextAttr(wildcard): ", stdout);
212 if ((attr = ppdFindNextAttr(ppd, "cupsTest", NULL)) == NULL)
213 {
214 status ++;
215 puts("FAIL (not found)");
216 }
217 else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Bar"))
218 {
219 status ++;
220 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
221 }
222 else
223 puts("PASS");
224
225 fputs("ppdFindAttr(Foo): ", stdout);
226 if ((attr = ppdFindAttr(ppd, "cupsTest", "Foo")) == NULL)
227 {
228 status ++;
229 puts("FAIL (not found)");
230 }
231 else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
232 {
233 status ++;
234 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
235 }
236 else
237 puts("PASS");
238
239 fputs("ppdFindNextAttr(Foo): ", stdout);
240 if ((attr = ppdFindNextAttr(ppd, "cupsTest", "Foo")) != NULL)
241 {
242 status ++;
243 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
244 }
245 else
246 puts("PASS");
247
248 fputs("ppdMarkDefaults: ", stdout);
249 ppdMarkDefaults(ppd);
250
251 if ((conflicts = ppdConflicts(ppd)) == 0)
252 puts("PASS");
253 else
254 {
255 status ++;
256 printf("FAIL (%d conflicts)\n", conflicts);
257 }
258
259 fputs("ppdEmitString (defaults): ", stdout);
260 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
261 !strcmp(s, default_code))
262 puts("PASS");
263 else
264 {
265 status ++;
266 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
267 (int)strlen(default_code));
268
269 if (s)
270 puts(s);
271 }
272
273 if (s)
274 free(s);
275
276 fputs("ppdEmitString (custom size and string): ", stdout);
277 ppdMarkOption(ppd, "PageSize", "Custom.400x500");
278 ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}");
279
280 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
281 !strcmp(s, custom_code))
282 puts("PASS");
283 else
284 {
285 status ++;
286 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
287 (int)strlen(custom_code));
288
289 if (s)
290 puts(s);
291 }
292
293 if (s)
294 free(s);
295
296 /*
297 * Test constraints...
298 */
299
300 fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout);
301 ppdMarkOption(ppd, "PageSize", "Letter");
302
303 num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options);
304 if (num_options != 2 ||
305 (val = cupsGetOption("PageRegion", num_options, options)) == NULL ||
306 _cups_strcasecmp(val, "Letter") ||
307 (val = cupsGetOption("PageSize", num_options, options)) == NULL ||
308 _cups_strcasecmp(val, "Letter"))
309 {
310 printf("FAIL (%d options:", num_options);
311 for (i = 0; i < num_options; i ++)
312 printf(" %s=%s", options[i].name, options[i].value);
313 puts(")");
314 status ++;
315 }
316 else
317 puts("PASS");
318
319 fputs("ppdConflicts(): ", stdout);
320 ppdMarkOption(ppd, "InputSlot", "Envelope");
321
322 if ((conflicts = ppdConflicts(ppd)) == 2)
323 puts("PASS (2)");
324 else
325 {
326 printf("FAIL (%d)\n", conflicts);
327 status ++;
328 }
329
330 fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout);
331 num_options = 0;
332 options = NULL;
333 if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options,
334 &options))
335 {
336 puts("FAIL (Unable to resolve)");
337 status ++;
338 }
339 else if (num_options != 2 ||
340 !cupsGetOption("PageSize", num_options, options))
341 {
342 printf("FAIL (%d options:", num_options);
343 for (i = 0; i < num_options; i ++)
344 printf(" %s=%s", options[i].name, options[i].value);
345 puts(")");
346 status ++;
347 }
348 else
349 puts("PASS (Resolved by changing PageSize)");
350
351 cupsFreeOptions(num_options, options);
352
353 fputs("cupsResolveConflicts(No option/choice): ", stdout);
354 num_options = 0;
355 options = NULL;
356 if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
357 num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") &&
358 !_cups_strcasecmp(options[0].value, "Tray"))
359 puts("PASS (Resolved by changing InputSlot)");
360 else if (num_options > 0)
361 {
362 printf("FAIL (%d options:", num_options);
363 for (i = 0; i < num_options; i ++)
364 printf(" %s=%s", options[i].name, options[i].value);
365 puts(")");
366 status ++;
367 }
368 else
369 {
370 puts("FAIL (Unable to resolve)");
371 status ++;
372 }
373 cupsFreeOptions(num_options, options);
374
375 fputs("ppdInstallableConflict(): ", stdout);
376 if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
377 !ppdInstallableConflict(ppd, "Duplex", "None"))
378 puts("PASS");
379 else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
380 {
381 puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
382 status ++;
383 }
384 else
385 {
386 puts("FAIL (Duplex=None conflicted)");
387 status ++;
388 }
389
390 /*
391 * ppdPageSizeLimits
392 */
393
394 fputs("ppdPageSizeLimits: ", stdout);
395 if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
396 {
397 if (fabs(minsize.width - 36.0) > 0.001 || fabs(minsize.length - 36.0) > 0.001 ||
398 fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001)
399 {
400 printf("FAIL (got min=%.3fx%.3f, max=%.3fx%.3f, "
401 "expected min=36x36, max=1080x86400)\n", minsize.width,
402 minsize.length, maxsize.width, maxsize.length);
403 status ++;
404 }
405 else
406 puts("PASS");
407 }
408 else
409 {
410 puts("FAIL (returned 0)");
411 status ++;
412 }
413
414 /*
415 * cupsMarkOptions with PWG and IPP size names.
416 */
417
418 fputs("cupsMarkOptions(media=iso-a4): ", stdout);
419 num_options = cupsAddOption("media", "iso-a4", 0, &options);
420 cupsMarkOptions(ppd, num_options, options);
421 cupsFreeOptions(num_options, options);
422
423 size = ppdPageSize(ppd, NULL);
424 if (!size || strcmp(size->name, "A4"))
425 {
426 printf("FAIL (%s)\n", size ? size->name : "unknown");
427 status ++;
428 }
429 else
430 puts("PASS");
431
432 fputs("cupsMarkOptions(media=na_letter_8.5x11in): ", stdout);
433 num_options = cupsAddOption("media", "na_letter_8.5x11in", 0, &options);
434 cupsMarkOptions(ppd, num_options, options);
435 cupsFreeOptions(num_options, options);
436
437 size = ppdPageSize(ppd, NULL);
438 if (!size || strcmp(size->name, "Letter"))
439 {
440 printf("FAIL (%s)\n", size ? size->name : "unknown");
441 status ++;
442 }
443 else
444 puts("PASS");
445
446 fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout);
447 num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0,
448 &options);
449 cupsMarkOptions(ppd, num_options, options);
450 cupsFreeOptions(num_options, options);
451
452 size = ppdPageSize(ppd, NULL);
453 if (!size || strcmp(size->name, "Letter.Fullbleed"))
454 {
455 printf("FAIL (%s)\n", size ? size->name : "unknown");
456 status ++;
457 }
458 else
459 puts("PASS");
460
461 fputs("cupsMarkOptions(media=A4): ", stdout);
462 num_options = cupsAddOption("media", "A4", 0, &options);
463 cupsMarkOptions(ppd, num_options, options);
464 cupsFreeOptions(num_options, options);
465
466 size = ppdPageSize(ppd, NULL);
467 if (!size || strcmp(size->name, "A4"))
468 {
469 printf("FAIL (%s)\n", size ? size->name : "unknown");
470 status ++;
471 }
472 else
473 puts("PASS");
474
475 /*
476 * Custom sizes...
477 */
478
479 fputs("cupsMarkOptions(media=Custom.8x10in): ", stdout);
480 num_options = cupsAddOption("media", "Custom.8x10in", 0, &options);
481 cupsMarkOptions(ppd, num_options, options);
482 cupsFreeOptions(num_options, options);
483
484 size = ppdPageSize(ppd, NULL);
485 if (!size || strcmp(size->name, "Custom") ||
486 fabs(size->width - 576.0) > 0.001 ||
487 fabs(size->length - 720.0) > 0.001)
488 {
489 printf("FAIL (%s - %gx%g)\n", size ? size->name : "unknown",
490 size ? size->width : 0.0, size ? size->length : 0.0);
491 status ++;
492 }
493 else
494 puts("PASS");
495
496 /*
497 * Test localization...
498 */
499
500 fputs("ppdLocalizeIPPReason(text): ", stdout);
501 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
502 !strcmp(buffer, "Foo Reason"))
503 puts("PASS");
504 else
505 {
506 status ++;
507 printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer);
508 }
509
510 fputs("ppdLocalizeIPPReason(http): ", stdout);
511 if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) &&
512 !strcmp(buffer, "http://foo/bar.html"))
513 puts("PASS");
514 else
515 {
516 status ++;
517 printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer);
518 }
519
520 fputs("ppdLocalizeIPPReason(help): ", stdout);
521 if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) &&
522 !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help"))
523 puts("PASS");
524 else
525 {
526 status ++;
527 printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer);
528 }
529
530 fputs("ppdLocalizeIPPReason(file): ", stdout);
531 if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) &&
532 !strcmp(buffer, "/help/foo/bar.html"))
533 puts("PASS");
534 else
535 {
536 status ++;
537 printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer);
538 }
539
540 putenv("LANG=fr");
541 putenv("LC_ALL=fr");
542 putenv("LC_CTYPE=fr");
543 putenv("LC_MESSAGES=fr");
544
545 fputs("ppdLocalizeIPPReason(fr text): ", stdout);
546 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
547 !strcmp(buffer, "La Long Foo Reason"))
548 puts("PASS");
549 else
550 {
551 status ++;
552 printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer);
553 }
554
555 putenv("LANG=zh_TW");
556 putenv("LC_ALL=zh_TW");
557 putenv("LC_CTYPE=zh_TW");
558 putenv("LC_MESSAGES=zh_TW");
559
560 fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout);
561 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
562 !strcmp(buffer, "Number 1 Foo Reason"))
563 puts("PASS");
564 else
565 {
566 status ++;
567 printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer);
568 }
569
570 /*
571 * cupsMarkerName localization...
572 */
573
574 putenv("LANG=en");
575 putenv("LC_ALL=en");
576 putenv("LC_CTYPE=en");
577 putenv("LC_MESSAGES=en");
578
579 fputs("ppdLocalizeMarkerName(bogus): ", stdout);
580
581 if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL)
582 {
583 status ++;
584 printf("FAIL (\"%s\" instead of NULL)\n", text);
585 }
586 else
587 puts("PASS");
588
589 fputs("ppdLocalizeMarkerName(cyan): ", stdout);
590
591 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
592 !strcmp(text, "Cyan Toner"))
593 puts("PASS");
594 else
595 {
596 status ++;
597 printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n",
598 text ? text : "(null)");
599 }
600
601 putenv("LANG=fr");
602 putenv("LC_ALL=fr");
603 putenv("LC_CTYPE=fr");
604 putenv("LC_MESSAGES=fr");
605
606 fputs("ppdLocalizeMarkerName(fr cyan): ", stdout);
607 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
608 !strcmp(text, "La Toner Cyan"))
609 puts("PASS");
610 else
611 {
612 status ++;
613 printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n",
614 text ? text : "(null)");
615 }
616
617 putenv("LANG=zh_TW");
618 putenv("LC_ALL=zh_TW");
619 putenv("LC_CTYPE=zh_TW");
620 putenv("LC_MESSAGES=zh_TW");
621
622 fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout);
623 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
624 !strcmp(text, "Number 1 Cyan Toner"))
625 puts("PASS");
626 else
627 {
628 status ++;
629 printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n",
630 text ? text : "(null)");
631 }
632
633 ppdClose(ppd);
634
635 /*
636 * Test new constraints...
637 */
638
639 fputs("ppdOpenFile(test2.ppd): ", stdout);
640
641 if ((ppd = ppdOpenFile("test2.ppd")) != NULL)
642 puts("PASS");
643 else
644 {
645 ppd_status_t err; /* Last error in file */
646 int line; /* Line number in file */
647
648
649 status ++;
650 err = ppdLastError(&line);
651
652 printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
653 }
654
655 fputs("ppdMarkDefaults: ", stdout);
656 ppdMarkDefaults(ppd);
657
658 if ((conflicts = ppdConflicts(ppd)) == 0)
659 puts("PASS");
660 else
661 {
662 status ++;
663 printf("FAIL (%d conflicts)\n", conflicts);
664 }
665
666 fputs("ppdEmitString (defaults): ", stdout);
667 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
668 !strcmp(s, default2_code))
669 puts("PASS");
670 else
671 {
672 status ++;
673 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
674 (int)strlen(default2_code));
675
676 if (s)
677 puts(s);
678 }
679
680 if (s)
681 free(s);
682
683 fputs("ppdConflicts(): ", stdout);
684 ppdMarkOption(ppd, "PageSize", "Env10");
685 ppdMarkOption(ppd, "InputSlot", "Envelope");
686 ppdMarkOption(ppd, "Quality", "Photo");
687
688 if ((conflicts = ppdConflicts(ppd)) == 1)
689 puts("PASS (1)");
690 else
691 {
692 printf("FAIL (%d)\n", conflicts);
693 status ++;
694 }
695
696 fputs("cupsResolveConflicts(Quality=Photo): ", stdout);
697 num_options = 0;
698 options = NULL;
699 if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
700 &options))
701 {
702 printf("FAIL (%d options:", num_options);
703 for (i = 0; i < num_options; i ++)
704 printf(" %s=%s", options[i].name, options[i].value);
705 puts(")");
706 status ++;
707 }
708 else
709 puts("PASS (Unable to resolve)");
710 cupsFreeOptions(num_options, options);
711
712 fputs("cupsResolveConflicts(No option/choice): ", stdout);
713 num_options = 0;
714 options = NULL;
715 if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
716 num_options == 1 && !_cups_strcasecmp(options->name, "Quality") &&
717 !_cups_strcasecmp(options->value, "Normal"))
718 puts("PASS");
719 else if (num_options > 0)
720 {
721 printf("FAIL (%d options:", num_options);
722 for (i = 0; i < num_options; i ++)
723 printf(" %s=%s", options[i].name, options[i].value);
724 puts(")");
725 status ++;
726 }
727 else
728 {
729 puts("FAIL (Unable to resolve!)");
730 status ++;
731 }
732 cupsFreeOptions(num_options, options);
733
734 fputs("cupsResolveConflicts(loop test): ", stdout);
735 ppdMarkOption(ppd, "PageSize", "A4");
736 ppdMarkOption(ppd, "InputSlot", "Tray");
737 ppdMarkOption(ppd, "Quality", "Photo");
738 num_options = 0;
739 options = NULL;
740 if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options))
741 puts("PASS");
742 else if (num_options > 0)
743 {
744 printf("FAIL (%d options:", num_options);
745 for (i = 0; i < num_options; i ++)
746 printf(" %s=%s", options[i].name, options[i].value);
747 puts(")");
748 }
749 else
750 puts("FAIL (No conflicts!)");
751
752 fputs("ppdInstallableConflict(): ", stdout);
753 if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
754 !ppdInstallableConflict(ppd, "Duplex", "None"))
755 puts("PASS");
756 else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
757 {
758 puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
759 status ++;
760 }
761 else
762 {
763 puts("FAIL (Duplex=None conflicted)");
764 status ++;
765 }
766
767 /*
768 * ppdPageSizeLimits
769 */
770
771 ppdMarkDefaults(ppd);
772
773 fputs("ppdPageSizeLimits(default): ", stdout);
774 if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
775 {
776 if (fabs(minsize.width - 36.0) > 0.001 || fabs(minsize.length - 36.0) > 0.001 ||
777 fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001)
778 {
779 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
780 "expected min=36x36, max=1080x86400)\n", minsize.width,
781 minsize.length, maxsize.width, maxsize.length);
782 status ++;
783 }
784 else
785 puts("PASS");
786 }
787 else
788 {
789 puts("FAIL (returned 0)");
790 status ++;
791 }
792
793 ppdMarkOption(ppd, "InputSlot", "Manual");
794
795 fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout);
796 if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
797 {
798 if (fabs(minsize.width - 100.0) > 0.001 || fabs(minsize.length - 100.0) > 0.001 ||
799 fabs(maxsize.width - 1000.0) > 0.001 || fabs(maxsize.length - 1000.0) > 0.001)
800 {
801 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
802 "expected min=100x100, max=1000x1000)\n", minsize.width,
803 minsize.length, maxsize.width, maxsize.length);
804 status ++;
805 }
806 else
807 puts("PASS");
808 }
809 else
810 {
811 puts("FAIL (returned 0)");
812 status ++;
813 }
814
815 ppdMarkOption(ppd, "Quality", "Photo");
816
817 fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
818 if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
819 {
820 if (fabs(minsize.width - 200.0) > 0.001 || fabs(minsize.length - 200.0) > 0.001 ||
821 fabs(maxsize.width - 1000.0) > 0.001 || fabs(maxsize.length - 1000.0) > 0.001)
822 {
823 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
824 "expected min=200x200, max=1000x1000)\n", minsize.width,
825 minsize.length, maxsize.width, maxsize.length);
826 status ++;
827 }
828 else
829 puts("PASS");
830 }
831 else
832 {
833 puts("FAIL (returned 0)");
834 status ++;
835 }
836
837 ppdMarkOption(ppd, "InputSlot", "Tray");
838
839 fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
840 if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
841 {
842 if (fabs(minsize.width - 300.0) > 0.001 || fabs(minsize.length - 300.0) > 0.001 ||
843 fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001)
844 {
845 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
846 "expected min=300x300, max=1080x86400)\n", minsize.width,
847 minsize.length, maxsize.width, maxsize.length);
848 status ++;
849 }
850 else
851 puts("PASS");
852 }
853 else
854 {
855 puts("FAIL (returned 0)");
856 status ++;
857 }
858 }
859 else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7))
860 {
861 /*
862 * ipp://... or ipps://...
863 */
864
865 http_t *http; /* Connection to printer */
866 ipp_t *request, /* Get-Printer-Attributes request */
867 *response; /* Get-Printer-Attributes response */
868 char scheme[32], /* URI scheme */
869 userpass[256], /* Username:password */
870 host[256], /* Hostname */
871 resource[256]; /* Resource path */
872 int port; /* Port number */
873 static const char * const pattrs[] =/* Requested printer attributes */
874 {
875 "job-template",
876 "printer-defaults",
877 "printer-description",
878 "media-col-database"
879 };
880
881 if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
882 {
883 printf("Bad URI \"%s\".\n", argv[1]);
884 return (1);
885 }
886
887 http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
888 if (!http)
889 {
890 printf("Unable to connect to \"%s:%d\": %s\n", host, port, cupsLastErrorString());
891 return (1);
892 }
893
894 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
895 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, argv[1]);
896 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs);
897 response = cupsDoRequest(http, request, resource);
898
899 if (_ppdCreateFromIPP(buffer, sizeof(buffer), response))
900 printf("Created PPD: %s\n", buffer);
901 else
902 puts("Unable to create PPD.");
903
904 ippDelete(response);
905 httpClose(http);
906 return (0);
907 }
908 else
909 {
910 const char *filename; /* PPD filename */
911 struct stat fileinfo; /* File information */
912
913
914 if (strchr(argv[1], ':'))
915 {
916 /*
917 * Server PPD...
918 */
919
920 if ((filename = cupsGetServerPPD(CUPS_HTTP_DEFAULT, argv[1])) == NULL)
921 {
922 printf("%s: %s\n", argv[1], cupsLastErrorString());
923 return (1);
924 }
925 }
926 else if (!strncmp(argv[1], "-d", 2))
927 {
928 const char *printer; /* Printer name */
929
930 if (argv[1][2])
931 printer = argv[1] + 2;
932 else if (argv[2])
933 printer = argv[2];
934 else
935 {
936 puts("Usage: ./testppd -d printer");
937 return (1);
938 }
939
940 filename = cupsGetPPD(printer);
941
942 if (!filename)
943 {
944 printf("%s: %s\n", printer, cupsLastErrorString());
945 return (1);
946 }
947 }
948 else
949 filename = argv[1];
950
951 if (lstat(filename, &fileinfo))
952 {
953 printf("%s: %s\n", filename, strerror(errno));
954 return (1);
955 }
956
957 if (S_ISLNK(fileinfo.st_mode))
958 {
959 char realfile[1024]; /* Real file path */
960 ssize_t realsize; /* Size of real file path */
961
962
963 if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0)
964 strlcpy(realfile, "Unknown", sizeof(realfile));
965 else
966 realfile[realsize] = '\0';
967
968 if (stat(realfile, &fileinfo))
969 printf("%s: symlink to \"%s\", %s\n", filename, realfile,
970 strerror(errno));
971 else
972 printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile,
973 (long)fileinfo.st_size);
974 }
975 else
976 printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size);
977
978 if ((ppd = ppdOpenFile(filename)) == NULL)
979 {
980 ppd_status_t err; /* Last error in file */
981 int line; /* Line number in file */
982
983
984 status ++;
985 err = ppdLastError(&line);
986
987 printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line);
988 }
989 else
990 {
991 int j, k; /* Looping vars */
992 ppd_group_t *group; /* Option group */
993 ppd_option_t *option; /* Option */
994 ppd_coption_t *coption; /* Custom option */
995 ppd_cparam_t *cparam; /* Custom parameter */
996 ppd_const_t *c; /* UIConstraints */
997 char lang[255], /* LANG environment variable */
998 lc_all[255], /* LC_ALL environment variable */
999 lc_ctype[255], /* LC_CTYPE environment variable */
1000 lc_messages[255];/* LC_MESSAGES environment variable */
1001
1002
1003 if (argc > 2)
1004 {
1005 snprintf(lang, sizeof(lang), "LANG=%s", argv[2]);
1006 putenv(lang);
1007 snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]);
1008 putenv(lc_all);
1009 snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]);
1010 putenv(lc_ctype);
1011 snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]);
1012 putenv(lc_messages);
1013 }
1014
1015 ppdLocalize(ppd);
1016 ppdMarkDefaults(ppd);
1017
1018 if (argc > 3)
1019 {
1020 text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer));
1021 printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3],
1022 text ? text : "(null)");
1023 return (text == NULL);
1024 }
1025
1026 for (i = ppd->num_groups, group = ppd->groups;
1027 i > 0;
1028 i --, group ++)
1029 {
1030 printf("%s (%s):\n", group->name, group->text);
1031
1032 for (j = group->num_options, option = group->options;
1033 j > 0;
1034 j --, option ++)
1035 {
1036 printf(" %s (%s):\n", option->keyword, option->text);
1037
1038 for (k = 0; k < option->num_choices; k ++)
1039 printf(" - %s%s (%s)\n",
1040 option->choices[k].marked ? "*" : "",
1041 option->choices[k].choice, option->choices[k].text);
1042
1043 if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
1044 {
1045 for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
1046 cparam;
1047 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
1048 {
1049 switch (cparam->type)
1050 {
1051 case PPD_CUSTOM_CURVE :
1052 printf(" %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n",
1053 cparam->name, cparam->text,
1054 cparam->minimum.custom_curve,
1055 cparam->maximum.custom_curve);
1056 break;
1057
1058 case PPD_CUSTOM_INT :
1059 printf(" %s(%s): PPD_CUSTOM_INT (%d to %d)\n",
1060 cparam->name, cparam->text,
1061 cparam->minimum.custom_int,
1062 cparam->maximum.custom_int);
1063 break;
1064
1065 case PPD_CUSTOM_INVCURVE :
1066 printf(" %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n",
1067 cparam->name, cparam->text,
1068 cparam->minimum.custom_invcurve,
1069 cparam->maximum.custom_invcurve);
1070 break;
1071
1072 case PPD_CUSTOM_PASSCODE :
1073 printf(" %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n",
1074 cparam->name, cparam->text,
1075 cparam->minimum.custom_passcode,
1076 cparam->maximum.custom_passcode);
1077 break;
1078
1079 case PPD_CUSTOM_PASSWORD :
1080 printf(" %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n",
1081 cparam->name, cparam->text,
1082 cparam->minimum.custom_password,
1083 cparam->maximum.custom_password);
1084 break;
1085
1086 case PPD_CUSTOM_POINTS :
1087 printf(" %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n",
1088 cparam->name, cparam->text,
1089 cparam->minimum.custom_points,
1090 cparam->maximum.custom_points);
1091 break;
1092
1093 case PPD_CUSTOM_REAL :
1094 printf(" %s(%s): PPD_CUSTOM_REAL (%g to %g)\n",
1095 cparam->name, cparam->text,
1096 cparam->minimum.custom_real,
1097 cparam->maximum.custom_real);
1098 break;
1099
1100 case PPD_CUSTOM_STRING :
1101 printf(" %s(%s): PPD_CUSTOM_STRING (%d to %d)\n",
1102 cparam->name, cparam->text,
1103 cparam->minimum.custom_string,
1104 cparam->maximum.custom_string);
1105 break;
1106 }
1107 }
1108 }
1109 }
1110 }
1111
1112 puts("\nSizes:");
1113 for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
1114 printf(" %s = %gx%g, [%g %g %g %g]\n", size->name, size->width,
1115 size->length, size->left, size->bottom, size->right, size->top);
1116
1117 puts("\nConstraints:");
1118
1119 for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
1120 printf(" *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
1121 c->option2, c->choice2);
1122 if (ppd->num_consts == 0)
1123 puts(" NO CONSTRAINTS");
1124
1125 puts("\nFilters:");
1126
1127 for (i = 0; i < ppd->num_filters; i ++)
1128 printf(" %s\n", ppd->filters[i]);
1129
1130 if (ppd->num_filters == 0)
1131 puts(" NO FILTERS");
1132
1133 puts("\nAttributes:");
1134
1135 for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
1136 attr;
1137 attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
1138 printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec,
1139 attr->text, attr->value ? attr->value : "");
1140
1141 puts("\nPPD Cache:");
1142 if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
1143 printf(" Unable to create: %s\n", cupsLastErrorString());
1144 else
1145 {
1146 _ppdCacheWriteFile(pc, "t.cache", NULL);
1147 puts(" Wrote t.cache.");
1148 }
1149 }
1150
1151 if (!strncmp(argv[1], "-d", 2))
1152 unlink(filename);
1153 }
1154
1155 #ifdef __APPLE__
1156 if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact"))
1157 {
1158 char command[1024]; /* malloc_history command */
1159
1160 snprintf(command, sizeof(command), "malloc_history %d -all_by_size",
1161 getpid());
1162 fflush(stdout);
1163 system(command);
1164 }
1165 #endif /* __APPLE__ */
1166
1167 ppdClose(ppd);
1168
1169 return (status);
1170 }