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