mirror of
				https://git.proxmox.com/git/grub2
				synced 2025-11-04 03:55:15 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			240 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *  GRUB  --  GRand Unified Bootloader
 | 
						|
 *  Copyright (C) 2010 Free Software Foundation, Inc.
 | 
						|
 *
 | 
						|
 *  GRUB 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.
 | 
						|
 *
 | 
						|
 *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
 | 
						|
#include <grub/mm.h>
 | 
						|
#include <grub/misc.h>
 | 
						|
#include <grub/test.h>
 | 
						|
 | 
						|
struct grub_test_failure
 | 
						|
{
 | 
						|
  /* The next failure.  */
 | 
						|
  struct grub_test_failure *next;
 | 
						|
  struct grub_test_failure **prev;
 | 
						|
 | 
						|
  /* The test source file name.  */
 | 
						|
  char *file;
 | 
						|
 | 
						|
  /* The test function name.  */
 | 
						|
  char *funp;
 | 
						|
 | 
						|
  /* The test call line number.  */
 | 
						|
  grub_uint32_t line;
 | 
						|
 | 
						|
  /* The test failure message.  */
 | 
						|
  char *message;
 | 
						|
};
 | 
						|
typedef struct grub_test_failure *grub_test_failure_t;
 | 
						|
 | 
						|
grub_test_t grub_test_list;
 | 
						|
static grub_test_failure_t failure_list;
 | 
						|
 | 
						|
static grub_test_failure_t
 | 
						|
failure_start(const char *file, const char *funp, grub_uint32_t line);
 | 
						|
static grub_test_failure_t
 | 
						|
failure_start(const char *file, const char *funp, grub_uint32_t line)
 | 
						|
{
 | 
						|
  grub_test_failure_t failure;
 | 
						|
 | 
						|
  failure = (grub_test_failure_t) grub_malloc (sizeof (*failure));
 | 
						|
  if (!failure)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  failure->file = grub_strdup (file ? : "<unknown_file>");
 | 
						|
  if (!failure->file)
 | 
						|
    {
 | 
						|
      grub_free(failure);
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  failure->funp = grub_strdup (funp ? : "<unknown_function>");
 | 
						|
  if (!failure->funp)
 | 
						|
    {
 | 
						|
      grub_free(failure->file);
 | 
						|
      grub_free(failure);
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  failure->line = line;
 | 
						|
 | 
						|
  failure->message = NULL;
 | 
						|
 | 
						|
  return failure;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
failure_append_vtext(grub_test_failure_t failure, const char *fmt, va_list args);
 | 
						|
static void
 | 
						|
failure_append_vtext(grub_test_failure_t failure, const char *fmt, va_list args)
 | 
						|
{
 | 
						|
  char *msg = grub_xvasprintf(fmt, args);
 | 
						|
  if (failure->message)
 | 
						|
    {
 | 
						|
      char *oldmsg = failure->message;
 | 
						|
 | 
						|
      failure->message = grub_xasprintf("%s%s", oldmsg, msg);
 | 
						|
      grub_free (oldmsg);
 | 
						|
      grub_free (msg);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      failure->message = msg;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
failure_append_text(grub_test_failure_t failure, const char *fmt, ...)
 | 
						|
{
 | 
						|
  va_list args;
 | 
						|
 | 
						|
  va_start(args, fmt);
 | 
						|
  failure_append_vtext(failure, fmt, args);
 | 
						|
  va_end(args);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
add_failure (const char *file,
 | 
						|
	     const char *funp,
 | 
						|
	     grub_uint32_t line, const char *fmt, va_list args)
 | 
						|
{
 | 
						|
  grub_test_failure_t failure = failure_start(file, funp, line);
 | 
						|
  failure_append_text(failure, fmt, args);
 | 
						|
  grub_list_push (GRUB_AS_LIST_P (&failure_list), GRUB_AS_LIST (failure));
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
free_failures (void)
 | 
						|
{
 | 
						|
  grub_test_failure_t item;
 | 
						|
 | 
						|
  while (failure_list)
 | 
						|
    {
 | 
						|
      item = failure_list;
 | 
						|
      failure_list = item->next;
 | 
						|
      if (item->message)
 | 
						|
	grub_free (item->message);
 | 
						|
 | 
						|
      if (item->funp)
 | 
						|
	grub_free (item->funp);
 | 
						|
 | 
						|
      if (item->file)
 | 
						|
	grub_free (item->file);
 | 
						|
 | 
						|
      grub_free (item);
 | 
						|
    }
 | 
						|
  failure_list = 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
grub_test_nonzero (int cond,
 | 
						|
		   const char *file,
 | 
						|
		   const char *funp, grub_uint32_t line, const char *fmt, ...)
 | 
						|
{
 | 
						|
  va_list ap;
 | 
						|
 | 
						|
  if (cond)
 | 
						|
    return;
 | 
						|
 | 
						|
  va_start (ap, fmt);
 | 
						|
  add_failure (file, funp, line, fmt, ap);
 | 
						|
  va_end (ap);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
grub_test_assert_helper (int cond, const char *file, const char *funp,
 | 
						|
			 grub_uint32_t line, const char *condstr,
 | 
						|
			 const char *fmt, ...)
 | 
						|
{
 | 
						|
  va_list ap;
 | 
						|
  grub_test_failure_t failure;
 | 
						|
 | 
						|
  if (cond)
 | 
						|
    return;
 | 
						|
 | 
						|
  failure = failure_start(file, funp, line);
 | 
						|
  failure_append_text(failure, "assert failed: %s ", condstr);
 | 
						|
 | 
						|
  va_start(ap, fmt);
 | 
						|
 | 
						|
  failure_append_vtext(failure, fmt, ap);
 | 
						|
 | 
						|
  va_end(ap);
 | 
						|
 | 
						|
  grub_list_push (GRUB_AS_LIST_P (&failure_list), GRUB_AS_LIST (failure));
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
grub_test_register (const char *name, void (*test_main) (void))
 | 
						|
{
 | 
						|
  grub_test_t test;
 | 
						|
 | 
						|
  test = (grub_test_t) grub_malloc (sizeof (*test));
 | 
						|
  if (!test)
 | 
						|
    return;
 | 
						|
 | 
						|
  test->name = grub_strdup (name);
 | 
						|
  test->main = test_main;
 | 
						|
 | 
						|
  grub_list_push (GRUB_AS_LIST_P (&grub_test_list), GRUB_AS_LIST (test));
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
grub_test_unregister (const char *name)
 | 
						|
{
 | 
						|
  grub_test_t test;
 | 
						|
 | 
						|
  test = (grub_test_t) grub_named_list_find
 | 
						|
    (GRUB_AS_NAMED_LIST (grub_test_list), name);
 | 
						|
 | 
						|
  if (test)
 | 
						|
    {
 | 
						|
      grub_list_remove (GRUB_AS_LIST (test));
 | 
						|
 | 
						|
      if (test->name)
 | 
						|
	grub_free (test->name);
 | 
						|
 | 
						|
      grub_free (test);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
grub_test_run (grub_test_t test)
 | 
						|
{
 | 
						|
  grub_test_failure_t failure;
 | 
						|
 | 
						|
  test->main ();
 | 
						|
 | 
						|
  grub_printf ("%s:\n", test->name);
 | 
						|
  FOR_LIST_ELEMENTS (failure, failure_list)
 | 
						|
    grub_printf (" %s:%s:%u: %s\n",
 | 
						|
		 (failure->file ? : "<unknown_file>"),
 | 
						|
		 (failure->funp ? : "<unknown_function>"),
 | 
						|
		 failure->line, (failure->message ? : "<no message>"));
 | 
						|
 | 
						|
  if (!failure_list)
 | 
						|
    {
 | 
						|
      grub_printf ("%s: PASS\n", test->name);
 | 
						|
      return GRUB_ERR_NONE;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      grub_printf ("%s: FAIL\n", test->name);
 | 
						|
      free_failures ();
 | 
						|
      return GRUB_ERR_TEST_FAILURE;
 | 
						|
    }
 | 
						|
}
 |