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