>From 50a1c8361c20909aab8fc1ced6e84986812594e9 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 10 Jan 2021 01:15:01 +0100 Subject: [PATCH 2/2] immutable: Add tests. * tests/test-immutable.sh: New file. * tests/test-immutable.c: New file. * modules/immutable-tests: New file. --- ChangeLog | 5 ++ modules/immutable-tests | 15 +++++ tests/test-immutable.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/test-immutable.sh | 12 ++++ 4 files changed, 190 insertions(+) create mode 100644 modules/immutable-tests create mode 100644 tests/test-immutable.c create mode 100644 tests/test-immutable.sh diff --git a/ChangeLog b/ChangeLog index d319a98..e70dac6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2021-01-09 Bruno Haible + 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 0000000..3265fa6 --- /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 0000000..4bee1f2 --- /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 . */ + +/* Written by Bruno Haible , 2021. */ + +#include + +#include "immutable.h" + +#include +#include +#include +#include + +#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 0000000..5b8d8d0 --- /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 -- 2.7.4