/* GDB self-testing. Copyright (C) 2016-2023 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 . */ #include "common-defs.h" #include "common-exceptions.h" #include "common-debug.h" #include "selftest.h" #include namespace selftests { /* 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 selftests_registry tests; /* Set of callback functions used to register selftests after GDB is fully initialized. */ static std::vector lazy_generators; /* See selftest.h. */ void register_test (const std::string &name, std::function function) { /* Check that no test with this name already exist. */ auto status = tests.emplace (name, std::move (function)); if (!status.second) gdb_assert_not_reached ("Test already registered"); } /* See selftest.h. */ void add_lazy_generator (selftests_generator generator) { lazy_generators.push_back (std::move (generator)); } /* See selftest.h. */ static bool run_verbose_ = false; /* See selftest.h. */ bool run_verbose () { return run_verbose_; } /* See selftest.h. */ void run_tests (gdb::array_view filters, bool verbose) { int ran = 0, failed = 0; run_verbose_ = verbose; for (const auto &test : all_selftests ()) { bool run = false; if (filters.empty ()) run = true; else { for (const char *filter : filters) { if (test.name.find (filter) != std::string::npos) run = true; } } if (!run) continue; try { debug_printf (_("Running selftest %s.\n"), test.name.c_str ()); ++ran; test.test (); } catch (const gdb_exception_error &ex) { ++failed; debug_printf ("Self test failed: %s\n", ex.what ()); } reset (); } debug_printf (_("Ran %d unit tests, %d failed\n"), ran, failed); } /* See selftest.h. */ selftests_range all_selftests () { /* 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