1 /* $OpenBSD: setlocale.c,v 1.4 2018/03/29 16:34:25 schwarze Exp $ */
2 /*
3 * Copyright (c) 2015 Sebastien Marie <semarie@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <err.h>
19 #include <locale.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <ctype.h>
24
25 /*
26 * test helpers for __LINE__
27 */
28 #define test_setlocale(_e, _c, _l) _test_setlocale(_e, _c, _l, __LINE__)
29 #define test_MB_CUR_MAX(_e) _test_MB_CUR_MAX(_e, __LINE__)
30 #define test_isalpha(_e, _c) _test_isalpha(_e, _c, __LINE__)
31
32
33 static void
_test_setlocale(char * expected,int category,char * locale,int line)34 _test_setlocale(char *expected, int category, char *locale, int line)
35 {
36 char *result = setlocale(category, locale);
37
38 if ((expected == NULL) || (result == NULL)) {
39 if (expected == result)
40 return;
41
42 errx(1, "[%d] setlocale(%d, \"%s\")=\"%s\" [expected: \"%s\"]",
43 line, category, locale, result, expected);
44 }
45
46 if (strcmp(expected, result) != 0)
47 errx(1, "[%d] setlocale(%d, \"%s\")=\"%s\" [expected: \"%s\"]",
48 line, category, locale, result, expected);
49 }
50
51 static void
_test_MB_CUR_MAX(size_t expected,int line)52 _test_MB_CUR_MAX(size_t expected, int line)
53 {
54 if (MB_CUR_MAX != expected)
55 errx(1, "[%d] MB_CUR_MAX=%ld [expected %ld]",
56 line, MB_CUR_MAX, expected);
57 }
58
59 static void
_test_isalpha(int expected,int c,int line)60 _test_isalpha(int expected, int c, int line)
61 {
62 int result = isalpha(c);
63 if (!!result != expected)
64 errx(1, "[%d] isalpha(%d)=%d [expected %d]",
65 line, c, result, expected);
66 }
67
68 int
main(int argc,char * argv[])69 main(int argc, char *argv[])
70 {
71 /* check initial state (should be "C") */
72 test_setlocale("C", LC_ALL, NULL); /* check */
73 test_MB_CUR_MAX(1);
74 test_isalpha(0, 0xe9); /* iso-8859-1 eacute */
75
76 /* load from env */
77 /* NOTE: we don't support non-C locales for some categories */
78 test_setlocale("fr_FR.UTF-8", LC_CTYPE, ""); /* set */
79 test_setlocale("fr_FR.UTF-8", LC_MESSAGES, ""); /* set */
80 test_MB_CUR_MAX(4);
81 test_isalpha(0, 0xe9); /* iso-8859-1 eacute */
82
83 test_setlocale("C", LC_MESSAGES, "C"); /* set */
84 test_MB_CUR_MAX(4);
85 test_setlocale("C/fr_FR.UTF-8/C/C/C/C", LC_ALL, NULL); /* check */
86
87 test_setlocale("C", LC_CTYPE, "C"); /* set */
88 test_MB_CUR_MAX(1);
89 test_setlocale("C", LC_ALL, NULL); /* check */
90
91 /* check for errors on checking */
92 test_setlocale("C", LC_ALL, "C"); /* reset */
93 test_setlocale(NULL, -1, NULL);
94 test_setlocale(NULL, _LC_LAST, NULL);
95 test_setlocale(NULL, _LC_LAST+0xff, NULL);
96 test_setlocale("C", LC_ALL, NULL); /* check */
97
98 /* check for errors on setting */
99 test_setlocale(NULL, -1, "");
100 test_setlocale(NULL, _LC_LAST, "");
101 test_setlocale(NULL, _LC_LAST+0xff, "");
102 test_setlocale("C", LC_ALL, NULL); /* check */
103
104 /* no codeset, fallback to ASCII */
105 test_setlocale("C", LC_ALL, "C"); /* reset */
106 test_setlocale("invalid", LC_CTYPE, "invalid"); /* set */
107 test_setlocale("invalid", LC_CTYPE, NULL);
108 test_MB_CUR_MAX(1);
109 test_isalpha(0, 0xe9); /* iso-8859-1 eacute */
110
111 /* with codeset */
112 test_setlocale("C", LC_ALL, "C"); /* reset */
113 test_setlocale("invalid.UTF-8", LC_CTYPE, "invalid.UTF-8"); /* set */
114 test_setlocale("invalid.UTF-8", LC_CTYPE, NULL);
115 test_setlocale("C/invalid.UTF-8/C/C/C/C", LC_ALL, NULL);
116 test_MB_CUR_MAX(4);
117
118 /* with invalid codeset (is an error) */
119 test_setlocale("C", LC_ALL, "C"); /* reset */
120 test_setlocale(NULL, LC_CTYPE, "fr_FR.invalid"); /* set */
121 test_setlocale("C", LC_CTYPE, NULL);
122 test_MB_CUR_MAX(1);
123
124 return (EXIT_SUCCESS);
125 }
126