1*71f3ceb9SRobert Mustacchi /*
2*71f3ceb9SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*71f3ceb9SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*71f3ceb9SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*71f3ceb9SRobert Mustacchi * 1.0 of the CDDL.
6*71f3ceb9SRobert Mustacchi *
7*71f3ceb9SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*71f3ceb9SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*71f3ceb9SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*71f3ceb9SRobert Mustacchi */
11*71f3ceb9SRobert Mustacchi
12*71f3ceb9SRobert Mustacchi /*
13*71f3ceb9SRobert Mustacchi * Copyright 2025 Oxide Computer Company
14*71f3ceb9SRobert Mustacchi */
15*71f3ceb9SRobert Mustacchi
16*71f3ceb9SRobert Mustacchi /*
17*71f3ceb9SRobert Mustacchi * Test various aspects of wcslcpy. We use various size buffers, fill each with
18*71f3ceb9SRobert Mustacchi * a stock character that we don't use in the test, and then ensure that we get
19*71f3ceb9SRobert Mustacchi * both the expected return value and the expected buffer contents.
20*71f3ceb9SRobert Mustacchi */
21*71f3ceb9SRobert Mustacchi
22*71f3ceb9SRobert Mustacchi #include <wchar.h>
23*71f3ceb9SRobert Mustacchi #include <err.h>
24*71f3ceb9SRobert Mustacchi #include <stdlib.h>
25*71f3ceb9SRobert Mustacchi #include <stdbool.h>
26*71f3ceb9SRobert Mustacchi #include <stdio.h>
27*71f3ceb9SRobert Mustacchi #include <sys/sysmacros.h>
28*71f3ceb9SRobert Mustacchi #include <sys/debug.h>
29*71f3ceb9SRobert Mustacchi
30*71f3ceb9SRobert Mustacchi #define WCSLCPY_BUFLEN 16
31*71f3ceb9SRobert Mustacchi
32*71f3ceb9SRobert Mustacchi typedef struct wcslcpy_test {
33*71f3ceb9SRobert Mustacchi const char *wt_desc;
34*71f3ceb9SRobert Mustacchi wchar_t *wt_src;
35*71f3ceb9SRobert Mustacchi size_t wt_rval;
36*71f3ceb9SRobert Mustacchi size_t wt_dstlen;
37*71f3ceb9SRobert Mustacchi wchar_t wt_res[WCSLCPY_BUFLEN];
38*71f3ceb9SRobert Mustacchi } wcslcpy_test_t;
39*71f3ceb9SRobert Mustacchi
40*71f3ceb9SRobert Mustacchi static const wcslcpy_test_t wcslcpy_tests[] = { {
41*71f3ceb9SRobert Mustacchi .wt_desc = "Zero-sized Destination Buffer (1)",
42*71f3ceb9SRobert Mustacchi .wt_src = L"Hello, World!",
43*71f3ceb9SRobert Mustacchi .wt_rval = 13,
44*71f3ceb9SRobert Mustacchi .wt_dstlen = 0,
45*71f3ceb9SRobert Mustacchi .wt_res = { L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-',
46*71f3ceb9SRobert Mustacchi L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-' }
47*71f3ceb9SRobert Mustacchi }, {
48*71f3ceb9SRobert Mustacchi .wt_desc = "Zero-sized Destination Buffer (2)",
49*71f3ceb9SRobert Mustacchi .wt_src = L"光",
50*71f3ceb9SRobert Mustacchi .wt_rval = 1,
51*71f3ceb9SRobert Mustacchi .wt_dstlen = 0,
52*71f3ceb9SRobert Mustacchi .wt_res = { L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-',
53*71f3ceb9SRobert Mustacchi L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-' }
54*71f3ceb9SRobert Mustacchi }, {
55*71f3ceb9SRobert Mustacchi .wt_desc = "Truncation (1)",
56*71f3ceb9SRobert Mustacchi .wt_src = L"asdfasdfasdfasdfasdf",
57*71f3ceb9SRobert Mustacchi .wt_rval = 20,
58*71f3ceb9SRobert Mustacchi .wt_dstlen = WCSLCPY_BUFLEN,
59*71f3ceb9SRobert Mustacchi .wt_res = { L'a', L's', L'd', L'f', L'a', L's', L'd', L'f',
60*71f3ceb9SRobert Mustacchi L'a', L's', L'd', L'f', L'a', L's', L'd', L'\0' }
61*71f3ceb9SRobert Mustacchi }, {
62*71f3ceb9SRobert Mustacchi .wt_desc = "Truncation (2)",
63*71f3ceb9SRobert Mustacchi .wt_src = L"77777777777777777777777",
64*71f3ceb9SRobert Mustacchi .wt_rval = 23,
65*71f3ceb9SRobert Mustacchi .wt_dstlen = WCSLCPY_BUFLEN,
66*71f3ceb9SRobert Mustacchi .wt_res = { L'7', L'7', L'7', L'7', L'7', L'7', L'7', L'7',
67*71f3ceb9SRobert Mustacchi L'7', L'7', L'7', L'7', L'7', L'7', L'7', L'\0' }
68*71f3ceb9SRobert Mustacchi }, {
69*71f3ceb9SRobert Mustacchi .wt_desc = "Short Write (small buf)",
70*71f3ceb9SRobert Mustacchi .wt_src = L"@",
71*71f3ceb9SRobert Mustacchi .wt_rval = 1,
72*71f3ceb9SRobert Mustacchi .wt_dstlen = 2,
73*71f3ceb9SRobert Mustacchi .wt_res = { L'@', L'\0', L'-', L'-', L'-', L'-', L'-', L'-',
74*71f3ceb9SRobert Mustacchi L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-' }
75*71f3ceb9SRobert Mustacchi }, {
76*71f3ceb9SRobert Mustacchi .wt_desc = "Short Write (small src)",
77*71f3ceb9SRobert Mustacchi .wt_src = L"@",
78*71f3ceb9SRobert Mustacchi .wt_rval = 1,
79*71f3ceb9SRobert Mustacchi .wt_dstlen = WCSLCPY_BUFLEN,
80*71f3ceb9SRobert Mustacchi .wt_res = { L'@', L'\0', L'-', L'-', L'-', L'-', L'-', L'-',
81*71f3ceb9SRobert Mustacchi L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-' }
82*71f3ceb9SRobert Mustacchi }, {
83*71f3ceb9SRobert Mustacchi .wt_desc = "Short Write (smallish src)",
84*71f3ceb9SRobert Mustacchi .wt_src = L"Sephiroth",
85*71f3ceb9SRobert Mustacchi .wt_rval = 9,
86*71f3ceb9SRobert Mustacchi .wt_dstlen = WCSLCPY_BUFLEN,
87*71f3ceb9SRobert Mustacchi .wt_res = { L'S', L'e', L'p', L'h', L'i', L'r', L'o', L't',
88*71f3ceb9SRobert Mustacchi L'h', L'\0', L'-', L'-', L'-', L'-', L'-', L'-' }
89*71f3ceb9SRobert Mustacchi }, {
90*71f3ceb9SRobert Mustacchi .wt_desc = "full buffer, no trunc",
91*71f3ceb9SRobert Mustacchi .wt_src = L"this is a buffe",
92*71f3ceb9SRobert Mustacchi .wt_rval = 15,
93*71f3ceb9SRobert Mustacchi .wt_dstlen = WCSLCPY_BUFLEN,
94*71f3ceb9SRobert Mustacchi .wt_res = { L't', L'h', L'i', L's', L' ', L'i', L's', L' ',
95*71f3ceb9SRobert Mustacchi L'a', L' ', L'b', L'u', L'f', L'f', L'e', L'\0' }
96*71f3ceb9SRobert Mustacchi }, {
97*71f3ceb9SRobert Mustacchi .wt_desc = "empty buffer, empty src",
98*71f3ceb9SRobert Mustacchi .wt_src = L"",
99*71f3ceb9SRobert Mustacchi .wt_rval = 0,
100*71f3ceb9SRobert Mustacchi .wt_dstlen = 0,
101*71f3ceb9SRobert Mustacchi .wt_res = { L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-',
102*71f3ceb9SRobert Mustacchi L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-' }
103*71f3ceb9SRobert Mustacchi }, {
104*71f3ceb9SRobert Mustacchi .wt_desc = "full buffer, empty src",
105*71f3ceb9SRobert Mustacchi .wt_src = L"",
106*71f3ceb9SRobert Mustacchi .wt_rval = 0,
107*71f3ceb9SRobert Mustacchi .wt_dstlen = WCSLCPY_BUFLEN,
108*71f3ceb9SRobert Mustacchi .wt_res = { L'\0', L'-', L'-', L'-', L'-', L'-', L'-', L'-',
109*71f3ceb9SRobert Mustacchi L'-', L'-', L'-', L'-', L'-', L'-', L'-', L'-' }
110*71f3ceb9SRobert Mustacchi } };
111*71f3ceb9SRobert Mustacchi
112*71f3ceb9SRobert Mustacchi static bool
wcslcpy_test_one(const wcslcpy_test_t * test)113*71f3ceb9SRobert Mustacchi wcslcpy_test_one(const wcslcpy_test_t *test)
114*71f3ceb9SRobert Mustacchi {
115*71f3ceb9SRobert Mustacchi wchar_t buf[WCSLCPY_BUFLEN];
116*71f3ceb9SRobert Mustacchi size_t wcret, dstlen;
117*71f3ceb9SRobert Mustacchi bool ret = true;
118*71f3ceb9SRobert Mustacchi
119*71f3ceb9SRobert Mustacchi (void) wmemset(buf, L'-', ARRAY_SIZE(buf));
120*71f3ceb9SRobert Mustacchi dstlen = MIN(ARRAY_SIZE(buf), test->wt_dstlen);
121*71f3ceb9SRobert Mustacchi VERIFY3U(test->wt_dstlen, ==, dstlen);
122*71f3ceb9SRobert Mustacchi
123*71f3ceb9SRobert Mustacchi wcret = wcslcpy(buf, test->wt_src, dstlen);
124*71f3ceb9SRobert Mustacchi if (wcret != test->wt_rval) {
125*71f3ceb9SRobert Mustacchi warnx("TEST FAILED: %s: wcslcpy() returned %zu, expected %zu",
126*71f3ceb9SRobert Mustacchi test->wt_desc, wcret, test->wt_rval);
127*71f3ceb9SRobert Mustacchi ret = false;
128*71f3ceb9SRobert Mustacchi }
129*71f3ceb9SRobert Mustacchi
130*71f3ceb9SRobert Mustacchi if (wmemcmp(buf, test->wt_res, ARRAY_SIZE(buf)) != 0) {
131*71f3ceb9SRobert Mustacchi warnx("TEST FAILED: %s: resulting buffer mismatch: found vs. "
132*71f3ceb9SRobert Mustacchi "expected", test->wt_desc);
133*71f3ceb9SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(buf); i++) {
134*71f3ceb9SRobert Mustacchi (void) printf("\t[%zu] = [0x%x] vs [0x%x]\n", i, buf[i],
135*71f3ceb9SRobert Mustacchi test->wt_res[i]);
136*71f3ceb9SRobert Mustacchi }
137*71f3ceb9SRobert Mustacchi ret = false;
138*71f3ceb9SRobert Mustacchi }
139*71f3ceb9SRobert Mustacchi
140*71f3ceb9SRobert Mustacchi if (ret) {
141*71f3ceb9SRobert Mustacchi (void) printf("TEST PASSED: %s\n", test->wt_desc);
142*71f3ceb9SRobert Mustacchi }
143*71f3ceb9SRobert Mustacchi
144*71f3ceb9SRobert Mustacchi return (ret);
145*71f3ceb9SRobert Mustacchi }
146*71f3ceb9SRobert Mustacchi
147*71f3ceb9SRobert Mustacchi int
main(void)148*71f3ceb9SRobert Mustacchi main(void)
149*71f3ceb9SRobert Mustacchi {
150*71f3ceb9SRobert Mustacchi int ret = EXIT_SUCCESS;
151*71f3ceb9SRobert Mustacchi
152*71f3ceb9SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(wcslcpy_tests); i++) {
153*71f3ceb9SRobert Mustacchi if (!wcslcpy_test_one(&wcslcpy_tests[i]))
154*71f3ceb9SRobert Mustacchi ret = EXIT_FAILURE;
155*71f3ceb9SRobert Mustacchi }
156*71f3ceb9SRobert Mustacchi
157*71f3ceb9SRobert Mustacchi if (ret == EXIT_SUCCESS) {
158*71f3ceb9SRobert Mustacchi (void) printf("All tests passed successfully!\n");
159*71f3ceb9SRobert Mustacchi }
160*71f3ceb9SRobert Mustacchi
161*71f3ceb9SRobert Mustacchi return (ret);
162*71f3ceb9SRobert Mustacchi }
163