/* * 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 . */ #include #include #include 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 ? : ""); if (!failure->file) { grub_free(failure); return NULL; } failure->funp = grub_strdup (funp ? : ""); 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); } 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 ? : ""), (failure->funp ? : ""), failure->line, (failure->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; } }