diff options
author | Bruno Haible <bruno@clisp.org> | 2021-01-10 01:15:01 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2021-01-10 01:26:19 +0100 |
commit | 14eeb8100475828af2641a7847586826be1f69d1 (patch) | |
tree | e8310cdfb2e8f43d8ffcd809cb5a1c672bac6c80 | |
parent | 9f87c80a00854651a0f62072d88302ade89abbbd (diff) | |
download | gnulib-14eeb8100475828af2641a7847586826be1f69d1.tar.gz |
immutable: Add tests.
* tests/test-immutable.sh: New file.
* tests/test-immutable.c: New file.
* modules/immutable-tests: New file.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | modules/immutable-tests | 15 | ||||
-rw-r--r-- | tests/test-immutable.c | 158 | ||||
-rw-r--r-- | tests/test-immutable.sh | 12 |
4 files changed, 190 insertions, 0 deletions
@@ -1,5 +1,10 @@ 2021-01-09 Bruno Haible <bruno@clisp.org> + immutable: Add tests. + * tests/test-immutable.sh: New file. + * tests/test-immutable.c: New file. + * modules/immutable-tests: New file. + immutable: New module. * lib/immutable.h: New file. * lib/immutable.c: New file. diff --git a/modules/immutable-tests b/modules/immutable-tests new file mode 100644 index 0000000000..3265fa6f89 --- /dev/null +++ b/modules/immutable-tests @@ -0,0 +1,15 @@ +Files: +tests/test-immutable.sh +tests/test-immutable.c +tests/macros.h + +Depends-on: +stdbool +_Exit + +configure.ac: + +Makefile.am: +TESTS += test-immutable.sh +check_PROGRAMS += test-immutable +test_immutable_LDADD = $(LDADD) $(LIBTHREAD) diff --git a/tests/test-immutable.c b/tests/test-immutable.c new file mode 100644 index 0000000000..4bee1f2b33 --- /dev/null +++ b/tests/test-immutable.c @@ -0,0 +1,158 @@ +/* Test of immutable data. + Copyright (C) 2021 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2021. */ + +#include <config.h> + +#include "immutable.h" + +#include <signal.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include "macros.h" + +struct data +{ + int x; + long y; +}; + +#if IMMUTABLE_EFFECTIVE + +static _GL_ASYNC_SAFE _Noreturn void +segv_handler (int signo) +{ + _Exit (0); +} + +static void +install_segv_handler (void) +{ + signal (SIGSEGV, segv_handler); +# if defined __APPLE__ && defined __MACH__ + signal (SIGBUS, segv_handler); +# endif +} + +#endif + +int +main (int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf (stderr, "%s: need 1 argument\n", argv[0]); + return 1; + } + int test = atoi (argv[1]); + switch (test) + { + case 0: + /* Indicates whether the implementation effectively rejects writes to + immutable data. */ + #if !IMMUTABLE_EFFECTIVE + fputs ("Skipping test: immutability cannot be enforced\n", stderr); + return 77; + #else + break; + #endif + + case 1: + /* Correct use of immmalloc. */ + { + struct data *wp; + struct data const *p; + + wp = (struct data *) immmalloc (sizeof (struct data)); + ASSERT (wp != NULL); + wp->x = 7; + wp->y = 42; + p = immfreeze (wp); + ASSERT (p->x == 7); + ASSERT (p->y == 42); + immfree (p); + } + break; + + case 2: + /* Catch invalid write access. */ + { + struct data *wp; + struct data const *p; + + wp = (struct data *) immmalloc (sizeof (struct data)); + ASSERT (wp != NULL); + wp->x = 7; + wp->y = 42; + p = immfreeze (wp); + #if IMMUTABLE_EFFECTIVE + install_segv_handler (); + #endif + /* This assignment should crash. */ + ((struct data *) p)->y = 77; + #if IMMUTABLE_EFFECTIVE + return 1; + #endif + } + break; + + case 3: + /* Catch invalid write access while another data object is not frozen. */ + { + struct data *wp; + struct data const *p; + struct data *wp2; + + wp = (struct data *) immmalloc (sizeof (struct data)); + ASSERT (wp != NULL); + wp->x = 7; + wp->y = 42; + p = immfreeze (wp); + ASSERT (p->x == 7); + ASSERT (p->y == 42); + + wp2 = (struct data *) immmalloc (sizeof (struct data)); + ASSERT (wp2 != NULL); + wp2->x = 7; + #if IMMUTABLE_EFFECTIVE + install_segv_handler (); + #endif + /* This assignment should crash. */ + ((struct data *) p)->y = 42; + #if IMMUTABLE_EFFECTIVE + return 1; + #endif + } + break; + + case 4: + /* Correct use of immstrdup. */ + { + const char *s = immstrdup ("Hello"); + ASSERT (strlen (s) == 5); + ASSERT (strcmp (s, "Hello") == 0); + immfree (s); + } + break; + + default: + ASSERT (false); + } + return 0; +} diff --git a/tests/test-immutable.sh b/tests/test-immutable.sh new file mode 100644 index 0000000000..5b8d8d0133 --- /dev/null +++ b/tests/test-immutable.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Print "Skipping test" if immutability cannot be enforced. +./test-immutable${EXEEXT} 0 +if test $? = 77; then exit 77; fi + +st=0 +for i in 1 2 3 4 ; do + ${CHECKER} ./test-immutable${EXEEXT} $i \ + || { echo test-immutable.sh: test case $i failed >&2; st=1; } +done +exit $st |