glibc/malloc/tst-alloc_buffer.c

666 lines
22 KiB
C
Raw Normal View History

/* Tests for struct alloc_buffer.
Copyright (C) 2017-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
Prefer https to http for gnu.org and fsf.org URLs Also, change sources.redhat.com to sourceware.org. This patch was automatically generated by running the following shell script, which uses GNU sed, and which avoids modifying files imported from upstream: sed -ri ' s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g ' \ $(find $(git ls-files) -prune -type f \ ! -name '*.po' \ ! -name 'ChangeLog*' \ ! -path COPYING ! -path COPYING.LIB \ ! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \ ! -path manual/texinfo.tex ! -path scripts/config.guess \ ! -path scripts/config.sub ! -path scripts/install-sh \ ! -path scripts/mkinstalldirs ! -path scripts/move-if-change \ ! -path INSTALL ! -path locale/programs/charmap-kw.h \ ! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \ ! '(' -name configure \ -execdir test -f configure.ac -o -f configure.in ';' ')' \ ! '(' -name preconfigure \ -execdir test -f preconfigure.ac ';' ')' \ -print) and then by running 'make dist-prepare' to regenerate files built from the altered files, and then executing the following to cleanup: chmod a+x sysdeps/unix/sysv/linux/riscv/configure # Omit irrelevant whitespace and comment-only changes, # perhaps from a slightly-different Autoconf version. git checkout -f \ sysdeps/csky/configure \ sysdeps/hppa/configure \ sysdeps/riscv/configure \ sysdeps/unix/sysv/linux/csky/configure # Omit changes that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines git checkout -f \ sysdeps/powerpc/powerpc64/ppc-mcount.S \ sysdeps/unix/sysv/linux/s390/s390-64/syscall.S # Omit change that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 13:40:42 +08:00
<https://www.gnu.org/licenses/>. */
#include <arpa/inet.h>
#include <alloc_buffer.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/support.h>
#include <support/test-driver.h>
/* Return true if PTR is sufficiently aligned for TYPE. */
#define IS_ALIGNED(ptr, type) \
((((uintptr_t) ptr) & (__alloc_buffer_assert_align (__alignof (type)) - 1)) \
== 0)
/* Structure with non-power-of-two size. */
struct twelve
{
uint32_t buffer[3] __attribute__ ((aligned (4)));
};
_Static_assert (sizeof (struct twelve) == 12, "struct twelve");
_Static_assert (__alignof__ (struct twelve) == 4, "struct twelve");
/* Check for success obtaining empty arrays. Does not assume the
buffer is empty. */
static void
test_empty_array (struct alloc_buffer refbuf)
{
bool refbuf_failed = alloc_buffer_has_failed (&refbuf);
if (test_verbose)
printf ("info: %s: current=0x%llx end=0x%llx refbuf_failed=%d\n",
__func__, (unsigned long long) refbuf.__alloc_buffer_current,
(unsigned long long) refbuf.__alloc_buffer_end, refbuf_failed);
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY ((alloc_buffer_alloc_bytes (&buf, 0) == NULL)
== refbuf_failed);
TEST_VERIFY (alloc_buffer_has_failed (&buf) == refbuf_failed);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY ((alloc_buffer_alloc_array (&buf, char, 0) == NULL)
== refbuf_failed);
TEST_VERIFY (alloc_buffer_has_failed (&buf) == refbuf_failed);
}
/* The following tests can fail due to the need for aligning the
returned pointer. */
{
struct alloc_buffer buf = refbuf;
bool expect_failure = refbuf_failed
|| !IS_ALIGNED (alloc_buffer_next (&buf, void), double);
double *ptr = alloc_buffer_alloc_array (&buf, double, 0);
TEST_VERIFY (IS_ALIGNED (ptr, double));
TEST_VERIFY ((ptr == NULL) == expect_failure);
TEST_VERIFY (alloc_buffer_has_failed (&buf) == expect_failure);
}
{
struct alloc_buffer buf = refbuf;
bool expect_failure = refbuf_failed
|| !IS_ALIGNED (alloc_buffer_next (&buf, void), struct twelve);
struct twelve *ptr = alloc_buffer_alloc_array (&buf, struct twelve, 0);
TEST_VERIFY (IS_ALIGNED (ptr, struct twelve));
TEST_VERIFY ((ptr == NULL) == expect_failure);
TEST_VERIFY (alloc_buffer_has_failed (&buf) == expect_failure);
}
}
/* Test allocation of impossibly large arrays. */
static void
test_impossible_array (struct alloc_buffer refbuf)
{
if (test_verbose)
printf ("info: %s: current=0x%llx end=0x%llx\n",
__func__, (unsigned long long) refbuf.__alloc_buffer_current,
(unsigned long long) refbuf.__alloc_buffer_end);
static const size_t counts[] =
{ SIZE_MAX, SIZE_MAX - 1, SIZE_MAX - 2, SIZE_MAX - 3, SIZE_MAX - 4,
SIZE_MAX / 2, SIZE_MAX / 2 + 1, SIZE_MAX / 2 - 1, 0};
for (int i = 0; counts[i] != 0; ++i)
{
size_t count = counts[i];
if (test_verbose)
printf ("info: %s: count=%zu\n", __func__, count);
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_bytes (&buf, count) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, char, count) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, short, count) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, double, count) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, struct twelve, count)
== NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
}
}
/* Check for failure to obtain anything from a failed buffer. */
static void
test_after_failure (struct alloc_buffer refbuf)
{
if (test_verbose)
printf ("info: %s: current=0x%llx end=0x%llx\n",
__func__, (unsigned long long) refbuf.__alloc_buffer_current,
(unsigned long long) refbuf.__alloc_buffer_end);
TEST_VERIFY (alloc_buffer_has_failed (&refbuf));
{
struct alloc_buffer buf = refbuf;
alloc_buffer_add_byte (&buf, 17);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, char) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, double) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, struct twelve) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
test_impossible_array (refbuf);
for (int count = 0; count <= 4; ++count)
{
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_bytes (&buf, count) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, char, count) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, double, count) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, struct twelve, count)
== NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
}
}
static void
test_empty (struct alloc_buffer refbuf)
{
TEST_VERIFY (alloc_buffer_size (&refbuf) == 0);
if (alloc_buffer_next (&refbuf, void) != NULL)
TEST_VERIFY (!alloc_buffer_has_failed (&refbuf));
test_empty_array (refbuf);
test_impossible_array (refbuf);
/* Failure to obtain non-empty objects. */
{
struct alloc_buffer buf = refbuf;
alloc_buffer_add_byte (&buf, 17);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, char) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, double) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, struct twelve) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, char, 1) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, double, 1) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, struct twelve, 1) == NULL);
test_after_failure (buf);
}
}
static void
test_size_1 (struct alloc_buffer refbuf)
{
TEST_VERIFY (!alloc_buffer_has_failed (&refbuf));
TEST_VERIFY (alloc_buffer_size (&refbuf) == 1);
test_empty_array (refbuf);
test_impossible_array (refbuf);
/* Success adding a single byte. */
{
struct alloc_buffer buf = refbuf;
alloc_buffer_add_byte (&buf, 17);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
test_empty (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "\x11", 1) == 0);
{
struct alloc_buffer buf = refbuf;
signed char *ptr = alloc_buffer_alloc (&buf, signed char);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
*ptr = 126;
test_empty (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "\176", 1) == 0);
{
struct alloc_buffer buf = refbuf;
char *ptr = alloc_buffer_alloc_array (&buf, char, 1);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
*ptr = (char) 253;
test_empty (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "\xfd", 1) == 0);
/* Failure with larger objects. */
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, short) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, double) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, struct twelve) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, short, 1) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, double, 1) == NULL);
test_after_failure (buf);
}
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, struct twelve, 1) == NULL);
test_after_failure (buf);
}
}
static void
test_size_2 (struct alloc_buffer refbuf)
{
TEST_VERIFY (!alloc_buffer_has_failed (&refbuf));
TEST_VERIFY (alloc_buffer_size (&refbuf) == 2);
TEST_VERIFY (IS_ALIGNED (alloc_buffer_next (&refbuf, void), short));
test_empty_array (refbuf);
test_impossible_array (refbuf);
/* Success adding two bytes. */
{
struct alloc_buffer buf = refbuf;
alloc_buffer_add_byte (&buf, '@');
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
test_size_1 (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "@\xfd", 2) == 0);
{
struct alloc_buffer buf = refbuf;
signed char *ptr = alloc_buffer_alloc (&buf, signed char);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
*ptr = 'A';
test_size_1 (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "A\xfd", 2) == 0);
{
struct alloc_buffer buf = refbuf;
char *ptr = alloc_buffer_alloc_array (&buf, char, 1);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
*ptr = 'B';
test_size_1 (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "B\xfd", 2) == 0);
{
struct alloc_buffer buf = refbuf;
unsigned short *ptr = alloc_buffer_alloc (&buf, unsigned short);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (IS_ALIGNED (ptr, unsigned short));
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
*ptr = htons (0x12f4);
test_empty (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "\x12\xf4", 2) == 0);
{
struct alloc_buffer buf = refbuf;
unsigned short *ptr = alloc_buffer_alloc_array (&buf, unsigned short, 1);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (IS_ALIGNED (ptr, unsigned short));
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
*ptr = htons (0x13f5);
test_empty (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "\x13\xf5", 2) == 0);
{
struct alloc_buffer buf = refbuf;
char *ptr = alloc_buffer_alloc_array (&buf, char, 2);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
memcpy (ptr, "12", 2);
test_empty (buf);
}
TEST_VERIFY (memcmp (alloc_buffer_next (&refbuf, void), "12", 2) == 0);
}
static void
test_misaligned (char pad)
{
enum { SIZE = 23 };
char *backing = xmalloc (SIZE + 2);
backing[0] = ~pad;
backing[SIZE + 1] = pad;
struct alloc_buffer refbuf = alloc_buffer_create (backing + 1, SIZE);
{
struct alloc_buffer buf = refbuf;
short *ptr = alloc_buffer_alloc_array (&buf, short, SIZE / sizeof (short));
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (IS_ALIGNED (ptr, short));
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
for (int i = 0; i < SIZE / sizeof (short); ++i)
ptr[i] = htons (0xff01 + i);
TEST_VERIFY (memcmp (ptr,
"\xff\x01\xff\x02\xff\x03\xff\x04"
"\xff\x05\xff\x06\xff\x07\xff\x08"
"\xff\x09\xff\x0a\xff\x0b", 22) == 0);
}
{
struct alloc_buffer buf = refbuf;
uint32_t *ptr = alloc_buffer_alloc_array
(&buf, uint32_t, SIZE / sizeof (uint32_t));
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (IS_ALIGNED (ptr, uint32_t));
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
for (int i = 0; i < SIZE / sizeof (uint32_t); ++i)
ptr[i] = htonl (0xf1e2d301 + i);
TEST_VERIFY (memcmp (ptr,
"\xf1\xe2\xd3\x01\xf1\xe2\xd3\x02"
"\xf1\xe2\xd3\x03\xf1\xe2\xd3\x04"
"\xf1\xe2\xd3\x05", 20) == 0);
}
{
struct alloc_buffer buf = refbuf;
struct twelve *ptr = alloc_buffer_alloc (&buf, struct twelve);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (IS_ALIGNED (ptr, struct twelve));
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
ptr->buffer[0] = htonl (0x11223344);
ptr->buffer[1] = htonl (0x55667788);
ptr->buffer[2] = htonl (0x99aabbcc);
TEST_VERIFY (memcmp (ptr,
"\x11\x22\x33\x44"
"\x55\x66\x77\x88"
"\x99\xaa\xbb\xcc", 12) == 0);
}
{
static const double nums[] = { 1, 2 };
struct alloc_buffer buf = refbuf;
double *ptr = alloc_buffer_alloc_array (&buf, double, 2);
TEST_VERIFY_EXIT (ptr != NULL);
TEST_VERIFY (IS_ALIGNED (ptr, double));
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
ptr[0] = nums[0];
ptr[1] = nums[1];
TEST_VERIFY (memcmp (ptr, nums, sizeof (nums)) == 0);
}
/* Verify that padding was not overwritten. */
TEST_VERIFY (backing[0] == (char) ~pad);
TEST_VERIFY (backing[SIZE + 1] == pad);
free (backing);
}
/* Check that overflow during alignment is handled properly. */
static void
test_large_misaligned (void)
{
uintptr_t minus1 = -1;
uintptr_t start = minus1 & ~0xfe;
struct alloc_buffer refbuf = alloc_buffer_create ((void *) start, 16);
TEST_VERIFY (!alloc_buffer_has_failed (&refbuf));
struct __attribute__ ((aligned (256))) align256
{
int dymmy;
};
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc (&buf, struct align256) == NULL);
test_after_failure (buf);
}
for (int count = 0; count < 3; ++count)
{
struct alloc_buffer buf = refbuf;
TEST_VERIFY (alloc_buffer_alloc_array (&buf, struct align256, count)
== NULL);
test_after_failure (buf);
}
}
/* Check behavior of large allocations. */
static void
test_large (void)
{
{
/* Allocation which wraps around. */
struct alloc_buffer buf = { 1, SIZE_MAX };
TEST_VERIFY (alloc_buffer_alloc_array (&buf, char, SIZE_MAX) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
/* Successful very large allocation. */
struct alloc_buffer buf = { 1, SIZE_MAX };
uintptr_t val = (uintptr_t) alloc_buffer_alloc_array
(&buf, char, SIZE_MAX - 1);
TEST_VERIFY (val == 1);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
test_empty (buf);
}
{
typedef char __attribute__ ((aligned (2))) char2;
/* Overflow in array size computation. */
struct alloc_buffer buf = { 1, SIZE_MAX };
TEST_VERIFY (alloc_buffer_alloc_array (&buf, char2, SIZE_MAX - 1) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
/* Successful allocation after alignment. */
buf = (struct alloc_buffer) { 1, SIZE_MAX };
uintptr_t val = (uintptr_t) alloc_buffer_alloc_array
(&buf, char2, SIZE_MAX - 2);
TEST_VERIFY (val == 2);
test_empty (buf);
/* Alignment behavior near the top of the address space. */
buf = (struct alloc_buffer) { SIZE_MAX, SIZE_MAX };
TEST_VERIFY (alloc_buffer_next (&buf, char2) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
buf = (struct alloc_buffer) { SIZE_MAX, SIZE_MAX };
TEST_VERIFY (alloc_buffer_alloc_array (&buf, char2, 0) == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
}
{
typedef short __attribute__ ((aligned (2))) short2;
/* Test overflow in size computation. */
struct alloc_buffer buf = { 1, SIZE_MAX };
TEST_VERIFY (alloc_buffer_alloc_array (&buf, short2, SIZE_MAX / 2)
== NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
/* A slightly smaller array fits within the allocation. */
buf = (struct alloc_buffer) { 2, SIZE_MAX - 1 };
uintptr_t val = (uintptr_t) alloc_buffer_alloc_array
(&buf, short2, SIZE_MAX / 2 - 1);
TEST_VERIFY (val == 2);
test_empty (buf);
}
}
static void
test_copy_bytes (void)
{
char backing[4];
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
alloc_buffer_copy_bytes (&buf, "1", 1);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
TEST_VERIFY (alloc_buffer_size (&buf) == 3);
TEST_VERIFY (memcmp (backing, "1@@@", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
alloc_buffer_copy_bytes (&buf, "12", 3);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
TEST_VERIFY (alloc_buffer_size (&buf) == 1);
TEST_VERIFY (memcmp (backing, "12\0@", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
alloc_buffer_copy_bytes (&buf, "1234", 4);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
TEST_VERIFY (alloc_buffer_size (&buf) == 0);
TEST_VERIFY (memcmp (backing, "1234", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
alloc_buffer_copy_bytes (&buf, "1234", 5);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
TEST_VERIFY (memcmp (backing, "@@@@", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
alloc_buffer_copy_bytes (&buf, "1234", -1);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
TEST_VERIFY (memcmp (backing, "@@@@", 4) == 0);
}
}
static void
test_copy_string (void)
{
char backing[4];
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
const char *p = alloc_buffer_copy_string (&buf, "");
TEST_VERIFY (p == backing);
TEST_VERIFY (strcmp (p, "") == 0);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
TEST_VERIFY (alloc_buffer_size (&buf) == 3);
TEST_VERIFY (memcmp (backing, "\0@@@", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
const char *p = alloc_buffer_copy_string (&buf, "1");
TEST_VERIFY (p == backing);
TEST_VERIFY (strcmp (p, "1") == 0);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
TEST_VERIFY (alloc_buffer_size (&buf) == 2);
TEST_VERIFY (memcmp (backing, "1\0@@", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
const char *p = alloc_buffer_copy_string (&buf, "12");
TEST_VERIFY (p == backing);
TEST_VERIFY (strcmp (p, "12") == 0);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
TEST_VERIFY (alloc_buffer_size (&buf) == 1);
TEST_VERIFY (memcmp (backing, "12\0@", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
const char *p = alloc_buffer_copy_string (&buf, "123");
TEST_VERIFY (p == backing);
TEST_VERIFY (strcmp (p, "123") == 0);
TEST_VERIFY (!alloc_buffer_has_failed (&buf));
TEST_VERIFY (alloc_buffer_size (&buf) == 0);
TEST_VERIFY (memcmp (backing, "123", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
TEST_VERIFY (alloc_buffer_copy_string (&buf, "1234") == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
TEST_VERIFY (memcmp (backing, "@@@@", 4) == 0);
}
{
memset (backing, '@', sizeof (backing));
struct alloc_buffer buf = alloc_buffer_create (backing, sizeof (backing));
TEST_VERIFY (alloc_buffer_copy_string (&buf, "12345") == NULL);
TEST_VERIFY (alloc_buffer_has_failed (&buf));
TEST_VERIFY (memcmp (backing, "@@@@", 4) == 0);
}
}
static int
do_test (void)
{
test_empty (alloc_buffer_create (NULL, 0));
test_empty (alloc_buffer_create ((char *) "", 0));
test_empty (alloc_buffer_create ((void *) 1, 0));
{
void *ptr = (void *) ""; /* Cannot be freed. */
struct alloc_buffer buf = alloc_buffer_allocate (1, &ptr);
test_size_1 (buf);
free (ptr); /* Should have been overwritten. */
}
{
void *ptr= (void *) ""; /* Cannot be freed. */
struct alloc_buffer buf = alloc_buffer_allocate (2, &ptr);
test_size_2 (buf);
free (ptr); /* Should have been overwritten. */
}
test_misaligned (0);
test_misaligned (0xc7);
test_misaligned (0xff);
test_large_misaligned ();
test_large ();
test_copy_bytes ();
test_copy_string ();
return 0;
}
#include <support/test-driver.c>