Home | History | Annotate | Line # | Download | only in isc
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