1 /*
2 * Localization test program for CUPS.
3 *
4 * Usage:
5 *
6 * ./testlang [-l locale] [-p ppd] ["String to localize"]
7 *
8 * Copyright 2007-2017 by Apple Inc.
9 * Copyright 1997-2006 by Easy Software Products.
10 *
11 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
12 */
13
14 /*
15 * Include necessary headers...
16 */
17
18 #include "cups-private.h"
19 #include "ppd-private.h"
20 #ifdef __APPLE__
21 # include <CoreFoundation/CoreFoundation.h>
22 #endif /* __APPLE__ */
23
24
25 /*
26 * Local functions...
27 */
28
29 static int show_ppd(const char *filename);
30 static int test_string(cups_lang_t *language, const char *msgid);
31 static void usage(void);
32
33
34 /*
35 * 'main()' - Load the specified language and show the strings for yes and no.
36 */
37
38 int /* O - Exit status */
main(int argc,char * argv[])39 main(int argc, /* I - Number of command-line arguments */
40 char *argv[]) /* I - Command-line arguments */
41 {
42 int i; /* Looping var */
43 const char *opt; /* Current option */
44 int errors = 0; /* Number of errors */
45 int dotests = 1; /* Do standard tests? */
46 cups_lang_t *language = NULL;/* Message catalog */
47 cups_lang_t *language2 = NULL;
48 /* Message catalog (second time) */
49 struct lconv *loc; /* Locale data */
50 char buffer[1024]; /* String buffer */
51 double number; /* Number */
52 static const char * const tests[] = /* Test strings */
53 {
54 "1",
55 "-1",
56 "3",
57 "5.125"
58 };
59
60
61 /*
62 * Parse command-line...
63 */
64
65 _cupsSetLocale(argv);
66
67 for (i = 1; i < argc; i ++)
68 {
69 if (argv[i][0] == '-')
70 {
71 if (!strcmp(argv[i], "--help"))
72 {
73 usage();
74 }
75 else
76 {
77 for (opt = argv[i] + 1; *opt; opt ++)
78 {
79 switch (*opt)
80 {
81 case 'l' :
82 i ++;
83 if (i >= argc)
84 {
85 usage();
86 return (1);
87 }
88
89 language = cupsLangGet(argv[i]);
90 language2 = cupsLangGet(argv[i]);
91
92 setenv("LANG", argv[i], 1);
93 setenv("SOFTWARE", "CUPS/" CUPS_SVERSION, 1);
94 break;
95
96 case 'p' :
97 i ++;
98 if (i >= argc)
99 {
100 usage();
101 return (1);
102 }
103
104 if (!language)
105 {
106 language = cupsLangDefault();
107 language2 = cupsLangDefault();
108 }
109
110 dotests = 0;
111 errors += show_ppd(argv[i]);
112 break;
113
114 default :
115 usage();
116 return (1);
117 }
118 }
119 }
120 }
121 else
122 {
123 if (!language)
124 {
125 language = cupsLangDefault();
126 language2 = cupsLangDefault();
127 }
128
129 dotests = 0;
130 errors += test_string(language, argv[i]);
131 }
132 }
133
134 if (!language)
135 {
136 language = cupsLangDefault();
137 language2 = cupsLangDefault();
138 }
139
140 if (language != language2)
141 {
142 errors ++;
143
144 puts("**** ERROR: Language cache did not work! ****");
145 puts("First result from cupsLangGet:");
146 }
147
148 printf("Language = \"%s\"\n", language->language);
149 printf("Encoding = \"%s\"\n", _cupsEncodingName(language->encoding));
150
151 if (dotests)
152 {
153 errors += test_string(language, "No");
154 errors += test_string(language, "Yes");
155
156 if (language != language2)
157 {
158 puts("Second result from cupsLangGet:");
159
160 printf("Language = \"%s\"\n", language2->language);
161 printf("Encoding = \"%s\"\n", _cupsEncodingName(language2->encoding));
162 printf("No = \"%s\"\n", _cupsLangString(language2, "No"));
163 printf("Yes = \"%s\"\n", _cupsLangString(language2, "Yes"));
164 }
165
166 loc = localeconv();
167
168 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i ++)
169 {
170 number = _cupsStrScand(tests[i], NULL, loc);
171
172 printf("_cupsStrScand(\"%s\") number=%f\n", tests[i], number);
173
174 _cupsStrFormatd(buffer, buffer + sizeof(buffer), number, loc);
175
176 printf("_cupsStrFormatd(%f) buffer=\"%s\"\n", number, buffer);
177
178 if (strcmp(buffer, tests[i]))
179 {
180 errors ++;
181 puts("**** ERROR: Bad formatted number! ****");
182 }
183 }
184
185 #ifdef __APPLE__
186 /*
187 * Test all possible language IDs for compatibility with _cupsAppleLocale...
188 */
189
190 CFIndex j, /* Looping var */
191 num_locales; /* Number of locales */
192 CFArrayRef locales; /* Locales */
193 CFStringRef locale_id, /* Current locale ID */
194 language_id; /* Current language ID */
195 char locale_str[256], /* Locale ID C string */
196 language_str[256], /* Language ID C string */
197 *bufptr; /* Pointer to ".UTF-8" in POSIX locale */
198 size_t buflen; /* Length of POSIX locale */
199 # if TEST_COUNTRY_CODES
200 CFIndex k, /* Looping var */
201 num_country_codes; /* Number of country codes */
202 CFArrayRef country_codes; /* Country codes */
203 CFStringRef country_code, /* Current country code */
204 temp_id; /* Temporary language ID */
205 char country_str[256]; /* Country code C string */
206 # endif /* TEST_COUNTRY_CODES */
207
208 locales = CFLocaleCopyAvailableLocaleIdentifiers();
209 num_locales = CFArrayGetCount(locales);
210
211 # if TEST_COUNTRY_CODES
212 country_codes = CFLocaleCopyISOCountryCodes();
213 num_country_codes = CFArrayGetCount(country_codes);
214 # endif /* TEST_COUNTRY_CODES */
215
216 printf("%d locales are available:\n", (int)num_locales);
217
218 for (j = 0; j < num_locales; j ++)
219 {
220 locale_id = CFArrayGetValueAtIndex(locales, j);
221 language_id = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorDefault, locale_id);
222
223 if (!locale_id || !CFStringGetCString(locale_id, locale_str, (CFIndex)sizeof(locale_str), kCFStringEncodingASCII))
224 {
225 printf("%d: FAIL (unable to get locale ID string)\n", (int)j + 1);
226 errors ++;
227 continue;
228 }
229
230 if (!language_id || !CFStringGetCString(language_id, language_str, (CFIndex)sizeof(language_str), kCFStringEncodingASCII))
231 {
232 printf("%d %s: FAIL (unable to get language ID string)\n", (int)j + 1, locale_str);
233 errors ++;
234 continue;
235 }
236
237 if (!_cupsAppleLocale(language_id, buffer, sizeof(buffer)))
238 {
239 printf("%d %s(%s): FAIL (unable to convert language ID string to POSIX locale)\n", (int)j + 1, locale_str, language_str);
240 errors ++;
241 continue;
242 }
243
244 if ((bufptr = strstr(buffer, ".UTF-8")) != NULL)
245 buflen = (size_t)(bufptr - buffer);
246 else
247 buflen = strlen(buffer);
248
249 if ((language = cupsLangGet(buffer)) == NULL)
250 {
251 printf("%d %s(%s): FAIL (unable to load POSIX locale \"%s\")\n", (int)j + 1, locale_str, language_str, buffer);
252 errors ++;
253 continue;
254 }
255
256 if (strncasecmp(language->language, buffer, buflen))
257 {
258 printf("%d %s(%s): FAIL (unable to load POSIX locale \"%s\", got \"%s\")\n", (int)j + 1, locale_str, language_str, buffer, language->language);
259 errors ++;
260 continue;
261 }
262
263 printf("%d %s(%s): PASS (POSIX locale is \"%s\")\n", (int)j + 1, locale_str, language_str, buffer);
264 }
265
266 CFRelease(locales);
267
268 # if TEST_COUNTRY_CODES
269 CFRelease(country_codes);
270 # endif /* TEST_COUNTRY_CODES */
271 #endif /* __APPLE__ */
272 }
273
274 if (errors == 0 && dotests)
275 puts("ALL TESTS PASSED");
276
277 return (errors > 0);
278 }
279
280
281 /*
282 * 'show_ppd()' - Show localized strings in a PPD file.
283 */
284
285 static int /* O - Number of errors */
show_ppd(const char * filename)286 show_ppd(const char *filename) /* I - Filename */
287 {
288 ppd_file_t *ppd; /* PPD file */
289 ppd_option_t *option; /* PageSize option */
290 ppd_choice_t *choice; /* PageSize/Letter choice */
291 char buffer[1024]; /* String buffer */
292
293
294 if ((ppd = ppdOpenFile(filename)) == NULL)
295 {
296 printf("Unable to open PPD file \"%s\".\n", filename);
297 return (1);
298 }
299
300 ppdLocalize(ppd);
301
302 if ((option = ppdFindOption(ppd, "PageSize")) == NULL)
303 {
304 puts("No PageSize option.");
305 return (1);
306 }
307 else
308 {
309 printf("PageSize: %s\n", option->text);
310
311 if ((choice = ppdFindChoice(option, "Letter")) == NULL)
312 {
313 puts("No Letter PageSize choice.");
314 return (1);
315 }
316 else
317 {
318 printf("Letter: %s\n", choice->text);
319 }
320 }
321
322 printf("media-empty: %s\n", ppdLocalizeIPPReason(ppd, "media-empty", NULL, buffer, sizeof(buffer)));
323
324 ppdClose(ppd);
325
326 return (0);
327 }
328
329
330 /*
331 * 'test_string()' - Test the localization of a string.
332 */
333
334 static int /* O - 1 on failure, 0 on success */
test_string(cups_lang_t * language,const char * msgid)335 test_string(cups_lang_t *language, /* I - Language */
336 const char *msgid) /* I - Message */
337 {
338 const char *msgstr; /* Localized string */
339
340
341 /*
342 * Get the localized string and then see if we got what we expected.
343 *
344 * For the POSIX locale, the string pointers should be the same.
345 * For any other locale, the string pointers should be different.
346 */
347
348 msgstr = _cupsLangString(language, msgid);
349 if (strcmp(language->language, "C") && msgid == msgstr)
350 {
351 printf("%-8s = \"%s\" (FAIL - no message catalog loaded)\n", msgid, msgstr);
352 return (1);
353 }
354 else if (!strcmp(language->language, "C") && msgid != msgstr)
355 {
356 printf("%-8s = \"%s\" (FAIL - POSIX locale is localized)\n", msgid, msgstr);
357 return (1);
358 }
359
360 printf("%-8s = \"%s\" (PASS)\n", msgid, msgstr);
361
362 return (0);
363 }
364
365
366 /*
367 * 'usage()' - Show program usage.
368 */
369
370 static void
usage(void)371 usage(void)
372 {
373 puts("./testlang [-l locale] [-p ppd] [\"String to localize\"]");
374 }
375