1*4f2483e5SBill Sommerfeld /*
2*4f2483e5SBill Sommerfeld * This file and its contents are supplied under the terms of the
3*4f2483e5SBill Sommerfeld * Common Development and Distribution License ("CDDL"), version 1.0.
4*4f2483e5SBill Sommerfeld * You may only use this file in accordance with the terms of version
5*4f2483e5SBill Sommerfeld * 1.0 of the CDDL.
6*4f2483e5SBill Sommerfeld *
7*4f2483e5SBill Sommerfeld * A full copy of the text of the CDDL should have accompanied this
8*4f2483e5SBill Sommerfeld * source. A copy of the CDDL is also available via the Internet at
9*4f2483e5SBill Sommerfeld * http://www.illumos.org/license/CDDL.
10*4f2483e5SBill Sommerfeld */
11*4f2483e5SBill Sommerfeld
12*4f2483e5SBill Sommerfeld /*
13*4f2483e5SBill Sommerfeld * Copyright 2025 Bill Sommerfeld
14*4f2483e5SBill Sommerfeld */
15*4f2483e5SBill Sommerfeld
16*4f2483e5SBill Sommerfeld /*
17*4f2483e5SBill Sommerfeld * Tests for localeconv(3C) and localeconv_l(3C). The libc tests depends on
18*4f2483e5SBill Sommerfeld * locale/ar, locale/de, locale/en, and locale/ja. We limit ourselves to
19*4f2483e5SBill Sommerfeld * these locales, plus C.UTF-8.
20*4f2483e5SBill Sommerfeld */
21*4f2483e5SBill Sommerfeld
22*4f2483e5SBill Sommerfeld #include <err.h>
23*4f2483e5SBill Sommerfeld #include <stdlib.h>
24*4f2483e5SBill Sommerfeld #include <xlocale.h>
25*4f2483e5SBill Sommerfeld #include <locale.h>
26*4f2483e5SBill Sommerfeld #include <sys/sysmacros.h>
27*4f2483e5SBill Sommerfeld #include <sys/debug.h>
28*4f2483e5SBill Sommerfeld #include <stdbool.h>
29*4f2483e5SBill Sommerfeld #include <string.h>
30*4f2483e5SBill Sommerfeld
31*4f2483e5SBill Sommerfeld
32*4f2483e5SBill Sommerfeld static struct test_locale {
33*4f2483e5SBill Sommerfeld const char *name;
34*4f2483e5SBill Sommerfeld locale_t loc;
35*4f2483e5SBill Sommerfeld struct lconv lconv;
36*4f2483e5SBill Sommerfeld } locales[] = {
37*4f2483e5SBill Sommerfeld { "C.UTF-8"},
38*4f2483e5SBill Sommerfeld { "ja_JP.UTF-8" },
39*4f2483e5SBill Sommerfeld { "de_DE.UTF-8" },
40*4f2483e5SBill Sommerfeld { "en_US.UTF-8" },
41*4f2483e5SBill Sommerfeld { "en_GB.UTF-8" },
42*4f2483e5SBill Sommerfeld };
43*4f2483e5SBill Sommerfeld
44*4f2483e5SBill Sommerfeld static bool
compare_lconv(const char * name,const struct lconv * a,const struct lconv * b)45*4f2483e5SBill Sommerfeld compare_lconv(const char *name, const struct lconv *a, const struct lconv *b)
46*4f2483e5SBill Sommerfeld {
47*4f2483e5SBill Sommerfeld bool all_match = true;
48*4f2483e5SBill Sommerfeld
49*4f2483e5SBill Sommerfeld #define FAIL(field, fmt) { warnx("TEST FAILED: %s %s mismatched" \
50*4f2483e5SBill Sommerfeld " (" fmt " vs " fmt ")", \
51*4f2483e5SBill Sommerfeld name, #field, a->field, b->field); all_match = false; }
52*4f2483e5SBill Sommerfeld
53*4f2483e5SBill Sommerfeld #define COMPARE_INT(field) if (a->field != b->field) FAIL(field, "%d")
54*4f2483e5SBill Sommerfeld #define COMPARE_STR(field) if (strcmp(a->field, b->field)) FAIL(field, "'%s'")
55*4f2483e5SBill Sommerfeld /* grouping encodes an array of int8_t's; punt on printing them */
56*4f2483e5SBill Sommerfeld #define COMPARE_GRP(field) if (strcmp(a->field, b->field)) FAIL(field, "%p")
57*4f2483e5SBill Sommerfeld
58*4f2483e5SBill Sommerfeld COMPARE_STR(decimal_point);
59*4f2483e5SBill Sommerfeld COMPARE_STR(thousands_sep);
60*4f2483e5SBill Sommerfeld COMPARE_GRP(grouping);
61*4f2483e5SBill Sommerfeld COMPARE_STR(int_curr_symbol);
62*4f2483e5SBill Sommerfeld COMPARE_STR(currency_symbol);
63*4f2483e5SBill Sommerfeld COMPARE_STR(mon_decimal_point);
64*4f2483e5SBill Sommerfeld COMPARE_STR(mon_thousands_sep);
65*4f2483e5SBill Sommerfeld COMPARE_GRP(mon_grouping);
66*4f2483e5SBill Sommerfeld COMPARE_STR(positive_sign);
67*4f2483e5SBill Sommerfeld COMPARE_STR(negative_sign);
68*4f2483e5SBill Sommerfeld
69*4f2483e5SBill Sommerfeld COMPARE_INT(int_frac_digits);
70*4f2483e5SBill Sommerfeld COMPARE_INT(frac_digits);
71*4f2483e5SBill Sommerfeld COMPARE_INT(p_cs_precedes);
72*4f2483e5SBill Sommerfeld COMPARE_INT(p_sep_by_space);
73*4f2483e5SBill Sommerfeld COMPARE_INT(n_cs_precedes);
74*4f2483e5SBill Sommerfeld COMPARE_INT(n_sep_by_space);
75*4f2483e5SBill Sommerfeld COMPARE_INT(p_sign_posn);
76*4f2483e5SBill Sommerfeld COMPARE_INT(n_sign_posn);
77*4f2483e5SBill Sommerfeld
78*4f2483e5SBill Sommerfeld COMPARE_INT(int_p_cs_precedes);
79*4f2483e5SBill Sommerfeld COMPARE_INT(int_p_sep_by_space);
80*4f2483e5SBill Sommerfeld COMPARE_INT(int_n_cs_precedes);
81*4f2483e5SBill Sommerfeld COMPARE_INT(int_n_sep_by_space);
82*4f2483e5SBill Sommerfeld COMPARE_INT(int_p_sign_posn);
83*4f2483e5SBill Sommerfeld COMPARE_INT(int_n_sign_posn);
84*4f2483e5SBill Sommerfeld
85*4f2483e5SBill Sommerfeld return (all_match);
86*4f2483e5SBill Sommerfeld }
87*4f2483e5SBill Sommerfeld int
main(void)88*4f2483e5SBill Sommerfeld main(void)
89*4f2483e5SBill Sommerfeld {
90*4f2483e5SBill Sommerfeld int ret = EXIT_SUCCESS;
91*4f2483e5SBill Sommerfeld
92*4f2483e5SBill Sommerfeld for (size_t i = 0; i < ARRAY_SIZE(locales); i++) {
93*4f2483e5SBill Sommerfeld locales[i].loc = newlocale(LC_ALL_MASK, locales[i].name, NULL);
94*4f2483e5SBill Sommerfeld if (locales[i].loc == NULL) {
95*4f2483e5SBill Sommerfeld err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to "
96*4f2483e5SBill Sommerfeld "construct locale %s", locales[i].name);
97*4f2483e5SBill Sommerfeld }
98*4f2483e5SBill Sommerfeld
99*4f2483e5SBill Sommerfeld if (uselocale(locales[i].loc) == NULL) {
100*4f2483e5SBill Sommerfeld err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to "
101*4f2483e5SBill Sommerfeld "set locale %s", locales[i].name);
102*4f2483e5SBill Sommerfeld }
103*4f2483e5SBill Sommerfeld
104*4f2483e5SBill Sommerfeld locales[i].lconv = *localeconv();
105*4f2483e5SBill Sommerfeld }
106*4f2483e5SBill Sommerfeld for (size_t i = 0; i < ARRAY_SIZE(locales); i++) {
107*4f2483e5SBill Sommerfeld if (!compare_lconv(locales[i].name,
108*4f2483e5SBill Sommerfeld localeconv_l(locales[i].loc),
109*4f2483e5SBill Sommerfeld &locales[i].lconv)) {
110*4f2483e5SBill Sommerfeld ret = EXIT_FAILURE;
111*4f2483e5SBill Sommerfeld }
112*4f2483e5SBill Sommerfeld }
113*4f2483e5SBill Sommerfeld
114*4f2483e5SBill Sommerfeld if (ret == EXIT_SUCCESS) {
115*4f2483e5SBill Sommerfeld (void) printf("All tests completed successfully\n");
116*4f2483e5SBill Sommerfeld }
117*4f2483e5SBill Sommerfeld
118*4f2483e5SBill Sommerfeld return (ret);
119*4f2483e5SBill Sommerfeld }
120