gdb: allow specifying multiple filters when running selftests
authorSimon Marchi <simon.marchi@polymtl.ca>
Thu, 13 Aug 2020 11:55:48 +0000 (07:55 -0400)
committerSimon Marchi <simon.marchi@polymtl.ca>
Thu, 13 Aug 2020 11:55:48 +0000 (07:55 -0400)
I found myself wanting to run a few specific selftests while developing.
I thought it would be nice to be able to provide multiple test names
when running `maintenant selftests`.  The arguments to that command is
currently interpreted as a single filter (not split by spaces), it now
becomes a list a filters, split by spaces.  A test is executed when it
matches at least one filter.

Here's an example of the result in GDB:

    (gdb) maintenance selftest xml
    Running selftest xml_escape_text.
    Running selftest xml_escape_text_append.
    Ran 2 unit tests, 0 failed
    (gdb) maintenance selftest xml unord
    Running selftest unordered_remove.
    Running selftest xml_escape_text.
    Running selftest xml_escape_text_append.
    Ran 3 unit tests, 0 failed
    (gdb) maintenance selftest xml unord foobar
    Running selftest unordered_remove.
    Running selftest xml_escape_text.
    Running selftest xml_escape_text_append.
    Ran 3 unit tests, 0 failed

Since the selftest machinery is also shared with gdbserver, I also
adapted gdbserver.  It accepts a `--selftest` switch, which accepts an
optional filter argument.  I made it so you can now pass `--selftest`
multiple time to add filters.

It's not so useful right now though: there's only a single selftest
right now in GDB and it's for an architecture I can't compile.  So I
tested by adding dummy tests, here's an example of the result:

    $ ./gdbserver --selftest=foo
    Running selftest foo.
    foo
    Running selftest foobar.
    foobar
    Ran 2 unit tests, 0 failed
    $ ./gdbserver --selftest=foo --selftest=bar
    Running selftest bar.
    bar
    Running selftest foo.
    foo
    Running selftest foobar.
    foobar
    Ran 3 unit tests, 0 failed

gdbsupport/ChangeLog:

* selftest.h (run_tests): Change parameter to array_view.
* selftest.c (run_tests): Change parameter to array_view and use
it.

gdb/ChangeLog:

* maint.c (maintenance_selftest): Split args and pass array_view
to run_tests.

gdbserver/ChangeLog:

* server.cc (captured_main): Accept multiple `--selftest=`
options.  Pass all `--selftest=` arguments to run_tests.

Change-Id: I422bd49f08ea8095ae174c5d66a2dd502a59613a

gdb/ChangeLog
gdb/maint.c
gdbserver/ChangeLog
gdbserver/server.cc
gdbsupport/ChangeLog
gdbsupport/selftest.cc
gdbsupport/selftest.h

index 27c6849cd6ae182b7ebebfe1bf260a1549721799..c1dc0ec01010ed1774fc02d81ff80a233b04f3d7 100644 (file)
@@ -1,3 +1,8 @@
+2020-08-13  Simon Marchi  <simon.marchi@polymtl.ca>
+
+       * maint.c (maintenance_selftest): Split args and pass array_view
+       to run_tests.
+
 2020-08-12  Luis Machado  <luis.machado@linaro.org>
 
        * value.c (check_type_length_before_alloc): Use ULONGEST to store a
index b4890c34cab9bc1694bf7a14e0d27547026116d8..fd37acce5226c18b0875930d56671df71b671987 100644 (file)
@@ -1041,7 +1041,8 @@ static void
 maintenance_selftest (const char *args, int from_tty)
 {
 #if GDB_SELF_TEST
-  selftests::run_tests (args);
+  gdb_argv argv (args);
+  selftests::run_tests (gdb::array_view<char *> (argv.get (), argv.count ()));
 #else
   printf_filtered (_("\
 Selftests have been disabled for this build.\n"));
index 743aa139c1764f70755170b142222468607ee747..e437493b56df38453ae46768406d71635c5cc662 100644 (file)
@@ -1,3 +1,8 @@
+2020-08-13  Simon Marchi  <simon.marchi@polymtl.ca>
+
+       * server.cc (captured_main): Accept multiple `--selftest=`
+       options.  Pass all `--selftest=` arguments to run_tests.
+
 2020-07-30  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * configure, config.in: Regenerate.
index aadcb9b5d30dc9b89cc99771c556e3a0f8cd64c0..d45154d1f54777d25b4f53a2f09e35ef1329dc51 100644 (file)
@@ -3610,7 +3610,7 @@ captured_main (int argc, char *argv[])
   int was_running;
   bool selftest = false;
 #if GDB_SELF_TEST
-  const char *selftest_filter = NULL;
+  std::vector<const char *> selftest_filters;
 #endif
 
   current_directory = getcwd (NULL, 0);
@@ -3747,8 +3747,16 @@ captured_main (int argc, char *argv[])
       else if (startswith (*next_arg, "--selftest="))
        {
          selftest = true;
+
 #if GDB_SELF_TEST
-         selftest_filter = *next_arg + strlen ("--selftest=");
+         const char *filter = *next_arg + strlen ("--selftest=");
+         if (*filter == '\0')
+           {
+             fprintf (stderr, _("Error: selftest filter is empty.\n"));
+             exit (1);
+           }
+
+         selftest_filters.push_back (filter);
 #endif
        }
       else
@@ -3825,7 +3833,7 @@ captured_main (int argc, char *argv[])
   if (selftest)
     {
 #if GDB_SELF_TEST
-      selftests::run_tests (selftest_filter);
+      selftests::run_tests (selftest_filters);
 #else
       printf (_("Selftests have been disabled for this build.\n"));
 #endif
index 27132444cc35698d3c52c5b5fe7eb452342e53bb..a19605373842999e98242d5534589d0ff8ad2d56 100644 (file)
@@ -1,3 +1,9 @@
+2020-08-13  Simon Marchi  <simon.marchi@polymtl.ca>
+
+       * selftest.h (run_tests): Change parameter to array_view.
+       * selftest.c (run_tests): Change parameter to array_view and use
+       it.
+
 2020-07-30  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * Makefile.am (AM_CPPFLAGS): Add LARGEFILE_CPPFLAGS.
index 8ab63be31391c92b87a0a1bcf1b75d71e44d907e..2adb7245571c5897beaf8aeee9e142b0f6660ac9 100644 (file)
@@ -68,7 +68,7 @@ register_test (const std::string &name, self_test_function *function)
 /* See selftest.h.  */
 
 void
-run_tests (const char *filter)
+run_tests (gdb::array_view<const char *const> filters)
 {
   int ran = 0, failed = 0;
 
@@ -76,9 +76,20 @@ run_tests (const char *filter)
     {
       const std::string &name = pair.first;
       const std::unique_ptr<selftest> &test = pair.second;
+      bool run = false;
 
-      if (filter != NULL && *filter != '\0'
-         && name.find (filter) == std::string::npos)
+      if (filters.empty ())
+       run = true;
+      else
+       {
+         for (const char *filter : filters)
+           {
+             if (name.find (filter) != std::string::npos)
+               run = true;
+           }
+       }
+
+      if (!run)
        continue;
 
       try
index 1c47fe1448ba6a1f1667d08a89a9f5d1c4bd8056..e0086132f7b97b29814892159fdc7a8551d61678 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef COMMON_SELFTEST_H
 #define COMMON_SELFTEST_H
 
+#include "gdbsupport/array-view.h"
+
 /* A test is just a function that does some checks and throws an
    exception if something has gone wrong.  */
 
@@ -47,10 +49,10 @@ extern void register_test (const std::string &name,
 /* Run all the self tests.  This print a message describing the number
    of test and the number of failures.
 
-   If FILTER is not NULL and not empty, only tests with names containing FILTER
-   will be ran.  */
+   If FILTERS is not empty, only run tests with names containing one of the
+   element of FILTERS.  */
 
-extern void run_tests (const char *filter);
+extern void run_tests (gdb::array_view<const char *const> filters);
 
 /* Reset GDB or GDBserver's internal state.  */
 extern void reset ();