Home | History | Annotate | Line # | Download | only in isc
buffer_test.c revision 1.2.4.2
      1 /*	$NetBSD: buffer_test.c,v 1.2.4.2 2024/02/29 12:35:54 martin 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 <fcntl.h>
     17 #include <inttypes.h>
     18 #include <limits.h>
     19 #include <sched.h> /* IWYU pragma: keep */
     20 #include <setjmp.h>
     21 #include <stdarg.h>
     22 #include <stdbool.h>
     23 #include <stddef.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <unistd.h>
     27 
     28 #define UNIT_TESTING
     29 #include <cmocka.h>
     30 
     31 #include <isc/buffer.h>
     32 #include <isc/print.h>
     33 #include <isc/region.h>
     34 #include <isc/result.h>
     35 #include <isc/types.h>
     36 #include <isc/util.h>
     37 
     38 #include <tests/isc.h>
     39 
     40 /* reserve space in dynamic buffers */
     41 ISC_RUN_TEST_IMPL(isc_buffer_reserve) {
     42 	isc_result_t result;
     43 	isc_buffer_t *b;
     44 
     45 	UNUSED(state);
     46 
     47 	b = NULL;
     48 	isc_buffer_allocate(mctx, &b, 1024);
     49 	assert_int_equal(b->length, 1024);
     50 
     51 	/*
     52 	 * 1024 bytes should already be available, so this call does
     53 	 * nothing.
     54 	 */
     55 	result = isc_buffer_reserve(&b, 1024);
     56 	assert_int_equal(result, ISC_R_SUCCESS);
     57 	assert_true(ISC_BUFFER_VALID(b));
     58 	assert_non_null(b);
     59 	assert_int_equal(b->length, 1024);
     60 
     61 	/*
     62 	 * This call should grow it to 2048 bytes as only 1024 bytes are
     63 	 * available in the buffer.
     64 	 */
     65 	result = isc_buffer_reserve(&b, 1025);
     66 	assert_int_equal(result, ISC_R_SUCCESS);
     67 	assert_true(ISC_BUFFER_VALID(b));
     68 	assert_non_null(b);
     69 	assert_int_equal(b->length, 2048);
     70 
     71 	/*
     72 	 * 2048 bytes should already be available, so this call does
     73 	 * nothing.
     74 	 */
     75 	result = isc_buffer_reserve(&b, 2000);
     76 	assert_int_equal(result, ISC_R_SUCCESS);
     77 	assert_true(ISC_BUFFER_VALID(b));
     78 	assert_non_null(b);
     79 	assert_int_equal(b->length, 2048);
     80 
     81 	/*
     82 	 * This call should grow it to 4096 bytes as only 2048 bytes are
     83 	 * available in the buffer.
     84 	 */
     85 	result = isc_buffer_reserve(&b, 3000);
     86 	assert_int_equal(result, ISC_R_SUCCESS);
     87 	assert_true(ISC_BUFFER_VALID(b));
     88 	assert_non_null(b);
     89 	assert_int_equal(b->length, 4096);
     90 
     91 	/* Consume some of the buffer so we can run the next test. */
     92 	isc_buffer_add(b, 4096);
     93 
     94 	/*
     95 	 * This call should fail and leave buffer untouched.
     96 	 */
     97 	result = isc_buffer_reserve(&b, UINT_MAX);
     98 	assert_int_equal(result, ISC_R_NOMEMORY);
     99 	assert_true(ISC_BUFFER_VALID(b));
    100 	assert_non_null(b);
    101 	assert_int_equal(b->length, 4096);
    102 
    103 	isc_buffer_free(&b);
    104 }
    105 
    106 /* dynamic buffer automatic reallocation */
    107 ISC_RUN_TEST_IMPL(isc_buffer_dynamic) {
    108 	isc_buffer_t *b;
    109 	size_t last_length = 10;
    110 	int i;
    111 
    112 	UNUSED(state);
    113 
    114 	b = NULL;
    115 	isc_buffer_allocate(mctx, &b, last_length);
    116 	assert_non_null(b);
    117 	assert_int_equal(b->length, last_length);
    118 
    119 	isc_buffer_setautorealloc(b, true);
    120 
    121 	isc_buffer_putuint8(b, 1);
    122 
    123 	for (i = 0; i < 1000; i++) {
    124 		isc_buffer_putstr(b, "thisisa24charslongstring");
    125 	}
    126 	assert_true(b->length - last_length >= 1000 * 24);
    127 	last_length += 1000 * 24;
    128 
    129 	for (i = 0; i < 10000; i++) {
    130 		isc_buffer_putuint8(b, 1);
    131 	}
    132 
    133 	assert_true(b->length - last_length >= 10000 * 1);
    134 	last_length += 10000 * 1;
    135 
    136 	for (i = 0; i < 10000; i++) {
    137 		isc_buffer_putuint16(b, 1);
    138 	}
    139 
    140 	assert_true(b->length - last_length >= 10000 * 2);
    141 
    142 	last_length += 10000 * 2;
    143 	for (i = 0; i < 10000; i++) {
    144 		isc_buffer_putuint24(b, 1);
    145 	}
    146 	assert_true(b->length - last_length >= 10000 * 3);
    147 
    148 	last_length += 10000 * 3;
    149 
    150 	for (i = 0; i < 10000; i++) {
    151 		isc_buffer_putuint32(b, 1);
    152 	}
    153 	assert_true(b->length - last_length >= 10000 * 4);
    154 
    155 	isc_buffer_free(&b);
    156 }
    157 
    158 /* copy a region into a buffer */
    159 ISC_RUN_TEST_IMPL(isc_buffer_copyregion) {
    160 	unsigned char data[] = { 0x11, 0x22, 0x33, 0x44 };
    161 	isc_buffer_t *b = NULL;
    162 	isc_result_t result;
    163 
    164 	isc_region_t r = {
    165 		.base = data,
    166 		.length = sizeof(data),
    167 	};
    168 
    169 	UNUSED(state);
    170 
    171 	isc_buffer_allocate(mctx, &b, sizeof(data));
    172 
    173 	/*
    174 	 * Fill originally allocated buffer space.
    175 	 */
    176 	result = isc_buffer_copyregion(b, &r);
    177 	assert_int_equal(result, ISC_R_SUCCESS);
    178 
    179 	/*
    180 	 * Appending more data to the buffer should fail.
    181 	 */
    182 	result = isc_buffer_copyregion(b, &r);
    183 	assert_int_equal(result, ISC_R_NOSPACE);
    184 
    185 	/*
    186 	 * Enable auto reallocation and retry.  Appending should now succeed.
    187 	 */
    188 	isc_buffer_setautorealloc(b, true);
    189 	result = isc_buffer_copyregion(b, &r);
    190 	assert_int_equal(result, ISC_R_SUCCESS);
    191 
    192 	isc_buffer_free(&b);
    193 }
    194 
    195 /* sprintf() into a buffer */
    196 ISC_RUN_TEST_IMPL(isc_buffer_printf) {
    197 	unsigned int used, prev_used;
    198 	const char *empty_fmt;
    199 	isc_result_t result;
    200 	isc_buffer_t *b, sb;
    201 	char buf[8];
    202 
    203 	UNUSED(state);
    204 
    205 	/*
    206 	 * Prepare a buffer with auto-reallocation enabled.
    207 	 */
    208 	b = NULL;
    209 	isc_buffer_allocate(mctx, &b, 0);
    210 	isc_buffer_setautorealloc(b, true);
    211 
    212 	/*
    213 	 * Sanity check.
    214 	 */
    215 	result = isc_buffer_printf(b, "foo");
    216 	assert_int_equal(result, ISC_R_SUCCESS);
    217 	used = isc_buffer_usedlength(b);
    218 	assert_int_equal(used, 3);
    219 
    220 	result = isc_buffer_printf(b, "bar");
    221 	assert_int_equal(result, ISC_R_SUCCESS);
    222 	used = isc_buffer_usedlength(b);
    223 	assert_int_equal(used, 3 + 3);
    224 
    225 	/*
    226 	 * Also check the terminating NULL byte is there, even though it is not
    227 	 * part of the buffer's used region.
    228 	 */
    229 	assert_memory_equal(isc_buffer_current(b), "foobar", 7);
    230 
    231 	/*
    232 	 * Skip over data from previous check to prevent failures in previous
    233 	 * check from affecting this one.
    234 	 */
    235 	prev_used = used;
    236 	isc_buffer_forward(b, prev_used);
    237 
    238 	/*
    239 	 * Some standard usage checks.
    240 	 */
    241 	isc_buffer_printf(b, "%d", 42);
    242 	used = isc_buffer_usedlength(b);
    243 	assert_int_equal(used - prev_used, 2);
    244 
    245 	isc_buffer_printf(b, "baz%1X", 42);
    246 	used = isc_buffer_usedlength(b);
    247 	assert_int_equal(used - prev_used, 2 + 5);
    248 
    249 	isc_buffer_printf(b, "%6.1f", 42.42f);
    250 	used = isc_buffer_usedlength(b);
    251 	assert_int_equal(used - prev_used, 2 + 5 + 6);
    252 
    253 	/*
    254 	 * Also check the terminating NULL byte is there, even though it is not
    255 	 * part of the buffer's used region.
    256 	 */
    257 	assert_memory_equal(isc_buffer_current(b), "42baz2A  42.4", 14);
    258 
    259 	/*
    260 	 * Check an empty format string is properly handled.
    261 	 *
    262 	 * Note: we don't use a string literal for the format string to
    263 	 * avoid triggering [-Werror=format-zero-length].
    264 	 * Note: we have a dummy third argument as some compilers complain
    265 	 * without it.
    266 	 */
    267 	prev_used = used;
    268 	empty_fmt = "";
    269 	result = isc_buffer_printf(b, empty_fmt, "");
    270 	assert_int_equal(result, ISC_R_SUCCESS);
    271 	used = isc_buffer_usedlength(b);
    272 	assert_int_equal(prev_used, used);
    273 
    274 	isc_buffer_free(&b);
    275 
    276 	/*
    277 	 * Check overflow on a static buffer.
    278 	 */
    279 	isc_buffer_init(&sb, buf, sizeof(buf));
    280 	result = isc_buffer_printf(&sb, "123456");
    281 	assert_int_equal(result, ISC_R_SUCCESS);
    282 	used = isc_buffer_usedlength(&sb);
    283 	assert_int_equal(used, 6);
    284 
    285 	result = isc_buffer_printf(&sb, "789");
    286 	assert_int_equal(result, ISC_R_NOSPACE);
    287 	used = isc_buffer_usedlength(&sb);
    288 	assert_int_equal(used, 6);
    289 
    290 	result = isc_buffer_printf(&sb, "78");
    291 	assert_int_equal(result, ISC_R_NOSPACE);
    292 	used = isc_buffer_usedlength(&sb);
    293 	assert_int_equal(used, 6);
    294 
    295 	result = isc_buffer_printf(&sb, "7");
    296 	assert_int_equal(result, ISC_R_SUCCESS);
    297 	used = isc_buffer_usedlength(&sb);
    298 	assert_int_equal(used, 7);
    299 }
    300 
    301 ISC_TEST_LIST_START
    302 
    303 ISC_TEST_ENTRY(isc_buffer_reserve)
    304 ISC_TEST_ENTRY(isc_buffer_dynamic)
    305 ISC_TEST_ENTRY(isc_buffer_copyregion)
    306 ISC_TEST_ENTRY(isc_buffer_printf)
    307 
    308 ISC_TEST_LIST_END
    309 
    310 ISC_TEST_MAIN
    311