]> Savannah Git Hosting - gnulib.git/commitdiff
immutable: Add tests.
authorBruno Haible <bruno@clisp.org>
Sun, 10 Jan 2021 00:15:01 +0000 (01:15 +0100)
committerBruno Haible <bruno@clisp.org>
Sun, 10 Jan 2021 00:26:19 +0000 (01:26 +0100)
* tests/test-immutable.sh: New file.
* tests/test-immutable.c: New file.
* modules/immutable-tests: New file.

ChangeLog
modules/immutable-tests [new file with mode: 0644]
tests/test-immutable.c [new file with mode: 0644]
tests/test-immutable.sh [new file with mode: 0644]

index 8e89903fabf1f5c049184f03393913d043b5733b..bc2e033c8598000abdac877687202e8672410fca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 (file)
index 0000000..3265fa6
--- /dev/null
@@ -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 (file)
index 0000000..4bee1f2
--- /dev/null
@@ -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 (file)
index 0000000..5b8d8d0
--- /dev/null
@@ -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