Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/tests/lib/libc/stdlib t_posix_memalign: Expand test cases an...



details:   https://anonhg.NetBSD.org/src/rev/280760d67bad
branches:  trunk
changeset: 377259:280760d67bad
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Tue Jul 04 15:06:36 2023 +0000

description:
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:

 tests/lib/libc/stdlib/Makefile           |    5 +-
 tests/lib/libc/stdlib/t_posix_memalign.c |  222 +++++++++++++++++++++++-------
 2 files changed, 173 insertions(+), 54 deletions(-)

diffs (294 lines):

diff -r 782c6735dab4 -r 280760d67bad tests/lib/libc/stdlib/Makefile
--- a/tests/lib/libc/stdlib/Makefile    Tue Jul 04 15:06:28 2023 +0000
+++ b/tests/lib/libc/stdlib/Makefile    Tue Jul 04 15:06:36 2023 +0000
@@ -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 -r 782c6735dab4 -r 280760d67bad tests/lib/libc/stdlib/t_posix_memalign.c
--- a/tests/lib/libc/stdlib/t_posix_memalign.c  Tue Jul 04 15:06:28 2023 +0000
+++ b/tests/lib/libc/stdlib/t_posix_memalign.c  Tue Jul 04 15:06:36 2023 +0000
@@ -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 @@
 #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;
 
-       size_t i;
-       void *p;
+       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]);
 
-       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] == 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;
+                       }
 
-               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);
+                       /*
+                        * 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.
+                                */
+                       }
+
                        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]);
 
-       size_t i;
-       void *p;
+                       /*
+                        * 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;
+                       }
 
-       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();
 }



Home | Main Index | Thread Index | Old Index