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