summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/locale/setlocale/setlocale.c
blob: 82245df5c5e6289edea6cb5fe8a7a7bc6038f89a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* $OpenBSD: setlocale.c,v 1.4 2018/03/29 16:34:25 schwarze Exp $ */
/*
 * Copyright (c) 2015 Sebastien Marie <semarie@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <err.h>
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

/*
 * test helpers for __LINE__
 */
#define test_setlocale(_e, _c, _l) _test_setlocale(_e, _c, _l, __LINE__)
#define test_MB_CUR_MAX(_e) _test_MB_CUR_MAX(_e, __LINE__)
#define test_isalpha(_e, _c) _test_isalpha(_e, _c, __LINE__)


static void
_test_setlocale(char *expected, int category, char *locale, int line)
{
	char *result = setlocale(category, locale);

	if ((expected == NULL) || (result == NULL)) {
		if (expected == result)
			return;

		errx(1, "[%d] setlocale(%d, \"%s\")=\"%s\" [expected: \"%s\"]",
		       line, category, locale, result, expected);
	}

	if (strcmp(expected, result) != 0)
		errx(1, "[%d] setlocale(%d, \"%s\")=\"%s\" [expected: \"%s\"]",
		       line, category, locale, result, expected);
}

static void
_test_MB_CUR_MAX(size_t expected, int line)
{
	if (MB_CUR_MAX != expected)
		errx(1, "[%d] MB_CUR_MAX=%ld [expected %ld]", 
			line, MB_CUR_MAX, expected);
}

static void
_test_isalpha(int expected, int c, int line)
{
	int result = isalpha(c);
	if (!!result != expected)
		errx(1, "[%d] isalpha(%d)=%d [expected %d]",
			line, c, result, expected);
}

int
main(int argc, char *argv[])
{
	/* check initial state (should be "C") */
	test_setlocale("C", LC_ALL, NULL); /* check */
	test_MB_CUR_MAX(1);
	test_isalpha(0, 0xe9); /* iso-8859-1 eacute */

	/* load from env */
	/* NOTE: we don't support non-C locales for some categories */
	test_setlocale("fr_FR.UTF-8", LC_CTYPE, ""); /* set */
	test_setlocale("fr_FR.UTF-8", LC_MESSAGES, ""); /* set */
	test_MB_CUR_MAX(4);
	test_isalpha(0, 0xe9); /* iso-8859-1 eacute */

	test_setlocale("C", LC_MESSAGES, "C"); /* set */
	test_MB_CUR_MAX(4);
	test_setlocale("C/fr_FR.UTF-8/C/C/C/C", LC_ALL, NULL); /* check */

	test_setlocale("C", LC_CTYPE, "C"); /* set */
	test_MB_CUR_MAX(1);
	test_setlocale("C", LC_ALL, NULL); /* check */

	/* check for errors on checking */
	test_setlocale("C", LC_ALL, "C"); /* reset */
	test_setlocale(NULL, -1, NULL);
	test_setlocale(NULL, _LC_LAST, NULL);
	test_setlocale(NULL, _LC_LAST+0xff, NULL);
	test_setlocale("C", LC_ALL, NULL); /* check */

	/* check for errors on setting */
	test_setlocale(NULL, -1, "");
	test_setlocale(NULL, _LC_LAST, "");
	test_setlocale(NULL, _LC_LAST+0xff, "");
	test_setlocale("C", LC_ALL, NULL); /* check */

	/* no codeset, fallback to ASCII */
	test_setlocale("C", LC_ALL, "C"); /* reset */
	test_setlocale("invalid", LC_CTYPE, "invalid"); /* set */
	test_setlocale("invalid", LC_CTYPE, NULL);
	test_MB_CUR_MAX(1);
	test_isalpha(0, 0xe9); /* iso-8859-1 eacute */

	/* with codeset */
	test_setlocale("C", LC_ALL, "C"); /* reset */
	test_setlocale("invalid.UTF-8", LC_CTYPE, "invalid.UTF-8"); /* set */
	test_setlocale("invalid.UTF-8", LC_CTYPE, NULL);
	test_setlocale("C/invalid.UTF-8/C/C/C/C", LC_ALL, NULL);
	test_MB_CUR_MAX(4);

	/* with invalid codeset (is an error) */
	test_setlocale("C", LC_ALL, "C"); /* reset */
	test_setlocale(NULL, LC_CTYPE, "fr_FR.invalid"); /* set */
	test_setlocale("C", LC_CTYPE, NULL);
	test_MB_CUR_MAX(1);

	return (EXIT_SUCCESS);
}