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