/* GDB self-testing.
   Copyright (C) 2016-2022 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 "common-defs.h"
#include "common-exceptions.h"
#include "common-debug.h"
#include "selftest.h"
#include <functional>

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<selftests_generator> lazy_generators;

/* See selftest.h.  */

void
register_test (const std::string &name,
	       std::function<void(void)> 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<const char *const> 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
