ascii_test.c revision 1.2 1 1.1 christos /* $NetBSD: ascii_test.c,v 1.2 2025/01/26 16:25:49 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos *
6 1.1 christos * SPDX-License-Identifier: MPL-2.0
7 1.1 christos *
8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 1.1 christos *
12 1.1 christos * See the COPYRIGHT file distributed with this work for additional
13 1.1 christos * information regarding copyright ownership.
14 1.1 christos */
15 1.1 christos
16 1.1 christos #include <ctype.h>
17 1.1 christos #include <inttypes.h>
18 1.1 christos #include <sched.h> /* IWYU pragma: keep */
19 1.1 christos #include <setjmp.h>
20 1.1 christos #include <stdarg.h>
21 1.1 christos #include <stdlib.h>
22 1.1 christos
23 1.1 christos #define UNIT_TESTING
24 1.1 christos #include <cmocka.h>
25 1.1 christos
26 1.1 christos #include <isc/ascii.h>
27 1.1 christos
28 1.1 christos #include <tests/isc.h>
29 1.1 christos
30 1.1 christos const char *same[][2] = {
31 1.1 christos {
32 1.1 christos "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
33 1.1 christos "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
34 1.1 christos },
35 1.1 christos {
36 1.1 christos "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
37 1.1 christos "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ",
38 1.1 christos },
39 1.1 christos {
40 1.1 christos "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ",
41 1.1 christos "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
42 1.1 christos },
43 1.1 christos {
44 1.1 christos "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ",
45 1.1 christos "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
46 1.1 christos },
47 1.1 christos {
48 1.1 christos "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVxXyYzZ",
49 1.1 christos "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvxxyyzz",
50 1.1 christos },
51 1.1 christos {
52 1.1 christos "WwW.ExAmPlE.OrG",
53 1.1 christos "wWw.eXaMpLe.oRg",
54 1.1 christos },
55 1.1 christos {
56 1.1 christos "_SIP.tcp.example.org",
57 1.1 christos "_sip.TCP.example.org",
58 1.1 christos },
59 1.1 christos {
60 1.1 christos "bind-USERS.lists.example.org",
61 1.1 christos "bind-users.lists.example.org",
62 1.1 christos },
63 1.1 christos {
64 1.1 christos "a0123456789.example.org",
65 1.1 christos "A0123456789.example.org",
66 1.1 christos },
67 1.1 christos {
68 1.1 christos "\\000.example.org",
69 1.1 christos "\\000.example.org",
70 1.1 christos },
71 1.1 christos {
72 1.1 christos "wWw.\\000.isc.org",
73 1.1 christos "www.\\000.isc.org",
74 1.1 christos },
75 1.1 christos {
76 1.1 christos "\255.example.org",
77 1.1 christos "\255.example.ORG",
78 1.1 christos }
79 1.1 christos };
80 1.1 christos
81 1.1 christos struct {
82 1.1 christos const char *a, *b;
83 1.1 christos int cmp;
84 1.1 christos } diff[] = {
85 1.1 christos { "foo", "bar", +1 },
86 1.1 christos { "bar", "foo", -1 },
87 1.1 christos { "foosuffix", "barsuffix", +1 },
88 1.1 christos { "barsuffix", "foosuffix", -1 },
89 1.1 christos { "prefixfoo", "prefixbar", +1 },
90 1.1 christos { "prefixbar", "prefixfoo", -1 },
91 1.1 christos };
92 1.1 christos
93 1.1 christos ISC_RUN_TEST_IMPL(upperlower) {
94 1.1 christos UNUSED(state);
95 1.1 christos
96 1.1 christos for (size_t n = 0; n < ARRAY_SIZE(same); n++) {
97 1.1 christos const char *a = same[n][0];
98 1.1 christos const char *b = same[n][1];
99 1.1 christos for (size_t i = 0; a[i] != '\0' && b[i] != '\0'; i++) {
100 1.1 christos assert_true(isc_ascii_toupper(a[i]) == (uint8_t)a[i] ||
101 1.1 christos isc_ascii_tolower(a[i]) == (uint8_t)a[i]);
102 1.1 christos assert_true(isc_ascii_toupper(b[i]) == (uint8_t)b[i] ||
103 1.1 christos isc_ascii_tolower(b[i]) == (uint8_t)b[i]);
104 1.1 christos assert_true(isc_ascii_toupper(a[i]) ==
105 1.1 christos isc_ascii_toupper(b[i]));
106 1.1 christos assert_true(isc_ascii_tolower(a[i]) ==
107 1.1 christos isc_ascii_tolower(b[i]));
108 1.1 christos }
109 1.1 christos }
110 1.1 christos }
111 1.1 christos
112 1.1 christos ISC_RUN_TEST_IMPL(lowerequal) {
113 1.1 christos for (size_t n = 0; n < ARRAY_SIZE(same); n++) {
114 1.1 christos const uint8_t *a = (void *)same[n][0];
115 1.1 christos const uint8_t *b = (void *)same[n][1];
116 1.1 christos unsigned int len = (unsigned int)strlen(same[n][0]);
117 1.1 christos assert_true(isc_ascii_lowerequal(a, b, len));
118 1.1 christos }
119 1.1 christos for (size_t n = 0; n < ARRAY_SIZE(diff); n++) {
120 1.1 christos const uint8_t *a = (void *)diff[n].a;
121 1.1 christos const uint8_t *b = (void *)diff[n].b;
122 1.1 christos unsigned int len = (unsigned int)strlen(diff[n].a);
123 1.1 christos assert_true(!isc_ascii_lowerequal(a, b, len));
124 1.1 christos }
125 1.1 christos }
126 1.1 christos
127 1.1 christos ISC_RUN_TEST_IMPL(lowercmp) {
128 1.1 christos for (size_t n = 0; n < ARRAY_SIZE(same); n++) {
129 1.1 christos const uint8_t *a = (void *)same[n][0];
130 1.1 christos const uint8_t *b = (void *)same[n][1];
131 1.1 christos unsigned int len = (unsigned int)strlen(same[n][0]);
132 1.1 christos assert_true(isc_ascii_lowercmp(a, b, len) == 0);
133 1.1 christos }
134 1.1 christos for (size_t n = 0; n < ARRAY_SIZE(diff); n++) {
135 1.1 christos const uint8_t *a = (void *)diff[n].a;
136 1.1 christos const uint8_t *b = (void *)diff[n].b;
137 1.1 christos unsigned int len = (unsigned int)strlen(diff[n].a);
138 1.1 christos assert_true(isc_ascii_lowercmp(a, b, len) == diff[n].cmp);
139 1.1 christos }
140 1.1 christos }
141 1.1 christos
142 1.1 christos ISC_RUN_TEST_IMPL(exhaustive) {
143 1.1 christos for (uint64_t ab = 0; ab < (1 << 16); ab++) {
144 1.1 christos uint8_t a = ab >> 8;
145 1.1 christos uint8_t b = ab & 0xFF;
146 1.1 christos uint64_t abc = tolower(a) << 8 | tolower(b);
147 1.1 christos uint64_t abi = isc_ascii_tolower(a) << 8 | isc_ascii_tolower(b);
148 1.1 christos uint64_t ab1 = isc__ascii_tolower1(a) << 8 |
149 1.1 christos isc__ascii_tolower1(b);
150 1.1 christos uint64_t ab8 = isc_ascii_tolower8(ab);
151 1.1 christos /* each byte individually matches ctype.h */
152 1.1 christos assert_int_equal(tolower(a), isc_ascii_tolower(a));
153 1.1 christos assert_int_equal(tolower(a), isc__ascii_tolower1(a));
154 1.1 christos assert_int_equal(tolower(a), isc_ascii_tolower8(a));
155 1.1 christos assert_int_equal(tolower(b), isc_ascii_tolower(b));
156 1.1 christos assert_int_equal(tolower(b), isc__ascii_tolower1(b));
157 1.1 christos assert_int_equal(tolower(b), isc_ascii_tolower8(b));
158 1.1 christos /* two lanes of SWAR match other implementations */
159 1.1 christos assert_int_equal(ab8, abc);
160 1.1 christos assert_int_equal(ab8, abi);
161 1.1 christos assert_int_equal(ab8, ab1);
162 1.1 christos /* check lack of overflow */
163 1.1 christos assert_int_equal(ab8 >> 16, 0);
164 1.1 christos /* all lanes of SWAR work */
165 1.1 christos assert_int_equal(isc_ascii_tolower8(ab << 8), abc << 8);
166 1.1 christos assert_int_equal(isc_ascii_tolower8(ab << 16), abc << 16);
167 1.1 christos assert_int_equal(isc_ascii_tolower8(ab << 24), abc << 24);
168 1.1 christos assert_int_equal(isc_ascii_tolower8(ab << 32), abc << 32);
169 1.1 christos assert_int_equal(isc_ascii_tolower8(ab << 40), abc << 40);
170 1.1 christos assert_int_equal(isc_ascii_tolower8(ab << 48), abc << 48);
171 1.1 christos }
172 1.1 christos }
173 1.1 christos
174 1.1 christos ISC_TEST_LIST_START
175 1.1 christos ISC_TEST_ENTRY(upperlower)
176 1.1 christos ISC_TEST_ENTRY(lowerequal)
177 1.1 christos ISC_TEST_ENTRY(lowercmp)
178 1.1 christos ISC_TEST_ENTRY(exhaustive)
179 1.1 christos ISC_TEST_LIST_END
180 1.1 christos
181 1.1 christos ISC_TEST_MAIN
182