Add self-test framework to gdb
authorTom Tromey <tom@tromey.com>
Wed, 20 Apr 2016 16:09:53 +0000 (10:09 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 17 May 2016 18:01:59 +0000 (12:01 -0600)
I wanted to unit test the Rust lexer, so I added a simple unit testing
command to gdb.

The intent is that self tests will only be compiled into gdb in
development mode.  In release mode they simply won't exist.  So, this
exposes $development to C code as GDB_SELF_TEST.

In development mode, test functions are registered with the self test
module.  A test function is just a function that does some checks, and
throws an exception on failure.

Then this adds a new "maint selftest" command which invokes the test
functions, and a new dejagnu test case that invokes it.

2016-05-17  Tom Tromey  <tom@tromey.com>

* NEWS: Add "maint selftest" entry.
* selftest.h: New file.
* selftest.c: New file.
* maint.c: Include selftest.h.
(maintenance_selftest): New function.
(_initialize_maint_cmds): Add "maint selftest" command.
* configure.ac (GDB_SELF_TEST): Maybe define.
* config.in, configure: Rebuild.
* Makefile.in (SFILES): Add selftest.c.
(COMMON_OBS): Add selftest.o.

2016-05-17  Tom Tromey  <tom@tromey.com>

* gdb.texinfo (Maintenance Commands): Document "maint selftest".

2016-05-17  Tom Tromey  <tom@tromey.com>

* gdb.gdb/unittest.exp: New file.

13 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/config.in
gdb/configure
gdb/configure.ac
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/maint.c
gdb/selftest.c [new file with mode: 0644]
gdb/selftest.h [new file with mode: 0644]
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.gdb/unittest.exp [new file with mode: 0644]

index 6bed450ebda53ecbafb2fba22f5d95734c7a279e..cad948f1a7398e8d075668728cceca2e933c9f27 100644 (file)
@@ -1,3 +1,16 @@
+2016-05-17  Tom Tromey  <tom@tromey.com>
+
+       * NEWS: Add "maint selftest" entry.
+       * selftest.h: New file.
+       * selftest.c: New file.
+       * maint.c: Include selftest.h.
+       (maintenance_selftest): New function.
+       (_initialize_maint_cmds): Add "maint selftest" command.
+       * configure.ac (GDB_SELF_TEST): Maybe define.
+       * config.in, configure: Rebuild.
+       * Makefile.in (SFILES): Add selftest.c.
+       (COMMON_OBS): Add selftest.o.
+
 2016-05-17  Tom Tromey  <tom@tromey.com>
 
        * expprint.c: Include f-lang.h.
index 400d2b0f916632c84a6696d043e04f9c56b7b9d1..c42b9aec294b8f9fe41e7945e530381359a948e9 100644 (file)
@@ -869,7 +869,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
        proc-service.list progspace.c \
        prologue-value.c psymtab.c \
        regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c reverse.c \
-       sentinel-frame.c \
+       selftest.c sentinel-frame.c \
        serial.c ser-base.c ser-unix.c ser-event.c skip.c \
        solib.c solib-target.c source.c \
        stabsread.c stack.c probe.c stap-probe.c std-regs.c \
@@ -1060,7 +1060,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
        go-lang.o go-valprint.o go-typeprint.o \
        jv-lang.o jv-valprint.o jv-typeprint.o jv-varobj.o \
        m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \
-       sentinel-frame.o \
+       selftest.o sentinel-frame.o \
        complaints.o typeprint.o \
        ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
        ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
index 7bf1e1acdef7d335a05d6326fbf498f7826a42d1..77dfc0cbb43c95d66dd6aaddeb82a01935ef7d6a 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -40,6 +40,9 @@ skip -rfunction regular-expression
 maint info line-table REGEXP
   Display the contents of GDB's internal line table data struture.
 
+maint selftest
+  Run any GDB unit tests that were compiled in.
+
 * Support for tracepoints and fast tracepoints on s390-linux and s390x-linux
   was added in GDBserver, including JIT compiling fast tracepoint's
   conditional expression bytecode into native code.
index dc9da0a7361059305f4ea8643e390c360703261b..905caf0b134281b22657411f4ab9892703a0fe98 100644 (file)
@@ -65,6 +65,9 @@
 /* Define to the default OS ABI for this configuration. */
 #undef GDB_OSABI_DEFAULT
 
+/* Define if self-testing features should be enabled */
+#undef GDB_SELF_TEST
+
 /* Define to 1 if you have `alloca', as a function or macro. */
 #undef HAVE_ALLOCA
 
index 7ade907b55800945ddbd8c4f1f8ce21da05b30d1..c9cd3ba7132900783f3b85ab9dc34e88839c47ef 100755 (executable)
@@ -16500,6 +16500,12 @@ ac_config_links="$ac_config_links $ac_config_links_1"
 $as_echo "#define GDB_DEFAULT_HOST_CHARSET \"UTF-8\"" >>confdefs.h
 
 
+if $development; then
+
+$as_echo "#define GDB_SELF_TEST 1" >>confdefs.h
+
+fi
+
 
   gdb_ac_transform=`echo "$program_transform_name" | sed -e 's/\\$\\$/\\$/g'`
   GDB_TRANSFORM_NAME=`echo gdb | sed -e "$gdb_ac_transform"`
index d1930f9ffc142cd8269d5fe0d4c18956871d4f9f..4364c025f9280ebbeddacf380f1ad45a46829fc9 100644 (file)
@@ -2348,6 +2348,11 @@ dnl  At the moment, we just assume it's UTF-8.
 AC_DEFINE(GDB_DEFAULT_HOST_CHARSET, "UTF-8",
           [Define to be a string naming the default host character set.])
 
+if $development; then
+  AC_DEFINE(GDB_SELF_TEST, 1,
+            [Define if self-testing features should be enabled])
+fi
+
 GDB_AC_TRANSFORM([gdb], [GDB_TRANSFORM_NAME])
 GDB_AC_TRANSFORM([gcore], [GCORE_TRANSFORM_NAME])
 AC_CONFIG_FILES([gcore], [chmod +x gcore])
index a6bd214707aeb547b0568a2d61bbb5b9cebf3bbf..2db9be20adf5637d822f485db530d080066ef9aa 100644 (file)
@@ -1,3 +1,7 @@
+2016-05-17  Tom Tromey  <tom@tromey.com>
+
+       * gdb.texinfo (Maintenance Commands): Document "maint selftest".
+
 2016-04-27  Yao Qi  <yao.qi@linaro.org>
 
        * gdb.texinfo (tfind): Complete doc about tfind without
index f74c41c1684f18cefd43b1c6a0c150c4201959ae..f91a609f8ead328f6fbc4eb64630e638515a361e 100644 (file)
@@ -34451,6 +34451,11 @@ that symbol is described.  The type chain produced by this command is
 a recursive definition of the data type as stored in @value{GDBN}'s
 data structures, including its flags and contained types.
 
+@kindex maint selftest
+@cindex self tests
+Run any self tests that were compiled in to @value{GDBN}.  This will
+print a message showing how many tests were run, and how many failed.
+
 @kindex maint set dwarf always-disassemble
 @kindex maint show dwarf always-disassemble
 @item maint set dwarf always-disassemble
index 5da1c11b50ab97fc67e929b258d5689a0926ea22..d2c9346b2ee43586f6e257c30d72573e2c79efd2 100644 (file)
@@ -41,6 +41,7 @@
 #include "top.h"
 #include "timeval-utils.h"
 #include "maint.h"
+#include "selftest.h"
 
 #include "cli/cli-decode.h"
 #include "cli/cli-utils.h"
@@ -980,6 +981,16 @@ show_per_command_cmd (char *args, int from_tty)
 {
   cmd_show_list (per_command_showlist, from_tty, "");
 }
+\f
+
+/* The "maintenance selftest" command.  */
+
+static void
+maintenance_selftest (char *args, int from_tty)
+{
+  run_self_tests ();
+}
+
 \f
 void
 _initialize_maint_cmds (void)
@@ -1153,6 +1164,13 @@ testsuite can check the command deprecator. You probably shouldn't use this,\n\
 If you decide you want to use it: maintenance undeprecate 'commandname'"),
           &maintenancelist);
 
+  add_cmd ("selftest", class_maintenance, maintenance_selftest, _("\
+Run gdb's unit tests.\n\
+Usage: maintenance selftest\n\
+This will run any unit tests that were built in to gdb.\n\
+gdb will abort if any test fails."),
+          &maintenancelist);
+
   add_setshow_zinteger_cmd ("watchdog", class_maintenance, &watchdog, _("\
 Set watchdog timer."), _("\
 Show watchdog timer."), _("\
diff --git a/gdb/selftest.c b/gdb/selftest.c
new file mode 100644 (file)
index 0000000..c63c06d
--- /dev/null
@@ -0,0 +1,67 @@
+/* GDB self-testing.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "selftest.h"
+#include "vec.h"
+
+typedef self_test_function *self_test_function_ptr;
+
+DEF_VEC_P (self_test_function_ptr);
+
+/* All the tests that have been registered.  */
+
+static VEC (self_test_function_ptr) *tests;
+
+/* See selftest.h.  */
+
+void
+register_self_test (self_test_function *function)
+{
+  VEC_safe_push (self_test_function_ptr, tests, function);
+}
+
+/* See selftest.h.  */
+
+void
+run_self_tests (void)
+{
+  int i;
+  self_test_function_ptr func;
+  int failed = 0;
+
+  for (i = 0; VEC_iterate (self_test_function_ptr, tests, i, func); ++i)
+    {
+      QUIT;
+
+      TRY
+       {
+         (*func) ();
+       }
+      CATCH (ex, RETURN_MASK_ERROR)
+       {
+         ++failed;
+         exception_fprintf (gdb_stderr, ex,
+                            _("Self test threw exception"));
+       }
+      END_CATCH
+    }
+
+  printf_filtered (_("Ran %u unit tests, %d failed\n"),
+                  VEC_length (self_test_function_ptr, tests), failed);
+}
diff --git a/gdb/selftest.h b/gdb/selftest.h
new file mode 100644 (file)
index 0000000..2b028dd
--- /dev/null
@@ -0,0 +1,44 @@
+/* GDB self-testing.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 <http://www.gnu.org/licenses/>.  */
+
+#ifndef SELFTEST_H
+#define SELFTEST_H
+
+/* A test is just a function that does some checks and throws an
+   exception if something has gone wrong.  */
+
+typedef void self_test_function (void);
+
+/* Register a new self-test.  */
+
+extern void register_self_test (self_test_function *function);
+
+/* Run all the self tests.  This print a message describing the number
+   of test and the number of failures.  */
+
+extern void run_self_tests (void);
+
+/* Check that VALUE is true, and, if not, throw an exception.  */
+
+#define SELF_CHECK(VALUE)                                              \
+  do {                                                                 \
+    if (!(VALUE))                                                      \
+      error (_("self-test failed at %s:%d"), __FILE__, __LINE__);      \
+  } while (0)
+
+#endif /* SELFTEST_H */
index c5ec75637c10e58c05225d9ee8955d133e50a85e..0e45f19b4170c519c99bda59325bb0309d482387 100644 (file)
@@ -1,3 +1,7 @@
+2016-05-17  Tom Tromey  <tom@tromey.com>
+
+       * gdb.gdb/unittest.exp: New file.
+
 2016-05-16  Yao Qi  <yao.qi@linaro.org>
 
        * gdb.base/batch-preserve-term-settings.exp: Remove variable
diff --git a/gdb/testsuite/gdb.gdb/unittest.exp b/gdb/testsuite/gdb.gdb/unittest.exp
new file mode 100644 (file)
index 0000000..88fd266
--- /dev/null
@@ -0,0 +1,17 @@
+# Copyright 2016 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 <http://www.gnu.org/licenses/>.
+
+gdb_start
+gdb_test "maintenance selftest" "Ran $decimal unit tests, 0 failed"