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