diff options
Diffstat (limited to 'lib/libc/tests/sys/brk_test.c')
| -rw-r--r-- | lib/libc/tests/sys/brk_test.c | 146 | 
1 files changed, 146 insertions, 0 deletions
| diff --git a/lib/libc/tests/sys/brk_test.c b/lib/libc/tests/sys/brk_test.c new file mode 100644 index 000000000000..2d8c7af38ff7 --- /dev/null +++ b/lib/libc/tests/sys/brk_test.c @@ -0,0 +1,146 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018 Mark Johnston <markj@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/mman.h> + +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include <atf-c.h> + +ATF_TC(brk_basic); +ATF_TC_HEAD(brk_basic, tc) +{ +	atf_tc_set_md_var(tc, "descr", "Verify basic brk() functionality"); +} +ATF_TC_BODY(brk_basic, tc) +{ +	void *oldbrk, *newbrk; +	int error; + +	/* Reset the break. */ +	error = brk(0); +	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno)); + +	oldbrk = sbrk(0); +	ATF_REQUIRE(oldbrk != (void *)-1); + +	/* Try to allocate a page. */ +	error = brk((void *)((intptr_t)oldbrk + PAGE_SIZE * 2)); +	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno)); + +	/* +	 * Attempt to set the break below minbrk.  This should have no effect. +	 */ +	error = brk((void *)((intptr_t)oldbrk - 1)); +	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno)); +	newbrk = sbrk(0); +	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno)); +	ATF_REQUIRE(newbrk == oldbrk); +} + +ATF_TC(sbrk_basic); +ATF_TC_HEAD(sbrk_basic, tc) +{ +	atf_tc_set_md_var(tc, "descr", "Verify basic sbrk() functionality"); +} +ATF_TC_BODY(sbrk_basic, tc) +{ +	void *newbrk, *oldbrk; +	int *p; + +	oldbrk = sbrk(0); +	ATF_REQUIRE_MSG(oldbrk != (void *)-1, "sbrk: %s", strerror(errno)); +	p = sbrk(sizeof(*p)); +	*p = 0; +	ATF_REQUIRE(oldbrk == p); + +	newbrk = sbrk(-sizeof(*p)); +	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno)); +	ATF_REQUIRE(oldbrk == sbrk(0)); + +	oldbrk = sbrk(PAGE_SIZE * 2 + 1); +	ATF_REQUIRE_MSG(oldbrk != (void *)-1, "sbrk: %s", strerror(errno)); +	memset(oldbrk, 0, PAGE_SIZE * 2 + 1); +	newbrk = sbrk(-(PAGE_SIZE * 2 + 1)); +	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno)); +	ATF_REQUIRE(sbrk(0) == oldbrk); +} + +ATF_TC(mlockfuture); +ATF_TC_HEAD(mlockfuture, tc) +{ +	atf_tc_set_md_var(tc, "descr", +	    "Verify that mlockall(MCL_FUTURE) applies to the data segment"); +} +ATF_TC_BODY(mlockfuture, tc) +{ +	void *oldbrk, *n, *newbrk; +	int error; +	char v; + +	error = mlockall(MCL_FUTURE); +	ATF_REQUIRE_MSG(error == 0, +	    "mlockall: %s", strerror(errno)); + +	/* +	 * Advance the break so that at least one page is added to the data +	 * segment.  This page should be automatically faulted in to the address +	 * space. +	 */ +	oldbrk = sbrk(0); +	ATF_REQUIRE(oldbrk != (void *)-1); +	newbrk = sbrk(PAGE_SIZE * 2); +	ATF_REQUIRE(newbrk != (void *)-1); + +	n = (void *)(((uintptr_t)oldbrk + PAGE_SIZE) & ~PAGE_SIZE); +	v = 0; +	error = mincore(n, PAGE_SIZE, &v); +	ATF_REQUIRE_MSG(error == 0, +	    "mincore: %s", strerror(errno)); +	ATF_REQUIRE_MSG((v & MINCORE_INCORE) != 0, +	    "unexpected page flags %#x", v); + +	error = brk(oldbrk); +	ATF_REQUIRE(error == 0); + +	error = munlockall(); +	ATF_REQUIRE_MSG(error == 0, +	    "munlockall: %s", strerror(errno)); +} + +ATF_TP_ADD_TCS(tp) +{ +	ATF_TP_ADD_TC(tp, brk_basic); +	ATF_TP_ADD_TC(tp, sbrk_basic); +	ATF_TP_ADD_TC(tp, mlockfuture); + +	return (atf_no_error()); +} | 
