xref: /freebsd/lib/libc/tests/locale/mbrtoc16_test.c (revision 559a218c9b257775fb249b67945fe4a05b7a6b9f)
19da7d79fSEnji Cooper /*-
29da7d79fSEnji Cooper  * Copyright (c) 2002 Tim J. Robbins
39da7d79fSEnji Cooper  * All rights reserved.
49da7d79fSEnji Cooper  *
59da7d79fSEnji Cooper  * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org>
69da7d79fSEnji Cooper  * All rights reserved.
79da7d79fSEnji Cooper  *
89da7d79fSEnji Cooper  * Redistribution and use in source and binary forms, with or without
99da7d79fSEnji Cooper  * modification, are permitted provided that the following conditions
109da7d79fSEnji Cooper  * are met:
119da7d79fSEnji Cooper  * 1. Redistributions of source code must retain the above copyright
129da7d79fSEnji Cooper  *    notice, this list of conditions and the following disclaimer.
139da7d79fSEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
149da7d79fSEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
159da7d79fSEnji Cooper  *    documentation and/or other materials provided with the distribution.
169da7d79fSEnji Cooper  *
179da7d79fSEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
189da7d79fSEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199da7d79fSEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
209da7d79fSEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
219da7d79fSEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
229da7d79fSEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
239da7d79fSEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
249da7d79fSEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
259da7d79fSEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
269da7d79fSEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
279da7d79fSEnji Cooper  * SUCH DAMAGE.
289da7d79fSEnji Cooper  */
299da7d79fSEnji Cooper /*
309da7d79fSEnji Cooper  * Test program for mbrtoc16() as specified by ISO/IEC 9899:2011.
319da7d79fSEnji Cooper  */
329da7d79fSEnji Cooper 
339da7d79fSEnji Cooper #include <errno.h>
349da7d79fSEnji Cooper #include <limits.h>
359da7d79fSEnji Cooper #include <locale.h>
369da7d79fSEnji Cooper #include <stdio.h>
379da7d79fSEnji Cooper #include <string.h>
389da7d79fSEnji Cooper #include <uchar.h>
399da7d79fSEnji Cooper 
409da7d79fSEnji Cooper #include <atf-c.h>
419da7d79fSEnji Cooper 
42*cc4ac19cSEnji Cooper static void
require_lc_ctype(const char * locale_name)43*cc4ac19cSEnji Cooper require_lc_ctype(const char *locale_name)
449da7d79fSEnji Cooper {
45*cc4ac19cSEnji Cooper 	char *lc_ctype_set;
469da7d79fSEnji Cooper 
47*cc4ac19cSEnji Cooper 	lc_ctype_set = setlocale(LC_CTYPE, locale_name);
48*cc4ac19cSEnji Cooper 	if (lc_ctype_set == NULL)
49*cc4ac19cSEnji Cooper 		atf_tc_fail("setlocale(LC_CTYPE, \"%s\") failed; errno=%d",
50*cc4ac19cSEnji Cooper 		    locale_name, errno);
51*cc4ac19cSEnji Cooper 
52*cc4ac19cSEnji Cooper 	ATF_REQUIRE(strcmp(lc_ctype_set, locale_name) == 0);
53*cc4ac19cSEnji Cooper }
54*cc4ac19cSEnji Cooper 
55*cc4ac19cSEnji Cooper static mbstate_t s;
56*cc4ac19cSEnji Cooper static char16_t c16;
57*cc4ac19cSEnji Cooper 
58*cc4ac19cSEnji Cooper ATF_TC_WITHOUT_HEAD(mbrtoc16_c_locale_test);
ATF_TC_BODY(mbrtoc16_c_locale_test,tc)59*cc4ac19cSEnji Cooper ATF_TC_BODY(mbrtoc16_c_locale_test, tc)
60*cc4ac19cSEnji Cooper {
61*cc4ac19cSEnji Cooper 
62*cc4ac19cSEnji Cooper 	require_lc_ctype("C");
639da7d79fSEnji Cooper 
649da7d79fSEnji Cooper 	/* Null wide character, internal state. */
659da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 1, NULL) == 0);
669da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0);
679da7d79fSEnji Cooper 
689da7d79fSEnji Cooper 	/* Null wide character. */
699da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
709da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 1, &s) == 0);
719da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0);
729da7d79fSEnji Cooper 
739da7d79fSEnji Cooper 	/* Latin letter A, internal state. */
749da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0);
759da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "A", 1, NULL) == 1);
769da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'A');
779da7d79fSEnji Cooper 
789da7d79fSEnji Cooper 	/* Latin letter A. */
799da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
809da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "A", 1, &s) == 1);
819da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'A');
829da7d79fSEnji Cooper 
839da7d79fSEnji Cooper 	/* Incomplete character sequence. */
849da7d79fSEnji Cooper 	c16 = L'z';
859da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
869da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
879da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'z');
889da7d79fSEnji Cooper 
899da7d79fSEnji Cooper 	/* Check that mbrtoc16() doesn't access the buffer when n == 0. */
909da7d79fSEnji Cooper 	c16 = L'z';
919da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
929da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
939da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'z');
949da7d79fSEnji Cooper 
959da7d79fSEnji Cooper 	/* Check that mbrtoc16() doesn't read ahead too aggressively. */
969da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
979da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "AB", 2, &s) == 1);
989da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'A');
999da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "C", 1, &s) == 1);
1009da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'C');
1019da7d79fSEnji Cooper 
102*cc4ac19cSEnji Cooper }
1039da7d79fSEnji Cooper 
104*cc4ac19cSEnji Cooper ATF_TC_WITHOUT_HEAD(mbrtoc16_iso_8859_1_test);
ATF_TC_BODY(mbrtoc16_iso_8859_1_test,tc)105*cc4ac19cSEnji Cooper ATF_TC_BODY(mbrtoc16_iso_8859_1_test, tc)
106*cc4ac19cSEnji Cooper {
107*cc4ac19cSEnji Cooper 
108*cc4ac19cSEnji Cooper 	require_lc_ctype("en_US.ISO8859-1");
1099da7d79fSEnji Cooper 
1109da7d79fSEnji Cooper 	/* Currency sign. */
1119da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1129da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xa4", 1, &s) == 1);
1139da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0xa4);
114*cc4ac19cSEnji Cooper }
1159da7d79fSEnji Cooper 
116*cc4ac19cSEnji Cooper ATF_TC_WITHOUT_HEAD(mbrtoc16_iso_8859_15_test);
ATF_TC_BODY(mbrtoc16_iso_8859_15_test,tc)117*cc4ac19cSEnji Cooper ATF_TC_BODY(mbrtoc16_iso_8859_15_test, tc)
118*cc4ac19cSEnji Cooper {
1199da7d79fSEnji Cooper 
120*cc4ac19cSEnji Cooper 	require_lc_ctype("en_US.ISO8859-15");
1219da7d79fSEnji Cooper 
1229da7d79fSEnji Cooper 	/* Euro sign. */
1239da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1249da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xa4", 1, &s) == 1);
1259da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0x20ac);
126*cc4ac19cSEnji Cooper }
1279da7d79fSEnji Cooper 
128*cc4ac19cSEnji Cooper ATF_TC_WITHOUT_HEAD(mbrtoc16_utf_8_test);
ATF_TC_BODY(mbrtoc16_utf_8_test,tc)129*cc4ac19cSEnji Cooper ATF_TC_BODY(mbrtoc16_utf_8_test, tc)
130*cc4ac19cSEnji Cooper {
1319da7d79fSEnji Cooper 
132*cc4ac19cSEnji Cooper 	require_lc_ctype("en_US.UTF-8");
1339da7d79fSEnji Cooper 
1349da7d79fSEnji Cooper 	/* Null wide character, internal state. */
1359da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0);
1369da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 1, NULL) == 0);
1379da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0);
1389da7d79fSEnji Cooper 
1399da7d79fSEnji Cooper 	/* Null wide character. */
1409da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1419da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 1, &s) == 0);
1429da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0);
1439da7d79fSEnji Cooper 
1449da7d79fSEnji Cooper 	/* Latin letter A, internal state. */
1459da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0);
1469da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "A", 1, NULL) == 1);
1479da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'A');
1489da7d79fSEnji Cooper 
1499da7d79fSEnji Cooper 	/* Latin letter A. */
1509da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1519da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "A", 1, &s) == 1);
1529da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'A');
1539da7d79fSEnji Cooper 
1549da7d79fSEnji Cooper 	/* Incomplete character sequence (zero length). */
1559da7d79fSEnji Cooper 	c16 = L'z';
1569da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1579da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
1589da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == L'z');
1599da7d79fSEnji Cooper 
1609da7d79fSEnji Cooper 	/* Incomplete character sequence (truncated double-byte). */
1619da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1629da7d79fSEnji Cooper 	c16 = 0;
1639da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2);
1649da7d79fSEnji Cooper 
1659da7d79fSEnji Cooper 	/* Same as above, but complete. */
1669da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1679da7d79fSEnji Cooper 	c16 = 0;
1689da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xc3\x84", 2, &s) == 2);
1699da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0xc4);
1709da7d79fSEnji Cooper 
1719da7d79fSEnji Cooper 	/* Test restarting behaviour. */
1729da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1739da7d79fSEnji Cooper 	c16 = 0;
1749da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2);
1759da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0);
1769da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xb7", 1, &s) == 1);
1779da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0xf7);
1789da7d79fSEnji Cooper 
1799da7d79fSEnji Cooper 	/* Surrogate pair. */
1809da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1819da7d79fSEnji Cooper 	c16 = 0;
1829da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xf0\x9f\x92\xa9", 4, &s) == 4);
1839da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0xd83d);
1849da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-3);
1859da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0xdca9);
1869da7d79fSEnji Cooper 
1879da7d79fSEnji Cooper 	/* Letter e with acute, precomposed. */
1889da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1899da7d79fSEnji Cooper 	c16 = 0;
1909da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xc3\xa9", 2, &s) == 2);
1919da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0xe9);
1929da7d79fSEnji Cooper 
1939da7d79fSEnji Cooper 	/* Letter e with acute, combined. */
1949da7d79fSEnji Cooper 	memset(&s, 0, sizeof(s));
1959da7d79fSEnji Cooper 	c16 = 0;
1969da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\x65\xcc\x81", 3, &s) == 1);
1979da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0x65);
1989da7d79fSEnji Cooper 	ATF_REQUIRE(mbrtoc16(&c16, "\xcc\x81", 2, &s) == 2);
1999da7d79fSEnji Cooper 	ATF_REQUIRE(c16 == 0x301);
2009da7d79fSEnji Cooper }
2019da7d79fSEnji Cooper 
ATF_TP_ADD_TCS(tp)2029da7d79fSEnji Cooper ATF_TP_ADD_TCS(tp)
2039da7d79fSEnji Cooper {
2049da7d79fSEnji Cooper 
205*cc4ac19cSEnji Cooper 	ATF_TP_ADD_TC(tp, mbrtoc16_c_locale_test);
206*cc4ac19cSEnji Cooper 	ATF_TP_ADD_TC(tp, mbrtoc16_iso_8859_1_test);
207*cc4ac19cSEnji Cooper 	ATF_TP_ADD_TC(tp, mbrtoc16_iso_8859_15_test);
208*cc4ac19cSEnji Cooper 	ATF_TP_ADD_TC(tp, mbrtoc16_utf_8_test);
2099da7d79fSEnji Cooper 
2109da7d79fSEnji Cooper 	return (atf_no_error());
2119da7d79fSEnji Cooper }
212