elf: Don't merge sections with different SHF_LINK_ORDER
[binutils-gdb.git] / gdbsupport / selftest.cc
index 466d7cfeab5cb874751b3aac6bcbd52c012bd29d..c2e3936614591841197dcd402205e57f9cb02df5 100644 (file)
@@ -1,5 +1,5 @@
 /* GDB self-testing.
-   Copyright (C) 2016-2022 Free Software Foundation, Inc.
+   Copyright (C) 2016-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "common-exceptions.h"
 #include "common-debug.h"
 #include "selftest.h"
-#include <map>
 #include <functional>
 
 namespace selftests
 {
-/* All the tests that have been registered.  Using an std::map allows keeping
+/* All the tests that have been registered.  Using an std::set allows keeping
    the order of tests stable and easily looking up whether a test name
    exists.  */
 
-static std::map<std::string, std::function<void(void)>> tests;
+static selftests_registry tests;
+
+/* Set of callback functions used to register selftests after GDB is fully
+   initialized.  */
+
+static std::vector<selftests_generator> lazy_generators;
 
 /* See selftest.h.  */
 
@@ -38,9 +42,17 @@ register_test (const std::string &name,
               std::function<void(void)> function)
 {
   /* Check that no test with this name already exist.  */
-  gdb_assert (tests.find (name) == tests.end ());
+  auto status = tests.emplace (name, std::move (function));
+  if (!status.second)
+    gdb_assert_not_reached ("Test already registered");
+}
 
-  tests[name] = function;
+/* See selftest.h.  */
+
+void
+add_lazy_generator (selftests_generator generator)
+{
+  lazy_generators.push_back (std::move (generator));
 }
 
 /* See selftest.h.  */
@@ -63,10 +75,8 @@ run_tests (gdb::array_view<const char *const> filters, bool verbose)
   int ran = 0, failed = 0;
   run_verbose_ = verbose;
 
-  for (const auto &pair : tests)
+  for (const auto &test : all_selftests ())
     {
-      const std::string &name = pair.first;
-      const auto &test = pair.second;
       bool run = false;
 
       if (filters.empty ())
@@ -75,7 +85,7 @@ run_tests (gdb::array_view<const char *const> filters, bool verbose)
        {
          for (const char *filter : filters)
            {
-             if (name.find (filter) != std::string::npos)
+             if (test.name.find (filter) != std::string::npos)
                run = true;
            }
        }
@@ -85,9 +95,9 @@ run_tests (gdb::array_view<const char *const> filters, bool verbose)
 
       try
        {
-         debug_printf (_("Running selftest %s.\n"), name.c_str ());
+         debug_printf (_("Running selftest %s.\n"), test.name.c_str ());
          ++ran;
-         test ();
+         test.test ();
        }
       catch (const gdb_exception_error &ex)
        {
@@ -104,10 +114,18 @@ run_tests (gdb::array_view<const char *const> filters, bool verbose)
 
 /* See selftest.h.  */
 
-void for_each_selftest (for_each_selftest_ftype func)
+selftests_range
+all_selftests ()
 {
-  for (const auto &pair : tests)
-    func (pair.first);
+  /* Execute any function which might still want to register tests.  Once each
+     function has been executed, clear lazy_generators to ensure that
+     callback functions are only executed once.  */
+  for (const auto &generator : lazy_generators)
+    for (selftest &test : generator ())
+      register_test (std::move (test.name), std::move (test.test));
+  lazy_generators.clear ();
+
+  return selftests_range (tests.cbegin (), tests.cend ());
 }
 
 } // namespace selftests