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 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 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