Skip to content

Commit f9a390d

Browse files
committed
tests: add locale tests
1 parent 2e1d3bc commit f9a390d

File tree

5 files changed

+261
-6
lines changed

5 files changed

+261
-6
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ jobs:
9999
- name: Test mlibc
100100
run: 'meson test -v -C pkg-builds/${{matrix.builds}}'
101101
working-directory: build/
102+
env:
103+
LOCPATH: "${{ github.workspace }}/build/packages/locale-data/usr/lib/locale/"
102104

103105
compile-sysdeps:
104106
strategy:

ci/bootstrap.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ sources:
2121
tag: 'libdrm-2.4.124'
2222
version: '2.4.124'
2323

24+
- name: glibc
25+
git: 'https://sourceware.org/git/glibc.git'
26+
tag: 'glibc-2.42'
27+
version: '2.42'
28+
2429
tools: []
2530

2631
packages:
@@ -30,6 +35,7 @@ packages:
3035
pkgs_required:
3136
- linux-headers
3237
- libdrm-headers
38+
- locale-data
3339
configure:
3440
- args:
3541
- 'meson'
@@ -65,6 +71,7 @@ packages:
6571
pkgs_required:
6672
- linux-headers
6773
- libdrm-headers
74+
- locale-data
6875
configure:
6976
- args:
7077
- 'meson'
@@ -97,6 +104,7 @@ packages:
97104
pkgs_required:
98105
- linux-headers
99106
- libdrm-headers
107+
- locale-data
100108
configure:
101109
- args:
102110
- 'meson'
@@ -130,6 +138,7 @@ packages:
130138
pkgs_required:
131139
- linux-headers
132140
- libdrm-headers
141+
- locale-data
133142
configure:
134143
- args:
135144
- 'meson'
@@ -226,3 +235,21 @@ packages:
226235
libdrm_dep = declare_dependency(include_directories: include_directories('include'))
227236
EOF
228237
- args: ['cp', '-r', '@THIS_SOURCE_DIR@/include', '@THIS_COLLECT_DIR@/usr/src/libdrm-headers/include']
238+
239+
- name: locale-data
240+
architecture: noarch
241+
from_source: 'glibc'
242+
build:
243+
- args: |
244+
ARCH="@OPTION:arch@"
245+
LOCALEDEF_FLAGS=""
246+
if [ "$ARCH" == "m68k" ]; then
247+
LOCALEDEF_FLAGS="--big-endian"
248+
fi
249+
mkdir -p @THIS_COLLECT_DIR@/usr/lib/locale/
250+
localedef $LOCALEDEF_FLAGS -fUTF-8 -ide_DE --prefix=@THIS_COLLECT_DIR@ --no-archive de_DE.utf8
251+
localedef $LOCALEDEF_FLAGS -fUTF-8 -ide_DE --prefix=@THIS_COLLECT_DIR@ --no-archive de_DE
252+
localedef $LOCALEDEF_FLAGS -fUTF-8 -iru_RU --prefix=@THIS_COLLECT_DIR@ --no-archive ru_RU.utf8
253+
localedef $LOCALEDEF_FLAGS -fUTF-8 -ien_US --prefix=@THIS_COLLECT_DIR@ --no-archive en_US.utf8
254+
environ:
255+
I18NPATH: '@THIS_SOURCE_DIR@/localedata/'

tests/ansi/locale.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,42 @@
1-
#include <stdio.h>
2-
#include <wchar.h>
1+
#include <assert.h>
2+
#include <ctype.h>
33
#include <limits.h>
44
#include <locale.h>
5-
#include <assert.h>
5+
#include <stdbool.h>
6+
#include <stdio.h>
7+
#include <string.h>
8+
#include <wchar.h>
69

710
int main() {
8-
wchar_t c = 0xC9;
9-
unsigned char buf[MB_LEN_MAX] = { 0 };
11+
char buf[64] = { 0 };
12+
wint_t c = 0xC9;
1013
setlocale(LC_ALL, "");
1114
if (sprintf(buf, "%lc", c) < 0)
1215
return -1;
1316

14-
assert(buf[0] == 0xc3 && buf[1] == 0x89
17+
assert((unsigned char) buf[0] == 0xc3 && (unsigned char) buf[1] == 0x89
1518
&& buf[2] == '\0' && buf[3] == '\0');
1619

20+
setlocale(LC_ALL, "C");
21+
22+
snprintf(buf, sizeof(buf), "%2.2f", 12.34);
23+
assert(!strcmp("12.34", buf));
24+
25+
setlocale(LC_ALL, "de_DE");
26+
27+
snprintf(buf, sizeof(buf), "%2.2f", 12.34);
28+
assert(!strcmp("12,34", buf));
29+
30+
char lower = tolower('A');
31+
assert(lower == 'a');
32+
char upper = toupper(lower);
33+
assert(upper == 'A');
34+
35+
assert(isalpha('z'));
36+
assert(!isalpha('z' + 1));
37+
38+
snprintf(buf, sizeof(buf), "%'g", 12345.67);
39+
// assert(!strcmp("12.345,7", buf));
40+
1741
return 0;
1842
}

tests/meson.build

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ all_test_cases = [
3333
'ansi/fgetpos',
3434
'ansi/fputs',
3535
'ansi/ftell',
36+
'ansi/locale',
3637
'bsd/ns_get_put',
3738
'bsd/reallocarray',
3839
'bsd/strl',
@@ -107,6 +108,7 @@ all_test_cases = [
107108
'posix/shm',
108109
'posix/swab',
109110
'posix/select',
111+
'posix/locale',
110112
'glibc/getopt',
111113
'glibc/ffsl-ffsll',
112114
'glibc/error_message_count',
@@ -157,11 +159,20 @@ host_libc_excluded_test_cases = [
157159
'glibc/error_at_line', # These tests depend on mlibc error messages.
158160
'rtld/search-order', # See rtld/search-order/meson.build.
159161
]
162+
163+
if target_machine.cpu_family() == 'm68k'
164+
host_libc_excluded_test_cases += [
165+
'ansi/locale',
166+
'posix/locale',
167+
]
168+
endif
169+
160170
host_libc_noasan_test_cases = [
161171
'posix/pthread_cancel',
162172
'posix/pthread_attr', # does some stack overflowing to check stack size
163173
'posix/posix_memalign',
164174
'posix/search', # requires tdelete (#351)
175+
'posix/locale', # encounters memory leaks
165176
'ansi/calloc', # does some overflowing
166177
'linux/pthread_attr', # encounters memory leaks
167178
]

tests/posix/locale.c

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#ifndef _GNU_SOURCE
2+
#define _GNU_SOURCE
3+
#endif
4+
5+
#include <assert.h>
6+
#include <ctype.h>
7+
#include <wctype.h>
8+
#include <stdbool.h>
9+
#include <langinfo.h>
10+
#include <limits.h>
11+
#include <stdlib.h>
12+
#include <locale.h>
13+
#include <stdio.h>
14+
#include <string.h>
15+
#include <wchar.h>
16+
17+
int main() {
18+
char buf[64] = { 0 };
19+
wint_t c = 0xC9;
20+
char *locale = setlocale(LC_ALL, "");
21+
assert(locale && strlen(locale));
22+
if (snprintf(buf, MB_LEN_MAX, "%lc", c) < 0)
23+
return -1;
24+
25+
assert((unsigned char) buf[0] == 0xc3 && (unsigned char) buf[1] == 0x89
26+
&& buf[2] == '\0' && buf[3] == '\0');
27+
28+
locale_t fake = newlocale(LC_ALL_MASK, "swamp german", 0);
29+
assert(fake == 0);
30+
31+
locale_t german = newlocale(LC_ALL_MASK, "de_DE.utf8", 0);
32+
assert(german != 0);
33+
34+
locale_t posix = newlocale(LC_ALL_MASK, "POSIX", 0);
35+
assert(posix != 0);
36+
37+
locale = setlocale(LC_ALL, "C");
38+
assert(locale && strlen(locale));
39+
40+
char *decimal_point = nl_langinfo_l(DECIMAL_POINT, german);
41+
assert(!strcmp(",", decimal_point));
42+
char *tousands_sep = nl_langinfo_l(THOUSEP, german);
43+
assert(!strcmp(".", tousands_sep));
44+
char *yesexpr = nl_langinfo_l(YESEXPR, german);
45+
assert(!strcmp("^[+1jJyY]", yesexpr));
46+
char *noexpr = nl_langinfo_l(NOEXPR, german);
47+
assert(!strcmp("^[-0nN]", noexpr));
48+
char *currency_symbol = nl_langinfo_l(CURRENCY_SYMBOL, german);
49+
assert(!strcmp("€", currency_symbol));
50+
char *crncystr = nl_langinfo_l(CRNCYSTR, german);
51+
assert(!strcmp("+€", crncystr));
52+
char *abday_1 = nl_langinfo_l(ABDAY_1, german);
53+
assert(!strcmp("So", abday_1));
54+
char *day_1 = nl_langinfo_l(DAY_1, german);
55+
assert(!strcmp("Sonntag", day_1));
56+
char *day_7 = nl_langinfo_l(DAY_7, german);
57+
assert(!strcmp("Samstag", day_7));
58+
char *pm = nl_langinfo_l(PM_STR, german);
59+
assert(!strcmp("", pm));
60+
61+
char lower = tolower_l('A', german);
62+
assert(lower == 'a');
63+
char upper = toupper_l(lower, german);
64+
assert(upper == 'A');
65+
wchar_t wlower = towlower_l(L'Ä', german);
66+
assert(wlower == L'ä');
67+
68+
assert(isblank_l(' ', german) == true);
69+
assert(isblank_l('\t', german) == true);
70+
assert(isblank_l('\n', german) == false);
71+
assert(isblank_l('a', german) == false);
72+
assert(isblank_l('1', german) == false);
73+
assert(isblank_l('\v', german) == false);
74+
assert(isblank_l('\r', german) == false);
75+
76+
assert(isblank_l(' ', posix) == true);
77+
assert(isblank_l('\t', posix) == true);
78+
assert(isblank_l('\n', posix) == false);
79+
assert(isblank_l('a', posix) == false);
80+
assert(isblank_l('1', posix) == false);
81+
assert(isblank_l('\v', posix) == false);
82+
assert(isblank_l('\r', posix) == false);
83+
84+
uselocale(german);
85+
86+
assert(iswalpha_l(L'ß', german));
87+
assert(iswlower_l(L'ß', german));
88+
assert(!iswalpha_l(L'ß', posix));
89+
90+
wlower = towlower_l(L'Ä', german);
91+
assert(wlower == L'ä');
92+
93+
memset(buf, 0, sizeof(buf));
94+
snprintf(buf, sizeof(buf), "%2.2f", 12.34);
95+
assert(!strcmp("12,34", buf));
96+
97+
assert(strtod_l(" 12,34", NULL, german) == 12.34);
98+
99+
wctype_t wctype = wctype_l("alpha", german);
100+
assert(wctype);
101+
assert(iswctype_l(L'ß', wctype, german));
102+
assert(!iswctype_l(L'÷', wctype, german));
103+
assert(!iswctype_l(L'❔', wctype, german));
104+
wctype = wctype_l("graph", german);
105+
assert(wctype);
106+
assert(iswctype_l(L'ß', wctype, german));
107+
assert(iswctype_l(L'÷', wctype, german));
108+
assert(iswctype_l(L'❔', wctype, german));
109+
assert(!iswctype_l(L'\x91', wctype, german));
110+
assert(!iswctype_l(WEOF, wctype, german));
111+
112+
uselocale(LC_GLOBAL_LOCALE);
113+
freelocale(german);
114+
115+
snprintf(buf, sizeof(buf), "%2.2f", 12.34);
116+
assert(!strcmp("12.34", buf));
117+
118+
decimal_point = nl_langinfo_l(DECIMAL_POINT, posix);
119+
assert(!strcmp(".", decimal_point));
120+
tousands_sep = nl_langinfo_l(THOUSEP, posix);
121+
assert(!strcmp("", tousands_sep));
122+
yesexpr = nl_langinfo_l(YESEXPR, posix);
123+
assert(!strcmp("^[yY]", yesexpr));
124+
noexpr = nl_langinfo_l(NOEXPR, posix);
125+
assert(!strcmp("^[nN]", noexpr));
126+
currency_symbol = nl_langinfo_l(CURRENCY_SYMBOL, posix);
127+
assert(!strcmp("", currency_symbol));
128+
crncystr = nl_langinfo_l(CRNCYSTR, posix);
129+
assert(!strcmp("-", crncystr));
130+
abday_1 = nl_langinfo_l(ABDAY_1, posix);
131+
assert(!strcmp("Sun", abday_1));
132+
day_1 = nl_langinfo_l(DAY_1, posix);
133+
assert(!strcmp("Sunday", day_1));
134+
day_7 = nl_langinfo_l(DAY_7, posix);
135+
assert(!strcmp("Saturday", day_7));
136+
pm = nl_langinfo_l(PM_STR, posix);
137+
assert(!strcmp("PM", pm));
138+
139+
freelocale(posix);
140+
141+
locale = setlocale(LC_ALL, "de_DE");
142+
assert(locale && strlen(locale));
143+
144+
tousands_sep = nl_langinfo(THOUSEP);
145+
assert(!strcmp(".", tousands_sep));
146+
decimal_point = nl_langinfo(DECIMAL_POINT);
147+
assert(!strcmp(",", decimal_point));
148+
pm = nl_langinfo(PM_STR);
149+
assert(!strcmp("", pm));
150+
151+
lower = tolower('A');
152+
assert(lower == 'a');
153+
upper = toupper(lower);
154+
assert(upper == 'A');
155+
156+
assert(isalpha('z'));
157+
assert(!isalpha('z' + 1));
158+
159+
snprintf(buf, sizeof(buf), "%'g", 12345.67);
160+
// assert(!strcmp("12.345,7", buf));
161+
162+
locale = setlocale(LC_NUMERIC, "C");
163+
assert(locale && strlen(locale));
164+
165+
tousands_sep = nl_langinfo(THOUSEP);
166+
assert(!strcmp("", tousands_sep));
167+
decimal_point = nl_langinfo(DECIMAL_POINT);
168+
assert(!strcmp(".", decimal_point));
169+
pm = nl_langinfo(PM_STR);
170+
assert(!strcmp("", pm));
171+
172+
locale = setlocale(LC_TIME, "ru_RU.utf8");
173+
assert(locale && strlen(locale));
174+
175+
day_7 = nl_langinfo(DAY_7);
176+
assert(!strcmp("Суббота", day_7));
177+
178+
locale = setlocale(LC_MONETARY, "en_US.utf8");
179+
assert(locale && strlen(locale));
180+
181+
currency_symbol = nl_langinfo(CURRENCY_SYMBOL);
182+
assert(!strcmp("$", currency_symbol));
183+
184+
locale = setlocale(LC_ALL, "C");
185+
assert(locale && strlen(locale));
186+
187+
pm = nl_langinfo(PM_STR);
188+
assert(!strcmp("PM", pm));
189+
190+
return 0;
191+
}

0 commit comments

Comments
 (0)