]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testppd.c
Merge CUPS 1.4svn-r7762.
[thirdparty/cups.git] / cups / testppd.c
1 /*
2 * "$Id: testppd.c 7633 2008-06-10 23:07:29Z mike $"
3 *
4 * PPD test program for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007-2008 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 * Contents:
18 *
19 * main() - Main entry.
20 */
21
22 /*
23 * Include necessary headers...
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <cups/string.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #include "cups.h"
32 #ifdef WIN32
33 # include <io.h>
34 #else
35 # include <unistd.h>
36 # include <fcntl.h>
37 #endif /* WIN32 */
38
39
40 /*
41 * Test data...
42 */
43
44 static const char *default_code =
45 "[{\n"
46 "%%BeginFeature: *InstalledDuplexer False\n"
47 "%%EndFeature\n"
48 "} stopped cleartomark\n"
49 "[{\n"
50 "%%BeginFeature: *PageRegion Letter\n"
51 "PageRegion=Letter\n"
52 "%%EndFeature\n"
53 "} stopped cleartomark\n"
54 "[{\n"
55 "%%BeginFeature: *InputSlot Tray\n"
56 "InputSlot=Tray\n"
57 "%%EndFeature\n"
58 "} stopped cleartomark\n"
59 "[{\n"
60 "%%BeginFeature: *IntOption None\n"
61 "%%EndFeature\n"
62 "} stopped cleartomark\n"
63 "[{\n"
64 "%%BeginFeature: *StringOption None\n"
65 "%%EndFeature\n"
66 "} stopped cleartomark\n";
67
68 static const char *custom_code =
69 "[{\n"
70 "%%BeginFeature: *InstalledDuplexer False\n"
71 "%%EndFeature\n"
72 "} stopped cleartomark\n"
73 "[{\n"
74 "%%BeginFeature: *InputSlot Tray\n"
75 "InputSlot=Tray\n"
76 "%%EndFeature\n"
77 "} stopped cleartomark\n"
78 "[{\n"
79 "%%BeginFeature: *IntOption None\n"
80 "%%EndFeature\n"
81 "} stopped cleartomark\n"
82 "[{\n"
83 "%%BeginFeature: *StringOption None\n"
84 "%%EndFeature\n"
85 "} stopped cleartomark\n"
86 "[{\n"
87 "%%BeginFeature: *CustomPageSize True\n"
88 "400\n"
89 "500\n"
90 "0\n"
91 "0\n"
92 "0\n"
93 "PageSize=Custom\n"
94 "%%EndFeature\n"
95 "} stopped cleartomark\n";
96
97
98 /*
99 * 'main()' - Main entry.
100 */
101
102 int /* O - Exit status */
103 main(int argc, /* I - Number of command-line arguments */
104 char *argv[]) /* I - Command-line arguments */
105 {
106 int i; /* Looping var */
107 ppd_file_t *ppd; /* PPD file loaded from disk */
108 int status; /* Status of tests (0 = success, 1 = fail) */
109 int conflicts; /* Number of conflicts */
110 char *s; /* String */
111 char buffer[8192]; /* String buffer */
112 const char *text; /* Localized text */
113 int num_options; /* Number of options */
114 cups_option_t *options; /* Options */
115
116
117 status = 0;
118
119 if (argc == 1)
120 {
121 /*
122 * Setup directories for locale stuff...
123 */
124
125 if (access("locale", 0))
126 {
127 mkdir("locale", 0777);
128 mkdir("locale/fr", 0777);
129 symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po");
130 mkdir("locale/zh_TW", 0777);
131 symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po");
132 }
133
134 putenv("LOCALEDIR=locale");
135
136 /*
137 * Do tests with test.ppd...
138 */
139
140 fputs("ppdOpenFile(test.ppd): ", stdout);
141
142 if ((ppd = ppdOpenFile("test.ppd")) != NULL)
143 puts("PASS");
144 else
145 {
146 ppd_status_t err; /* Last error in file */
147 int line; /* Line number in file */
148
149
150 status ++;
151 err = ppdLastError(&line);
152
153 printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
154 }
155
156 fputs("ppdMarkDefaults: ", stdout);
157 ppdMarkDefaults(ppd);
158
159 if ((conflicts = ppdConflicts(ppd)) == 0)
160 puts("PASS");
161 else
162 {
163 status ++;
164 printf("FAIL (%d conflicts)\n", conflicts);
165 }
166
167 fputs("ppdEmitString (defaults): ", stdout);
168 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
169 !strcmp(s, default_code))
170 puts("PASS");
171 else
172 {
173 status ++;
174 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
175 (int)strlen(default_code));
176
177 if (s)
178 puts(s);
179 }
180
181 if (s)
182 free(s);
183
184 fputs("ppdEmitString (custom size): ", stdout);
185 ppdMarkOption(ppd, "PageSize", "Custom.400x500");
186
187 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
188 !strcmp(s, custom_code))
189 puts("PASS");
190 else
191 {
192 status ++;
193 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
194 (int)strlen(custom_code));
195
196 if (s)
197 puts(s);
198 }
199
200 if (s)
201 free(s);
202
203 /*
204 * Test constraints...
205 */
206
207 fputs("ppdConflicts(): ", stdout);
208 ppdMarkOption(ppd, "PageSize", "Letter");
209 ppdMarkOption(ppd, "InputSlot", "Envelope");
210
211 if ((conflicts = ppdConflicts(ppd)) == 2)
212 puts("PASS (2)");
213 else
214 {
215 printf("FAIL (%d)\n", conflicts);
216 status ++;
217 }
218
219 fputs("cupsResolveConflicts(): ", stdout);
220 num_options = 0;
221 options = NULL;
222 if (cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options,
223 &options) &&
224 num_options == 1 && !strcasecmp(options->name, "InputSlot") &&
225 !strcasecmp(options->value, "Tray"))
226 puts("PASS");
227 else if (num_options > 0)
228 {
229 printf("FAIL (%d options:", num_options);
230 for (i = 0; i < num_options; i ++)
231 printf(" %s=%s", options[i].name, options[i].value);
232 puts(")");
233 status ++;
234 }
235 else
236 {
237 puts("FAIL (Unable to resolve!)");
238 status ++;
239 }
240 cupsFreeOptions(num_options, options);
241
242 fputs("ppdInstallableConflict(): ", stdout);
243 if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
244 !ppdInstallableConflict(ppd, "Duplex", "None"))
245 puts("PASS");
246 else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
247 {
248 puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
249 status ++;
250 }
251 else
252 {
253 puts("FAIL (Duplex=None conflicted)");
254 status ++;
255 }
256
257 /*
258 * Test localization...
259 */
260
261 fputs("ppdLocalizeIPPReason(text): ", stdout);
262 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
263 !strcmp(buffer, "Foo Reason"))
264 puts("PASS");
265 else
266 {
267 status ++;
268 printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer);
269 }
270
271 fputs("ppdLocalizeIPPReason(http): ", stdout);
272 if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) &&
273 !strcmp(buffer, "http://foo/bar.html"))
274 puts("PASS");
275 else
276 {
277 status ++;
278 printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer);
279 }
280
281 fputs("ppdLocalizeIPPReason(help): ", stdout);
282 if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) &&
283 !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help"))
284 puts("PASS");
285 else
286 {
287 status ++;
288 printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer);
289 }
290
291 fputs("ppdLocalizeIPPReason(file): ", stdout);
292 if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) &&
293 !strcmp(buffer, "/help/foo/bar.html"))
294 puts("PASS");
295 else
296 {
297 status ++;
298 printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer);
299 }
300
301 putenv("LANG=fr");
302
303 fputs("ppdLocalizeIPPReason(fr text): ", stdout);
304 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
305 !strcmp(buffer, "La Long Foo Reason"))
306 puts("PASS");
307 else
308 {
309 status ++;
310 printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer);
311 }
312
313 putenv("LANG=zh_TW");
314
315 fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout);
316 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
317 !strcmp(buffer, "Number 1 Foo Reason"))
318 puts("PASS");
319 else
320 {
321 status ++;
322 printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer);
323 }
324
325 /*
326 * cupsMarkerName localization...
327 */
328
329 putenv("LANG=en");
330
331 fputs("ppdLocalizeMarkerName(bogus): ", stdout);
332
333 if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL)
334 {
335 status ++;
336 printf("FAIL (\"%s\" instead of NULL)\n", text);
337 }
338 else
339 puts("PASS");
340
341 fputs("ppdLocalizeMarkerName(cyan): ", stdout);
342
343 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
344 !strcmp(text, "Cyan Toner"))
345 puts("PASS");
346 else
347 {
348 status ++;
349 printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n",
350 text ? text : "(null)");
351 }
352
353 putenv("LANG=fr");
354
355 fputs("ppdLocalizeMarkerName(fr cyan): ", stdout);
356 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
357 !strcmp(text, "La Toner Cyan"))
358 puts("PASS");
359 else
360 {
361 status ++;
362 printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n",
363 text ? text : "(null)");
364 }
365
366 putenv("LANG=zh_TW");
367
368 fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout);
369 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
370 !strcmp(text, "Number 1 Cyan Toner"))
371 puts("PASS");
372 else
373 {
374 status ++;
375 printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n",
376 text ? text : "(null)");
377 }
378
379 ppdClose(ppd);
380
381 /*
382 * Test new constraints...
383 */
384
385 fputs("ppdOpenFile(test2.ppd): ", stdout);
386
387 if ((ppd = ppdOpenFile("test2.ppd")) != NULL)
388 puts("PASS");
389 else
390 {
391 ppd_status_t err; /* Last error in file */
392 int line; /* Line number in file */
393
394
395 status ++;
396 err = ppdLastError(&line);
397
398 printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
399 }
400
401 fputs("ppdMarkDefaults: ", stdout);
402 ppdMarkDefaults(ppd);
403
404 if ((conflicts = ppdConflicts(ppd)) == 0)
405 puts("PASS");
406 else
407 {
408 status ++;
409 printf("FAIL (%d conflicts)\n", conflicts);
410 }
411
412 fputs("ppdConflicts(): ", stdout);
413 ppdMarkOption(ppd, "PageSize", "Env10");
414 ppdMarkOption(ppd, "InputSlot", "Envelope");
415 ppdMarkOption(ppd, "Quality", "Photo");
416
417 if ((conflicts = ppdConflicts(ppd)) == 2)
418 puts("PASS (2)");
419 else
420 {
421 printf("FAIL (%d)\n", conflicts);
422 status ++;
423 }
424
425 fputs("cupsResolveConflicts(): ", stdout);
426 num_options = 0;
427 options = NULL;
428 if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
429 &options) &&
430 num_options == 1 && !strcasecmp(options->name, "Quality") &&
431 !strcasecmp(options->value, "Normal"))
432 puts("PASS");
433 else if (num_options > 0)
434 {
435 printf("FAIL (%d options:", num_options);
436 for (i = 0; i < num_options; i ++)
437 printf(" %s=%s", options[i].name, options[i].value);
438 puts(")");
439 status ++;
440 }
441 else
442 {
443 puts("FAIL (Unable to resolve!)");
444 status ++;
445 }
446 cupsFreeOptions(num_options, options);
447
448 fputs("cupsResolveConflicts(loop test): ", stdout);
449 ppdMarkOption(ppd, "PageSize", "A4");
450 ppdMarkOption(ppd, "Quality", "Photo");
451 num_options = 0;
452 options = NULL;
453 if (!cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
454 &options))
455 puts("PASS");
456 else if (num_options > 0)
457 {
458 printf("FAIL (%d options:", num_options);
459 for (i = 0; i < num_options; i ++)
460 printf(" %s=%s", options[i].name, options[i].value);
461 puts(")");
462 }
463 else
464 puts("FAIL (No conflicts!)");
465
466 fputs("ppdInstallableConflict(): ", stdout);
467 if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
468 !ppdInstallableConflict(ppd, "Duplex", "None"))
469 puts("PASS");
470 else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
471 {
472 puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
473 status ++;
474 }
475 else
476 {
477 puts("FAIL (Duplex=None conflicted)");
478 status ++;
479 }
480 }
481 else
482 {
483 const char *filename; /* PPD filename */
484
485
486 if (!strncmp(argv[1], "-d", 2))
487 filename = cupsGetPPD(argv[1] + 2);
488 else
489 filename = argv[1];
490
491 if ((ppd = ppdOpenFile(filename)) == NULL)
492 {
493 ppd_status_t err; /* Last error in file */
494 int line; /* Line number in file */
495
496
497 status ++;
498 err = ppdLastError(&line);
499
500 printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line);
501 }
502 else
503 {
504 int j, k; /* Looping vars */
505 ppd_attr_t *attr; /* Current attribute */
506 ppd_group_t *group; /* Option group */
507 ppd_option_t *option; /* Option */
508 ppd_coption_t *coption; /* Custom option */
509 ppd_cparam_t *cparam; /* Custom parameter */
510 ppd_const_t *c; /* UIConstraints */
511 char lang[255]; /* LANG environment variable */
512
513
514 if (argc > 2)
515 {
516 snprintf(lang, sizeof(lang), "LANG=%s", argv[2]);
517 putenv(lang);
518 }
519
520 ppdLocalize(ppd);
521
522 for (i = ppd->num_groups, group = ppd->groups;
523 i > 0;
524 i --, group ++)
525 {
526 printf("%s (%s):\n", group->name, group->text);
527
528 for (j = group->num_options, option = group->options;
529 j > 0;
530 j --, option ++)
531 {
532 printf(" %s (%s):\n", option->keyword, option->text);
533
534 for (k = 0; k < option->num_choices; k ++)
535 printf(" - %s (%s)\n", option->choices[k].choice,
536 option->choices[k].text);
537
538 if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
539 {
540 for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
541 cparam;
542 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
543 {
544 switch (cparam->type)
545 {
546 case PPD_CUSTOM_CURVE :
547 printf(" %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n",
548 cparam->name, cparam->text,
549 cparam->minimum.custom_curve,
550 cparam->maximum.custom_curve);
551 break;
552
553 case PPD_CUSTOM_INT :
554 printf(" %s(%s): PPD_CUSTOM_INT (%d to %d)\n",
555 cparam->name, cparam->text,
556 cparam->minimum.custom_int,
557 cparam->maximum.custom_int);
558 break;
559
560 case PPD_CUSTOM_INVCURVE :
561 printf(" %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n",
562 cparam->name, cparam->text,
563 cparam->minimum.custom_invcurve,
564 cparam->maximum.custom_invcurve);
565 break;
566
567 case PPD_CUSTOM_PASSCODE :
568 printf(" %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n",
569 cparam->name, cparam->text,
570 cparam->minimum.custom_passcode,
571 cparam->maximum.custom_passcode);
572 break;
573
574 case PPD_CUSTOM_PASSWORD :
575 printf(" %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n",
576 cparam->name, cparam->text,
577 cparam->minimum.custom_password,
578 cparam->maximum.custom_password);
579 break;
580
581 case PPD_CUSTOM_POINTS :
582 printf(" %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n",
583 cparam->name, cparam->text,
584 cparam->minimum.custom_points,
585 cparam->maximum.custom_points);
586 break;
587
588 case PPD_CUSTOM_REAL :
589 printf(" %s(%s): PPD_CUSTOM_REAL (%g to %g)\n",
590 cparam->name, cparam->text,
591 cparam->minimum.custom_real,
592 cparam->maximum.custom_real);
593 break;
594
595 case PPD_CUSTOM_STRING :
596 printf(" %s(%s): PPD_CUSTOM_STRING (%d to %d)\n",
597 cparam->name, cparam->text,
598 cparam->minimum.custom_string,
599 cparam->maximum.custom_string);
600 break;
601 }
602 }
603 }
604 }
605 }
606
607 puts("Constraints:");
608
609 for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
610 printf(" *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
611 c->option2, c->choice2);
612
613 puts("Attributes:");
614
615 for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
616 attr;
617 attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
618 printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec,
619 attr->text, attr->value ? attr->value : "");
620 }
621
622 if (!strncmp(argv[1], "-d", 2))
623 unlink(filename);
624 }
625
626 #ifdef __APPLE__
627 if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact"))
628 {
629 char command[1024]; /* malloc_history command */
630
631 snprintf(command, sizeof(command), "malloc_history %d -all_by_size",
632 getpid());
633 fflush(stdout);
634 system(command);
635 }
636 #endif /* __APPLE__ */
637
638 ppdClose(ppd);
639
640 return (status);
641 }
642
643
644 /*
645 * End of "$Id: testppd.c 7633 2008-06-10 23:07:29Z mike $".
646 */