]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/testppd.c
License change: Apache License, Version 2.0.
[thirdparty/cups.git] / cups / testppd.c
CommitLineData
fa73b229 1/*
7e86f2f6 2 * PPD test program for CUPS.
fa73b229 3 *
4886d674 4 * Copyright 2007-2017 by Apple Inc.
7e86f2f6 5 * Copyright 1997-2006 by Easy Software Products.
fa73b229 6 *
e3101897 7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
fa73b229 8 */
9
10/*
11 * Include necessary headers...
12 */
13
5489ad43 14#undef _CUPS_NO_DEPRECATED
71e16022 15#include "cups-private.h"
f787e1e3 16#include "ppd-private.h"
c9fc04c6 17#include <sys/stat.h>
fa73b229 18#ifdef WIN32
19# include <io.h>
20#else
21# include <unistd.h>
22# include <fcntl.h>
23#endif /* WIN32 */
07623986 24#include <math.h>
fa73b229 25
26
e1d6a774 27/*
28 * Test data...
29 */
30
31static const char *default_code =
66ab9486
MS
32 "[{\n"
33 "%%BeginFeature: *InstalledDuplexer False\n"
34 "%%EndFeature\n"
35 "} stopped cleartomark\n"
e1d6a774 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"
8ca02f3c 45 "} stopped cleartomark\n"
46 "[{\n"
20aa0765
MS
47 "%%BeginFeature: *OutputBin Tray1\n"
48 "OutputBin=Tray1\n"
49 "%%EndFeature\n"
50 "} stopped cleartomark\n"
51 "[{\n"
54afec33
MS
52 "%%BeginFeature: *MediaType Plain\n"
53 "MediaType=Plain\n"
54 "%%EndFeature\n"
55 "} stopped cleartomark\n"
56 "[{\n"
8ca02f3c 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
65static const char *custom_code =
66ab9486
MS
66 "[{\n"
67 "%%BeginFeature: *InstalledDuplexer False\n"
68 "%%EndFeature\n"
69 "} stopped cleartomark\n"
8ca02f3c 70 "[{\n"
71 "%%BeginFeature: *InputSlot Tray\n"
72 "InputSlot=Tray\n"
73 "%%EndFeature\n"
74 "} stopped cleartomark\n"
75 "[{\n"
54afec33
MS
76 "%%BeginFeature: *MediaType Plain\n"
77 "MediaType=Plain\n"
78 "%%EndFeature\n"
79 "} stopped cleartomark\n"
80 "[{\n"
20aa0765
MS
81 "%%BeginFeature: *OutputBin Tray1\n"
82 "OutputBin=Tray1\n"
83 "%%EndFeature\n"
84 "} stopped cleartomark\n"
85 "[{\n"
8ca02f3c 86 "%%BeginFeature: *IntOption None\n"
87 "%%EndFeature\n"
88 "} stopped cleartomark\n"
89 "[{\n"
ee571f26
MS
90 "%%BeginFeature: *CustomStringOption True\n"
91 "(value\\0502\\051)\n"
92 "(value 1)\n"
93 "StringOption=Custom\n"
8ca02f3c 94 "%%EndFeature\n"
0a682745
MS
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"
e1d6a774 105 "} stopped cleartomark\n";
106
f11a948a
MS
107static 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
e1d6a774 131
fa73b229 132/*
133 * 'main()' - Main entry.
134 */
135
136int /* O - Exit status */
137main(int argc, /* I - Number of command-line arguments */
138 char *argv[]) /* I - Command-line arguments */
139{
66ab9486 140 int i; /* Looping var */
fa73b229 141 ppd_file_t *ppd; /* PPD file loaded from disk */
142 int status; /* Status of tests (0 = success, 1 = fail) */
e1d6a774 143 int conflicts; /* Number of conflicts */
144 char *s; /* String */
bc44d920 145 char buffer[8192]; /* String buffer */
d2354e63
MS
146 const char *text, /* Localized text */
147 *val; /* Option value */
66ab9486
MS
148 int num_options; /* Number of options */
149 cups_option_t *options; /* Options */
005dd1eb 150 ppd_size_t minsize, /* Minimum size */
c168a833
MS
151 maxsize, /* Maximum size */
152 *size; /* Current size */
6e8b116d 153 ppd_attr_t *attr; /* Current attribute */
5a9febac 154 _ppd_cache_t *pc; /* PPD cache */
fa73b229 155
156
157 status = 0;
158
a74454a7 159 if (argc == 1)
fa73b229 160 {
c9fc04c6
MS
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");
b0f6947b 175 putenv("SOFTWARE=CUPS");
c9fc04c6
MS
176
177 /*
178 * Do tests with test.ppd...
179 */
180
66ab9486 181 fputs("ppdOpenFile(test.ppd): ", stdout);
a74454a7 182
9c80ffa2 183 if ((ppd = _ppdOpenFile("test.ppd", _PPD_LOCALIZATION_ALL)) != NULL)
a74454a7 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
6e8b116d
MS
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
a74454a7 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
8ca02f3c 259 fputs("ppdEmitString (defaults): ", stdout);
a74454a7 260 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
261 !strcmp(s, default_code))
262 puts("PASS");
263 else
264 {
bc44d920 265 status ++;
a74454a7 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);
ed486911 271 }
272
8ca02f3c 273 if (s)
274 free(s);
275
ee571f26 276 fputs("ppdEmitString (custom size and string): ", stdout);
8ca02f3c 277 ppdMarkOption(ppd, "PageSize", "Custom.400x500");
ee571f26 278 ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}");
8ca02f3c 279
280 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
281 !strcmp(s, custom_code))
282 puts("PASS");
283 else
284 {
bc44d920 285 status ++;
8ca02f3c 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
a74454a7 293 if (s)
294 free(s);
e1d6a774 295
66ab9486
MS
296 /*
297 * Test constraints...
298 */
299
d2354e63 300 fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout);
66ab9486 301 ppdMarkOption(ppd, "PageSize", "Letter");
d2354e63
MS
302
303 num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options);
304 if (num_options != 2 ||
305 (val = cupsGetOption("PageRegion", num_options, options)) == NULL ||
88f9aafc 306 _cups_strcasecmp(val, "Letter") ||
d2354e63 307 (val = cupsGetOption("PageSize", num_options, options)) == NULL ||
88f9aafc 308 _cups_strcasecmp(val, "Letter"))
d2354e63
MS
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);
66ab9486
MS
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
06d4e77b 330 fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout);
66ab9486
MS
331 num_options = 0;
332 options = NULL;
c168a833 333 if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options,
06d4e77b
MS
334 &options))
335 {
c168a833
MS
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(")");
06d4e77b
MS
346 status ++;
347 }
348 else
c168a833
MS
349 puts("PASS (Resolved by changing PageSize)");
350
06d4e77b
MS
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) &&
88f9aafc
MS
357 num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") &&
358 !_cups_strcasecmp(options[0].value, "Tray"))
c168a833 359 puts("PASS (Resolved by changing InputSlot)");
66ab9486
MS
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 {
06d4e77b 370 puts("FAIL (Unable to resolve)");
66ab9486
MS
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
005dd1eb
MS
390 /*
391 * ppdPageSizeLimits
392 */
393
394 fputs("ppdPageSizeLimits: ", stdout);
395 if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
396 {
7e86f2f6
MS
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)
005dd1eb 399 {
7e86f2f6 400 printf("FAIL (got min=%.3fx%.3f, max=%.3fx%.3f, "
005dd1eb
MS
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
c168a833
MS
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
f14324a7
MS
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
cc754834
MS
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
dcb445bc
MS
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") ||
7e86f2f6
MS
486 fabs(size->width - 576.0) > 0.001 ||
487 fabs(size->length - 720.0) > 0.001)
dcb445bc
MS
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
bc44d920 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");
c5571a1d
MS
541 putenv("LC_ALL=fr");
542 putenv("LC_CTYPE=fr");
543 putenv("LC_MESSAGES=fr");
bc44d920 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
db1f069b 555 putenv("LANG=zh_TW");
c5571a1d
MS
556 putenv("LC_ALL=zh_TW");
557 putenv("LC_CTYPE=zh_TW");
558 putenv("LC_MESSAGES=zh_TW");
db1f069b
MS
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 }
5a738aea
MS
569
570 /*
571 * cupsMarkerName localization...
572 */
573
574 putenv("LANG=en");
c5571a1d
MS
575 putenv("LC_ALL=en");
576 putenv("LC_CTYPE=en");
577 putenv("LC_MESSAGES=en");
5a738aea
MS
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");
c5571a1d
MS
602 putenv("LC_ALL=fr");
603 putenv("LC_CTYPE=fr");
604 putenv("LC_MESSAGES=fr");
5a738aea
MS
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");
c5571a1d
MS
618 putenv("LC_ALL=zh_TW");
619 putenv("LC_CTYPE=zh_TW");
620 putenv("LC_MESSAGES=zh_TW");
5a738aea
MS
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 }
66ab9486
MS
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
f11a948a
MS
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
66ab9486
MS
683 fputs("ppdConflicts(): ", stdout);
684 ppdMarkOption(ppd, "PageSize", "Env10");
685 ppdMarkOption(ppd, "InputSlot", "Envelope");
686 ppdMarkOption(ppd, "Quality", "Photo");
687
1340db2d
MS
688 if ((conflicts = ppdConflicts(ppd)) == 1)
689 puts("PASS (1)");
66ab9486
MS
690 else
691 {
692 printf("FAIL (%d)\n", conflicts);
693 status ++;
694 }
695
06d4e77b 696 fputs("cupsResolveConflicts(Quality=Photo): ", stdout);
66ab9486
MS
697 num_options = 0;
698 options = NULL;
699 if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
06d4e77b
MS
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) &&
88f9aafc
MS
716 num_options == 1 && !_cups_strcasecmp(options->name, "Quality") &&
717 !_cups_strcasecmp(options->value, "Normal"))
66ab9486
MS
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");
1340db2d 736 ppdMarkOption(ppd, "InputSlot", "Tray");
66ab9486
MS
737 ppdMarkOption(ppd, "Quality", "Photo");
738 num_options = 0;
739 options = NULL;
06d4e77b 740 if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options))
66ab9486
MS
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!)");
6d2f911b 751
66ab9486
MS
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 }
005dd1eb
MS
766
767 /*
768 * ppdPageSizeLimits
769 */
770
771 ppdMarkDefaults(ppd);
772
773 fputs("ppdPageSizeLimits(default): ", stdout);
774 if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
775 {
7e86f2f6
MS
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)
005dd1eb
MS
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 {
7e86f2f6
MS
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)
005dd1eb
MS
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 {
7e86f2f6
MS
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)
005dd1eb
MS
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 {
7e86f2f6
MS
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)
005dd1eb
MS
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 }
e1d6a774 858 }
d9fc71e4
MS
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
874 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)
875 {
876 printf("Bad URI \"%s\".\n", argv[1]);
877 return (1);
878 }
879
880 http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
881 if (!http)
882 {
883 printf("Unable to connect to \"%s:%d\": %s\n", host, port, cupsLastErrorString());
884 return (1);
885 }
886
887 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
888 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, argv[1]);
889 response = cupsDoRequest(http, request, resource);
890
891 if (_ppdCreateFromIPP(buffer, sizeof(buffer), response))
892 printf("Created PPD: %s\n", buffer);
893 else
894 puts("Unable to create PPD.");
895
896 ippDelete(response);
fffed089 897 httpClose(http);
d9fc71e4
MS
898 return (0);
899 }
e1d6a774 900 else
901 {
dd1abb6b 902 const char *filename; /* PPD filename */
d1c13e16 903 struct stat fileinfo; /* File information */
dd1abb6b
MS
904
905
61c9d9f8
MS
906 if (strchr(argv[1], ':'))
907 {
908 /*
909 * Server PPD...
910 */
911
912 if ((filename = cupsGetServerPPD(CUPS_HTTP_DEFAULT, argv[1])) == NULL)
913 {
914 printf("%s: %s\n", argv[1], cupsLastErrorString());
915 return (1);
916 }
917 }
918 else if (!strncmp(argv[1], "-d", 2))
749b1e90 919 {
c8fef167
MS
920 const char *printer; /* Printer name */
921
922 if (argv[1][2])
923 printer = argv[1] + 2;
924 else if (argv[2])
925 printer = argv[2];
926 else
927 {
928 puts("Usage: ./testppd -d printer");
929 return (1);
930 }
931
932 filename = cupsGetPPD(printer);
933
749b1e90
MS
934 if (!filename)
935 {
c8fef167 936 printf("%s: %s\n", printer, cupsLastErrorString());
749b1e90
MS
937 return (1);
938 }
939 }
dd1abb6b
MS
940 else
941 filename = argv[1];
942
d1c13e16
MS
943 if (lstat(filename, &fileinfo))
944 {
945 printf("%s: %s\n", filename, strerror(errno));
946 return (1);
947 }
948
949 if (S_ISLNK(fileinfo.st_mode))
950 {
951 char realfile[1024]; /* Real file path */
952 ssize_t realsize; /* Size of real file path */
953
954
955 if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0)
5a9febac 956 strlcpy(realfile, "Unknown", sizeof(realfile));
d1c13e16
MS
957 else
958 realfile[realsize] = '\0';
959
960 if (stat(realfile, &fileinfo))
961 printf("%s: symlink to \"%s\", %s\n", filename, realfile,
962 strerror(errno));
963 else
964 printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile,
965 (long)fileinfo.st_size);
966 }
967 else
968 printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size);
969
dd1abb6b 970 if ((ppd = ppdOpenFile(filename)) == NULL)
a74454a7 971 {
972 ppd_status_t err; /* Last error in file */
973 int line; /* Line number in file */
974
975
976 status ++;
977 err = ppdLastError(&line);
978
979 printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line);
980 }
981 else
982 {
66ab9486 983 int j, k; /* Looping vars */
a74454a7 984 ppd_group_t *group; /* Option group */
985 ppd_option_t *option; /* Option */
b86bc4cf 986 ppd_coption_t *coption; /* Custom option */
987 ppd_cparam_t *cparam; /* Custom parameter */
66ab9486 988 ppd_const_t *c; /* UIConstraints */
c5571a1d
MS
989 char lang[255], /* LANG environment variable */
990 lc_all[255], /* LC_ALL environment variable */
991 lc_ctype[255], /* LC_CTYPE environment variable */
992 lc_messages[255];/* LC_MESSAGES environment variable */
a74454a7 993
994
d09495fa 995 if (argc > 2)
996 {
997 snprintf(lang, sizeof(lang), "LANG=%s", argv[2]);
998 putenv(lang);
c5571a1d
MS
999 snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]);
1000 putenv(lc_all);
1001 snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]);
1002 putenv(lc_ctype);
1003 snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]);
1004 putenv(lc_messages);
d09495fa 1005 }
1006
a74454a7 1007 ppdLocalize(ppd);
f0ab5bff 1008 ppdMarkDefaults(ppd);
a74454a7 1009
e4572d57
MS
1010 if (argc > 3)
1011 {
1012 text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer));
1013 printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3],
1014 text ? text : "(null)");
1015 return (text == NULL);
1016 }
1017
a74454a7 1018 for (i = ppd->num_groups, group = ppd->groups;
1019 i > 0;
1020 i --, group ++)
1021 {
1022 printf("%s (%s):\n", group->name, group->text);
d09495fa 1023
a74454a7 1024 for (j = group->num_options, option = group->options;
1025 j > 0;
1026 j --, option ++)
1027 {
1028 printf(" %s (%s):\n", option->keyword, option->text);
1029
1030 for (k = 0; k < option->num_choices; k ++)
f0ab5bff
MS
1031 printf(" - %s%s (%s)\n",
1032 option->choices[k].marked ? "*" : "",
1033 option->choices[k].choice, option->choices[k].text);
b86bc4cf 1034
1035 if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
1036 {
1037 for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
1038 cparam;
1039 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
1040 {
1041 switch (cparam->type)
1042 {
1043 case PPD_CUSTOM_CURVE :
1044 printf(" %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n",
1045 cparam->name, cparam->text,
1046 cparam->minimum.custom_curve,
1047 cparam->maximum.custom_curve);
1048 break;
1049
1050 case PPD_CUSTOM_INT :
1051 printf(" %s(%s): PPD_CUSTOM_INT (%d to %d)\n",
1052 cparam->name, cparam->text,
1053 cparam->minimum.custom_int,
1054 cparam->maximum.custom_int);
1055 break;
1056
1057 case PPD_CUSTOM_INVCURVE :
1058 printf(" %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n",
1059 cparam->name, cparam->text,
1060 cparam->minimum.custom_invcurve,
1061 cparam->maximum.custom_invcurve);
1062 break;
1063
1064 case PPD_CUSTOM_PASSCODE :
1065 printf(" %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n",
1066 cparam->name, cparam->text,
1067 cparam->minimum.custom_passcode,
1068 cparam->maximum.custom_passcode);
1069 break;
1070
1071 case PPD_CUSTOM_PASSWORD :
1072 printf(" %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n",
1073 cparam->name, cparam->text,
1074 cparam->minimum.custom_password,
1075 cparam->maximum.custom_password);
1076 break;
1077
1078 case PPD_CUSTOM_POINTS :
1079 printf(" %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n",
1080 cparam->name, cparam->text,
1081 cparam->minimum.custom_points,
1082 cparam->maximum.custom_points);
1083 break;
1084
1085 case PPD_CUSTOM_REAL :
1086 printf(" %s(%s): PPD_CUSTOM_REAL (%g to %g)\n",
1087 cparam->name, cparam->text,
1088 cparam->minimum.custom_real,
1089 cparam->maximum.custom_real);
1090 break;
1091
1092 case PPD_CUSTOM_STRING :
1093 printf(" %s(%s): PPD_CUSTOM_STRING (%d to %d)\n",
1094 cparam->name, cparam->text,
1095 cparam->minimum.custom_string,
1096 cparam->maximum.custom_string);
1097 break;
1098 }
1099 }
1100 }
a74454a7 1101 }
1102 }
d09495fa 1103
030ae6a1
MS
1104 puts("\nSizes:");
1105 for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
1106 printf(" %s = %gx%g, [%g %g %g %g]\n", size->name, size->width,
1107 size->length, size->left, size->bottom, size->right, size->top);
1108
1340db2d 1109 puts("\nConstraints:");
66ab9486
MS
1110
1111 for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
1112 printf(" *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
1113 c->option2, c->choice2);
1340db2d
MS
1114 if (ppd->num_consts == 0)
1115 puts(" NO CONSTRAINTS");
1116
1117 puts("\nFilters:");
1118
1119 for (i = 0; i < ppd->num_filters; i ++)
1120 printf(" %s\n", ppd->filters[i]);
1121
1122 if (ppd->num_filters == 0)
1123 puts(" NO FILTERS");
66ab9486 1124
1340db2d 1125 puts("\nAttributes:");
d09495fa 1126
1127 for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
1128 attr;
1129 attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
1130 printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec,
1131 attr->text, attr->value ? attr->value : "");
5a9febac
MS
1132
1133 puts("\nPPD Cache:");
1134 if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
1135 printf(" Unable to create: %s\n", cupsLastErrorString());
1136 else
1137 {
1138 _ppdCacheWriteFile(pc, "t.cache", NULL);
1139 puts(" Wrote t.cache.");
1140 }
a74454a7 1141 }
dd1abb6b
MS
1142
1143 if (!strncmp(argv[1], "-d", 2))
1144 unlink(filename);
e1d6a774 1145 }
1146
2e4ff8af
MS
1147#ifdef __APPLE__
1148 if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact"))
1149 {
1150 char command[1024]; /* malloc_history command */
1151
1152 snprintf(command, sizeof(command), "malloc_history %d -all_by_size",
1153 getpid());
1154 fflush(stdout);
1155 system(command);
1156 }
1157#endif /* __APPLE__ */
1158
1159 ppdClose(ppd);
1160
fa73b229 1161 return (status);
1162}