1/* Test c16rtomb handling of surrogate pairs (DR#488, bug 23794).
2 Copyright (C) 2018-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <errno.h>
20#include <locale.h>
21#include <stdio.h>
22#include <string.h>
23#include <uchar.h>
24#include <wchar.h>
25#include <array_length.h>
26#include <support/check.h>
27
28static int
29do_test (void)
30{
31 TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL);
32 /* Test conversions of surrogate pairs. */
33 for (char32_t c = 0x10000; c <= 0x10ffff; c += 0x123)
34 {
35 char32_t c_pos = c - 0x10000;
36 char16_t c_hi = (c_pos >> 10) + 0xd800;
37 char16_t c_lo = (c_pos & 0x3ff) + 0xdc00;
38 printf (format: "testing U+0x%08x (0x%x 0x%x)\n",
39 (unsigned int) c, (unsigned int) c_hi, (unsigned int) c_lo);
40 char buf[16] = { 0 };
41 size_t ret_hi = c16rtomb (s: buf, c16: c_hi, NULL);
42 TEST_COMPARE (ret_hi, 0);
43 size_t ret_lo = c16rtomb (s: buf, c16: c_lo, NULL);
44 TEST_COMPARE (ret_lo, 4);
45 wchar_t wc = 0;
46 size_t ret_wc = mbrtowc (&wc, buf, 4, NULL);
47 TEST_COMPARE (ret_wc, 4);
48 TEST_COMPARE (wc, (wchar_t) c);
49 }
50 /* Test errors for invalid conversions. */
51 static const char16_t err_cases[][2] =
52 {
53 /* High surrogate followed by non-surrogate. */
54 { 0xd800, 0x1 },
55 /* High surrogate followed by another high surrogate. */
56 { 0xd800, 0xd800 },
57 /* Low surrogate not following high surrogate. */
58 { 0xdc00, 0 }
59 };
60 for (size_t i = 0; i < array_length (err_cases); i++)
61 {
62 char16_t c_hi = err_cases[i][0];
63 char16_t c_lo = err_cases[i][1];
64 printf (format: "testing error case: 0x%x 0x%x\n", (unsigned int) c_hi,
65 (unsigned int) c_lo);
66 c16rtomb (NULL, c16: 0, NULL);
67 char buf[16] = { 0 };
68 errno = 0;
69 size_t ret_hi = c16rtomb (s: buf, c16: c_hi, NULL);
70 if (c_lo == 0)
71 {
72 /* Unmatched low surrogate in first place. */
73 TEST_COMPARE (ret_hi, (size_t) -1);
74 TEST_COMPARE (errno, EILSEQ);
75 }
76 else
77 {
78 /* High surrogate; error in second place. */
79 TEST_COMPARE (ret_hi, 0);
80 errno = 0;
81 size_t ret_lo = c16rtomb (s: buf, c16: c_lo, NULL);
82 TEST_COMPARE (ret_lo, (size_t) -1);
83 TEST_COMPARE (errno, EILSEQ);
84 }
85 }
86 return 0;
87}
88
89#include <support/test-driver.c>
90

source code of glibc/wcsmbs/tst-c16-surrogate.c