2010-01-17 17:29:57 +00:00
|
|
|
/*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
#include <grub/mm.h>
|
2010-01-08 09:49:10 +00:00
|
|
|
#include <grub/misc.h>
|
|
|
|
#include <grub/test.h>
|
|
|
|
|
|
|
|
struct grub_test_failure
|
|
|
|
{
|
|
|
|
/* The next failure. */
|
|
|
|
struct grub_test_failure *next;
|
2012-01-24 12:31:12 +00:00
|
|
|
struct grub_test_failure **prev;
|
2010-01-08 09:49:10 +00:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2012-05-27 12:26:18 +00:00
|
|
|
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)
|
2010-01-08 09:49:10 +00:00
|
|
|
{
|
|
|
|
grub_test_failure_t failure;
|
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
failure = (grub_test_failure_t) grub_malloc (sizeof (*failure));
|
2010-01-08 09:49:10 +00:00
|
|
|
if (!failure)
|
2012-05-27 12:26:18 +00:00
|
|
|
return NULL;
|
2010-01-08 09:49:10 +00:00
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
failure->file = grub_strdup (file ? : "<unknown_file>");
|
2012-05-27 12:26:18 +00:00
|
|
|
if (!failure->file)
|
|
|
|
{
|
|
|
|
grub_free(failure);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
failure->funp = grub_strdup (funp ? : "<unknown_function>");
|
2012-05-27 12:26:18 +00:00
|
|
|
if (!failure->funp)
|
|
|
|
{
|
|
|
|
grub_free(failure->file);
|
|
|
|
grub_free(failure);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-01-08 09:49:10 +00:00
|
|
|
failure->line = line;
|
|
|
|
|
2012-05-27 12:26:18 +00:00
|
|
|
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);
|
2013-05-04 11:47:10 +00:00
|
|
|
grub_free (oldmsg);
|
|
|
|
grub_free (msg);
|
2012-05-27 12:26:18 +00:00
|
|
|
}
|
|
|
|
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);
|
2010-01-08 09:49:10 +00:00
|
|
|
grub_list_push (GRUB_AS_LIST_P (&failure_list), GRUB_AS_LIST (failure));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_failures (void)
|
|
|
|
{
|
|
|
|
grub_test_failure_t item;
|
|
|
|
|
2010-03-26 19:20:52 +00:00
|
|
|
while (failure_list)
|
2010-01-08 09:49:10 +00:00
|
|
|
{
|
2010-03-26 19:20:52 +00:00
|
|
|
item = failure_list;
|
|
|
|
failure_list = item->next;
|
2010-01-08 09:49:10 +00:00
|
|
|
if (item->message)
|
2010-01-14 11:47:51 +00:00
|
|
|
grub_free (item->message);
|
2010-01-08 09:49:10 +00:00
|
|
|
|
|
|
|
if (item->funp)
|
2010-01-14 11:47:51 +00:00
|
|
|
grub_free (item->funp);
|
2010-01-08 09:49:10 +00:00
|
|
|
|
|
|
|
if (item->file)
|
2010-01-14 11:47:51 +00:00
|
|
|
grub_free (item->file);
|
2010-01-08 09:49:10 +00:00
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
grub_free (item);
|
2010-01-08 09:49:10 +00:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-05-27 12:26:18 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2010-01-08 09:49:10 +00:00
|
|
|
void
|
|
|
|
grub_test_register (const char *name, void (*test_main) (void))
|
|
|
|
{
|
|
|
|
grub_test_t test;
|
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
test = (grub_test_t) grub_malloc (sizeof (*test));
|
2010-01-08 09:49:10 +00:00
|
|
|
if (!test)
|
|
|
|
return;
|
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
test->name = grub_strdup (name);
|
2010-01-08 09:49:10 +00:00
|
|
|
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)
|
|
|
|
{
|
2012-01-24 12:31:12 +00:00
|
|
|
grub_list_remove (GRUB_AS_LIST (test));
|
2010-01-08 09:49:10 +00:00
|
|
|
|
|
|
|
if (test->name)
|
2010-01-14 11:47:51 +00:00
|
|
|
grub_free (test->name);
|
2010-01-08 09:49:10 +00:00
|
|
|
|
2010-01-14 11:47:51 +00:00
|
|
|
grub_free (test);
|
2010-01-08 09:49:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-01-08 11:05:32 +00:00
|
|
|
grub_test_run (grub_test_t test)
|
2010-01-08 09:49:10 +00:00
|
|
|
{
|
2010-03-26 18:35:34 +00:00
|
|
|
grub_test_failure_t failure;
|
|
|
|
|
|
|
|
test->main ();
|
2010-01-08 09:49:10 +00:00
|
|
|
|
2010-03-26 18:35:34 +00:00
|
|
|
grub_printf ("%s:\n", test->name);
|
|
|
|
FOR_LIST_ELEMENTS (failure, failure_list)
|
2010-01-14 11:47:51 +00:00
|
|
|
grub_printf (" %s:%s:%u: %s\n",
|
|
|
|
(failure->file ? : "<unknown_file>"),
|
|
|
|
(failure->funp ? : "<unknown_function>"),
|
|
|
|
failure->line, (failure->message ? : "<no message>"));
|
2010-01-08 09:49:10 +00:00
|
|
|
|
2010-01-08 11:05:32 +00:00
|
|
|
if (!failure_list)
|
2013-01-02 16:42:48 +00:00
|
|
|
{
|
|
|
|
grub_printf ("%s: PASS\n", test->name);
|
|
|
|
return GRUB_ERR_NONE;
|
|
|
|
}
|
2010-01-08 11:05:32 +00:00
|
|
|
else
|
2013-01-02 16:42:48 +00:00
|
|
|
{
|
|
|
|
grub_printf ("%s: FAIL\n", test->name);
|
|
|
|
free_failures ();
|
|
|
|
return GRUB_ERR_TEST_FAILURE;
|
|
|
|
}
|
2010-01-08 09:49:10 +00:00
|
|
|
}
|