1 /*- 2 * Copyright (c) 2023 The FreeBSD Foundation 3 * 4 * This software was developed by Robert Clausecker <fuz@FreeBSD.org> 5 * under sponsorship from the FreeBSD Foundation. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ''AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE 27 */ 28 29 #include <sys/cdefs.h> 30 31 #include <atf-c.h> 32 #include <assert.h> 33 #include <limits.h> 34 #include <stdbool.h> 35 #include <stddef.h> 36 #include <string.h> 37 38 enum { 39 MAXALIGN = 16, /* test all offsets from this alignment */ 40 MAXBUF = 64, /* test up to this buffer length */ 41 }; 42 43 enum { NOMATCH, MATCH }; 44 45 #ifdef STRSPN 46 #define STRXSPN strspn 47 #else 48 #define STRXSPN strcspn 49 #endif 50 51 static void 52 testcase(char *buf, size_t buflen, char *set, size_t setlen, int want_match) 53 { 54 size_t i, outcome, expected; 55 56 assert(setlen < UCHAR_MAX - 2); 57 58 for (i = 0; i < buflen; i++) 59 #ifdef STRSPN 60 buf[i] = UCHAR_MAX - i % (setlen > 0 ? setlen : 1); 61 #else /* strcspn */ 62 buf[i] = 1 + i % (UCHAR_MAX - setlen - 1); 63 #endif 64 65 buf[i] = '\0'; 66 67 for (i = 0; i < setlen; i++) 68 set[i] = UCHAR_MAX - i; 69 70 set[i] = '\0'; 71 72 #ifdef STRSPN 73 if (setlen == 0) 74 expected = 0; 75 else if (want_match == MATCH && buflen > 0) { 76 buf[buflen - 1] = 1; 77 expected = buflen - 1; 78 } else 79 expected = buflen; 80 #else /* strcspn */ 81 if (want_match == MATCH && buflen > 0 && setlen > 0) { 82 buf[buflen - 1] = UCHAR_MAX; 83 expected = buflen - 1; 84 } else 85 expected = buflen; 86 #endif 87 88 outcome = STRXSPN(buf, set); 89 ATF_CHECK_EQ_MSG(expected, outcome, "%s(%p[%zu], %p[%zu]) = %zu != %zu", 90 __XSTRING(STRXSPN), buf, buflen, set, setlen, outcome, expected); 91 } 92 93 /* test set with all alignments and lengths of buf */ 94 static void 95 test_buf_alignments(char *set, size_t setlen, int want_match) 96 { 97 char buf[MAXALIGN + MAXBUF + 1]; 98 size_t i, j; 99 100 for (i = 0; i < MAXALIGN; i++) 101 for (j = 0; j <= MAXBUF; j++) 102 testcase(buf + i, j, set, setlen, want_match); 103 } 104 105 /* test buf with all alignments and lengths of set */ 106 static void 107 test_set_alignments(char *buf, size_t buflen, int want_match) 108 { 109 char set[MAXALIGN + MAXBUF + 1]; 110 size_t i, j; 111 112 for (i = 0; i < MAXALIGN; i++) 113 for (j = 0; j <= MAXBUF; j++) 114 testcase(buf, buflen, set + i, j, want_match); 115 } 116 117 ATF_TC_WITHOUT_HEAD(buf_alignments); 118 ATF_TC_BODY(buf_alignments, tc) 119 { 120 char set[41]; 121 122 test_buf_alignments(set, 0, MATCH); 123 test_buf_alignments(set, 1, MATCH); 124 test_buf_alignments(set, 5, MATCH); 125 test_buf_alignments(set, 20, MATCH); 126 test_buf_alignments(set, 40, MATCH); 127 128 test_buf_alignments(set, 0, NOMATCH); 129 test_buf_alignments(set, 1, NOMATCH); 130 test_buf_alignments(set, 5, NOMATCH); 131 test_buf_alignments(set, 20, NOMATCH); 132 test_buf_alignments(set, 40, NOMATCH); 133 } 134 135 ATF_TC_WITHOUT_HEAD(set_alignments); 136 ATF_TC_BODY(set_alignments, tc) 137 { 138 char buf[31]; 139 140 test_set_alignments(buf, 0, MATCH); 141 test_set_alignments(buf, 10, MATCH); 142 test_set_alignments(buf, 20, MATCH); 143 test_set_alignments(buf, 30, MATCH); 144 145 test_set_alignments(buf, 0, NOMATCH); 146 test_set_alignments(buf, 10, NOMATCH); 147 test_set_alignments(buf, 20, NOMATCH); 148 test_set_alignments(buf, 30, NOMATCH); 149 } 150 151 ATF_TP_ADD_TCS(tp) 152 { 153 ATF_TP_ADD_TC(tp, buf_alignments); 154 ATF_TP_ADD_TC(tp, set_alignments); 155 156 return (atf_no_error()); 157 } 158