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