]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
503b54c9 | 2 | * Localization test program for CUPS. |
ef416fc2 | 3 | * |
6b2fb435 MS |
4 | * Usage: |
5 | * | |
6 | * ./testlang [-l locale] [-p ppd] ["String to localize"] | |
7 | * | |
1a9743f9 | 8 | * Copyright 2007-2017 by Apple Inc. |
503b54c9 | 9 | * Copyright 1997-2006 by Easy Software Products. |
ef416fc2 | 10 | * |
e3101897 | 11 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
ef416fc2 | 12 | */ |
13 | ||
14 | /* | |
15 | * Include necessary headers... | |
16 | */ | |
17 | ||
71e16022 | 18 | #include "cups-private.h" |
f787e1e3 | 19 | #include "ppd-private.h" |
1a9743f9 MS |
20 | #ifdef __APPLE__ |
21 | # include <CoreFoundation/CoreFoundation.h> | |
22 | #endif /* __APPLE__ */ | |
ef416fc2 | 23 | |
24 | ||
9964a31a MS |
25 | /* |
26 | * Local functions... | |
27 | */ | |
28 | ||
6b2fb435 MS |
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); | |
9964a31a MS |
32 | |
33 | ||
ef416fc2 | 34 | /* |
35 | * 'main()' - Load the specified language and show the strings for yes and no. | |
36 | */ | |
37 | ||
38 | int /* O - Exit status */ | |
39 | main(int argc, /* I - Number of command-line arguments */ | |
40 | char *argv[]) /* I - Command-line arguments */ | |
41 | { | |
7594b224 | 42 | int i; /* Looping var */ |
6b2fb435 | 43 | const char *opt; /* Current option */ |
7594b224 | 44 | int errors = 0; /* Number of errors */ |
6b2fb435 MS |
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) */ | |
7594b224 | 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 | ||
ef416fc2 | 60 | |
6b2fb435 MS |
61 | /* |
62 | * Parse command-line... | |
63 | */ | |
64 | ||
65 | _cupsSetLocale(argv); | |
66 | ||
67 | for (i = 1; i < argc; i ++) | |
ef416fc2 | 68 | { |
6b2fb435 MS |
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 | } | |
36474350 | 128 | |
6b2fb435 MS |
129 | dotests = 0; |
130 | errors += test_string(language, argv[i]); | |
131 | } | |
ef416fc2 | 132 | } |
133 | ||
6b2fb435 MS |
134 | if (!language) |
135 | { | |
136 | language = cupsLangDefault(); | |
137 | language2 = cupsLangDefault(); | |
138 | } | |
36474350 | 139 | |
ef416fc2 | 140 | if (language != language2) |
141 | { | |
7594b224 | 142 | errors ++; |
143 | ||
ef416fc2 | 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)); | |
997db404 | 150 | |
6b2fb435 | 151 | if (dotests) |
ef416fc2 | 152 | { |
6b2fb435 MS |
153 | errors += test_string(language, "No"); |
154 | errors += test_string(language, "Yes"); | |
7594b224 | 155 | |
6b2fb435 | 156 | if (language != language2) |
7594b224 | 157 | { |
6b2fb435 MS |
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")); | |
7594b224 | 164 | } |
7594b224 | 165 | |
6b2fb435 | 166 | loc = localeconv(); |
36474350 | 167 | |
6b2fb435 | 168 | for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i ++) |
36474350 | 169 | { |
6b2fb435 | 170 | number = _cupsStrScand(tests[i], NULL, loc); |
36474350 | 171 | |
6b2fb435 | 172 | printf("_cupsStrScand(\"%s\") number=%f\n", tests[i], number); |
36474350 | 173 | |
6b2fb435 | 174 | _cupsStrFormatd(buffer, buffer + sizeof(buffer), number, loc); |
36474350 | 175 | |
6b2fb435 | 176 | printf("_cupsStrFormatd(%f) buffer=\"%s\"\n", number, buffer); |
2650d637 | 177 | |
6b2fb435 MS |
178 | if (strcmp(buffer, tests[i])) |
179 | { | |
180 | errors ++; | |
181 | puts("**** ERROR: Bad formatted number! ****"); | |
182 | } | |
36474350 | 183 | } |
6b2fb435 | 184 | |
1a9743f9 | 185 | #ifdef __APPLE__ |
1a9743f9 MS |
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 */ | |
1a9743f9 | 271 | #endif /* __APPLE__ */ |
6b2fb435 | 272 | } |
36474350 | 273 | |
6b2fb435 | 274 | if (errors == 0 && dotests) |
6579c998 MS |
275 | puts("ALL TESTS PASSED"); |
276 | ||
7594b224 | 277 | return (errors > 0); |
ef416fc2 | 278 | } |
9964a31a MS |
279 | |
280 | ||
6b2fb435 MS |
281 | /* |
282 | * 'show_ppd()' - Show localized strings in a PPD file. | |
283 | */ | |
284 | ||
285 | static int /* O - Number of errors */ | |
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 | ||
9964a31a MS |
330 | /* |
331 | * 'test_string()' - Test the localization of a string. | |
332 | */ | |
333 | ||
334 | static int /* O - 1 on failure, 0 on success */ | |
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 | ||
6b2fb435 MS |
365 | |
366 | /* | |
367 | * 'usage()' - Show program usage. | |
368 | */ | |
369 | ||
370 | static void | |
371 | usage(void) | |
372 | { | |
373 | puts("./testlang [-l locale] [-p ppd] [\"String to localize\"]"); | |
374 | } |