summaryrefslogtreecommitdiff
path: root/tests/lib
diff options
context:
space:
mode:
authorriastradh <riastradh@NetBSD.org>2023-07-04 15:06:36 +0000
committerriastradh <riastradh@NetBSD.org>2023-07-04 15:06:36 +0000
commit53c5a21bc488abf07268f188acb1ca2d7659cec7 (patch)
treec6f3a040734bfbe10f2091f0e594e7e7c77f924d /tests/lib
parentf9baae5e2b34873478cf545917ec3fa4978cf1cb (diff)
t_posix_memalign: Expand test cases and properties.
- Test cartesian product of a sampling of sizes and a sampling of alignments. - Verify all the edge cases I could find in posix_memalign and aligned_alloc, including failure modes. - Test an unreasonably large (but aligned) allocation size. - Use ATF_CHECK_* instead of ATF_REQUIRE_* so all failures will be reported, not just the first one. - While here, build with -fno-builtin-aligned_alloc and with -fno-builtin-posix_memalign to make sure the compiler doesn't try any shenanigans. XXX pullup-10
Diffstat (limited to 'tests/lib')
-rw-r--r--tests/lib/libc/stdlib/Makefile5
-rw-r--r--tests/lib/libc/stdlib/t_posix_memalign.c228
2 files changed, 176 insertions, 57 deletions
diff --git a/tests/lib/libc/stdlib/Makefile b/tests/lib/libc/stdlib/Makefile
index 13eaf97cc10..a7221b5033f 100644
--- a/tests/lib/libc/stdlib/Makefile
+++ b/tests/lib/libc/stdlib/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.33 2020/07/01 07:16:37 jruoho Exp $
+# $NetBSD: Makefile,v 1.34 2023/07/04 15:06:36 riastradh Exp $
.include <bsd.own.mk>
@@ -31,6 +31,9 @@ BINDIR= ${TESTSDIR}
PROGS+= h_atexit
PROGS+= h_getopt h_getopt_long
+CFLAGS.t_posix_memalign.c+= -fno-builtin-posix_memalign
+CFLAGS.t_posix_memalign.c+= -fno-builtin-aligned_alloc
+
CPPFLAGS.t_strtod.c+= -D__TEST_FENV
LDADD.t_strtod= -lm
DPADD.t_strtod+= ${LIBM}
diff --git a/tests/lib/libc/stdlib/t_posix_memalign.c b/tests/lib/libc/stdlib/t_posix_memalign.c
index eaf5b6d8d01..bd2af6f55ff 100644
--- a/tests/lib/libc/stdlib/t_posix_memalign.c
+++ b/tests/lib/libc/stdlib/t_posix_memalign.c
@@ -1,4 +1,4 @@
-/* $NetBSD: t_posix_memalign.c,v 1.5 2018/07/29 01:45:25 maya Exp $ */
+/* $NetBSD: t_posix_memalign.c,v 1.6 2023/07/04 15:06:36 riastradh Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
__COPYRIGHT("@(#) Copyright (c) 2008\
The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_posix_memalign.c,v 1.5 2018/07/29 01:45:25 maya Exp $");
+__RCSID("$NetBSD: t_posix_memalign.c,v 1.6 2023/07/04 15:06:36 riastradh Exp $");
#include <atf-c.h>
@@ -43,6 +43,8 @@ __RCSID("$NetBSD: t_posix_memalign.c,v 1.5 2018/07/29 01:45:25 maya Exp $");
#include <stdlib.h>
#include <string.h>
+#define rounddown(x, n) (((x) / (n)) * (n))
+
ATF_TC(posix_memalign_basic);
ATF_TC_HEAD(posix_memalign_basic, tc)
{
@@ -50,32 +52,77 @@ ATF_TC_HEAD(posix_memalign_basic, tc)
}
ATF_TC_BODY(posix_memalign_basic, tc)
{
- static const size_t size[] = {
- 1, 2, 3, 4, 10, 100, 16384, 32768, 65536
- };
+ enum { maxaligntest = 16384 };
static const size_t align[] = {
- 512, 1024, 16, 32, 64, 4, 2048, 16, 2
+ 0, 1, 2, 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096,
+ 8192, maxaligntest,
};
+ static const size_t size[] = {
+ 0, 1, 2, 3, 4, 10, 100, 10000, 16384, 32768, 65536,
+ rounddown(SIZE_MAX, maxaligntest),
+ };
+ size_t i, j;
+
+ for (i = 0; i < __arraycount(align); i++) {
+ for (j = 0; j < __arraycount(size); j++) {
+ void *p = (void *)0x1;
+ const int ret = posix_memalign(&p, align[i], size[j]);
+
+ if (align[i] == 0 ||
+ (align[i] & (align[i] - 1)) != 0 ||
+ align[i] < sizeof(void *)) {
+ ATF_CHECK_EQ_MSG(ret, EINVAL,
+ "posix_memalign(&p, %zu, %zu): %s",
+ align[i], size[j], strerror(ret));
+ continue;
+ }
+ if (size[j] == rounddown(SIZE_MAX, maxaligntest) &&
+ ret != EINVAL) {
+ /*
+ * If obscenely large alignment isn't
+ * rejected as EINVAL, we can't
+ * allocate that much memory anyway.
+ */
+ ATF_CHECK_EQ_MSG(ret, ENOMEM,
+ "posix_memalign(&p, %zu, %zu): %s",
+ align[i], size[j], strerror(ret));
+ continue;
+ }
+
+ /*
+ * Allocation should fail only if the alignment
+ * isn't supported, in which case it will fail
+ * with EINVAL. No standard criterion for what
+ * alignments are supported, so just stop here
+ * on EINVAL.
+ */
+ if (ret == EINVAL)
+ continue;
+
+ ATF_CHECK_EQ_MSG(ret, 0,
+ "posix_memalign(&p, %zu, %zu): %s",
+ align[i], size[j], strerror(ret));
+ ATF_CHECK_EQ_MSG((intptr_t)p & (align[i] - 1), 0,
+ "posix_memalign(&p, %zu, %zu): %p",
+ align[i], size[j], p);
+
+ if (size[j] != 0) {
+ if (p == NULL) {
+ atf_tc_fail_nonfatal(
+ "%s:%d:"
+ "posix_memalign(&p, %zu, %zu):"
+ " %p",
+ __FILE__, __LINE__,
+ align[i], size[j], p);
+ }
+ } else {
+ /*
+ * No guarantees about whether
+ * zero-size allocation yields null
+ * pointer or something else.
+ */
+ }
- size_t i;
- void *p;
-
- for (i = 0; i < __arraycount(size); i++) {
- int ret;
- p = (void*)0x1;
-
- (void)printf("Checking posix_memalign(&p, %zu, %zu)...\n",
- align[i], size[i]);
- ret = posix_memalign(&p, align[i], size[i]);
-
- if ( align[i] < sizeof(void *))
- ATF_REQUIRE_EQ_MSG(ret, EINVAL,
- "posix_memalign: %s", strerror(ret));
- else {
- ATF_REQUIRE_EQ_MSG(ret, 0,
- "posix_memalign: %s", strerror(ret));
- ATF_REQUIRE_EQ_MSG(((intptr_t)p) & (align[i] - 1), 0,
- "p = %p", p);
free(p);
}
}
@@ -89,40 +136,108 @@ ATF_TC_HEAD(aligned_alloc_basic, tc)
}
ATF_TC_BODY(aligned_alloc_basic, tc)
{
- static const size_t size[] = {
- 1, 2, 3, 4, 10, 100, 16384, 32768, 65536, 10000, 0
- };
+ enum { maxaligntest = 16384 };
static const size_t align[] = {
- 512, 1024, 16, 32, 64, 4, 2048, 16, 2, 2048, 0
+ 0, 1, 2, 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096,
+ 8192, maxaligntest,
+ };
+ static const size_t size[] = {
+ 0, 1, 2, 3, 4, 10, 100, 10000, 16384, 32768, 65536,
+ rounddown(SIZE_MAX, maxaligntest),
};
+ size_t i, j;
+
+ for (i = 0; i < __arraycount(align); i++) {
+ for (j = 0; j < __arraycount(size); j++) {
+ void *const p = aligned_alloc(align[i], size[j]);
+
+ /*
+ * C11, 6.2.8 Alignment of objects, paragraph
+ * 4, p. 48:
+ *
+ * Every valid alignment value shall be a
+ * nonnegative integral power of two.
+ *
+ * C11, 7.22.3.1 The aligned_alloc function,
+ * paragraph 2, p. 348:
+ *
+ * The value of alignment shall be a valid
+ * alignment supported by the
+ * implementation and the value of size
+ * shall be an integral multiple of
+ * alignment.
+ *
+ * Setting errno to EINVAL is a NetBSD
+ * extension. The last clause appears to rule
+ * out aligned_alloc(n, 0) for any n, but it's
+ * not clear.
+ */
+ if (align[i] == 0 ||
+ (align[i] & (align[i] - 1)) != 0 ||
+ (size[j] != 0 && size[j] % align[i] != 0)) {
+ if (p != NULL) {
+ ATF_CHECK_EQ_MSG(p, NULL,
+ "aligned_alloc(%zu, %zu): %p",
+ align[i], size[j], p);
+ continue;
+ }
+ ATF_CHECK_EQ_MSG(errno, EINVAL,
+ "aligned_alloc(%zu, %zu): %s",
+ align[i], size[j], strerror(errno));
+ continue;
+ }
- size_t i;
- void *p;
-
- for (i = 0; i < __arraycount(size); i++) {
- (void)printf("Checking aligned_alloc(%zu, %zu)...\n",
- align[i], size[i]);
- p = aligned_alloc(align[i], size[i]);
- if (p == NULL) {
- if (align[i] == 0 || ((align[i] - 1) & align[i]) != 0 ||
- size[i] % align[i] != 0) {
- ATF_REQUIRE_EQ_MSG(errno, EINVAL,
- "aligned_alloc: %s", strerror(errno));
+ if (size[j] == rounddown(SIZE_MAX, maxaligntest)) {
+ ATF_CHECK_EQ_MSG(p, NULL,
+ "aligned_alloc(%zu, %zu): %p, %s",
+ align[i], size[j], p, strerror(errno));
+ switch (errno) {
+ case EINVAL:
+ case ENOMEM:
+ break;
+ default:
+ atf_tc_fail_nonfatal(
+ "%s:%d:"
+ " aligned_alloc(%zu, %zu): %s",
+ __FILE__, __LINE__,
+ align[i], size[j],
+ strerror(errno));
+ break;
+ }
+ continue;
}
- else {
- ATF_REQUIRE_EQ_MSG(errno, ENOMEM,
- "aligned_alloc: %s", strerror(errno));
+
+ /*
+ * Allocation should fail only if the alignment
+ * isn't supported, in which case it will fail
+ * with EINVAL. No standard criterion for what
+ * alignments are supported, so just stop here
+ * on EINVAL.
+ */
+ if (p == NULL && errno == EINVAL)
+ continue;
+
+ ATF_CHECK_EQ_MSG((intptr_t)p & (align[i] - 1), 0,
+ "aligned_alloc(%zu, %zu): %p",
+ align[i], size[j], p);
+ if (size[j] != 0) {
+ if (p == NULL) {
+ atf_tc_fail_nonfatal(
+ "%s:%d:"
+ " aligned_alloc(&p, %zu, %zu):"
+ " %p, %s",
+ __FILE__, __LINE__,
+ align[i], size[j], p,
+ strerror(errno));
+ }
+ } else {
+ /*
+ * No guarantees about whether
+ * zero-size allocation yields null
+ * pointer or something else.
+ */
}
- }
- else {
- ATF_REQUIRE_EQ_MSG(align[i] == 0, false,
- "aligned_alloc: success when alignment was not "
- "a power of 2");
- ATF_REQUIRE_EQ_MSG((align[i] - 1) & align[i], 0,
- "aligned_alloc: success when alignment was not "
- "a power of 2");
- ATF_REQUIRE_EQ_MSG(((intptr_t)p) & (align[i] - 1), 0,
- "p = %p", p);
+
free(p);
}
}
@@ -131,8 +246,9 @@ ATF_TC_BODY(aligned_alloc_basic, tc)
ATF_TP_ADD_TCS(tp)
{
+
ATF_TP_ADD_TC(tp, posix_memalign_basic);
- ATF_TP_ADD_TC(tp, aligned_alloc_basic);
-
+ ATF_TP_ADD_TC(tp, aligned_alloc_basic);
+
return atf_no_error();
}