/* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2010 Free Software Foundation, Inc. * * VAS_EBOOT 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. * * VAS_EBOOT 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 VAS_EBOOT. If not, see . */ #include #include #include struct VasEBoot_test_failure { /* The next failure. */ struct VasEBoot_test_failure *next; struct VasEBoot_test_failure **prev; /* The test source file name. */ char *file; /* The test function name. */ char *funp; /* The test call line number. */ VasEBoot_uint32_t line; /* The test failure message. */ char *message; }; typedef struct VasEBoot_test_failure *VasEBoot_test_failure_t; VasEBoot_test_t VasEBoot_test_list; static VasEBoot_test_failure_t failure_list; static VasEBoot_test_failure_t failure_start(const char *file, const char *funp, VasEBoot_uint32_t line); static VasEBoot_test_failure_t failure_start(const char *file, const char *funp, VasEBoot_uint32_t line) { VasEBoot_test_failure_t failure; failure = (VasEBoot_test_failure_t) VasEBoot_malloc (sizeof (*failure)); if (!failure) return NULL; failure->file = VasEBoot_strdup (file ? : ""); if (!failure->file) { VasEBoot_free(failure); return NULL; } failure->funp = VasEBoot_strdup (funp ? : ""); if (!failure->funp) { VasEBoot_free(failure->file); VasEBoot_free(failure); return NULL; } failure->line = line; failure->message = NULL; return failure; } static void failure_append_vtext(VasEBoot_test_failure_t failure, const char *fmt, va_list args); static void failure_append_vtext(VasEBoot_test_failure_t failure, const char *fmt, va_list args) { char *msg = VasEBoot_xvasprintf(fmt, args); if (failure->message) { char *oldmsg = failure->message; failure->message = VasEBoot_xasprintf("%s%s", oldmsg, msg); VasEBoot_free (oldmsg); VasEBoot_free (msg); } else { failure->message = msg; } } static void failure_append_text(VasEBoot_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, VasEBoot_uint32_t line, const char *fmt, va_list args) { VasEBoot_test_failure_t failure = failure_start(file, funp, line); failure_append_text(failure, fmt, args); VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (&failure_list), VAS_EBOOT_AS_LIST (failure)); } static void free_failures (void) { VasEBoot_test_failure_t item; while (failure_list) { item = failure_list; failure_list = item->next; if (item->message) VasEBoot_free (item->message); if (item->funp) VasEBoot_free (item->funp); if (item->file) VasEBoot_free (item->file); VasEBoot_free (item); } failure_list = 0; } void VasEBoot_test_nonzero (int cond, const char *file, const char *funp, VasEBoot_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 VasEBoot_test_assert_helper (int cond, const char *file, const char *funp, VasEBoot_uint32_t line, const char *condstr, const char *fmt, ...) { va_list ap; VasEBoot_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); VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (&failure_list), VAS_EBOOT_AS_LIST (failure)); } void VasEBoot_test_register (const char *name, void (*test_main) (void)) { VasEBoot_test_t test; test = (VasEBoot_test_t) VasEBoot_malloc (sizeof (*test)); if (!test) return; test->name = VasEBoot_strdup (name); test->main = test_main; VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (&VasEBoot_test_list), VAS_EBOOT_AS_LIST (test)); } void VasEBoot_test_unregister (const char *name) { VasEBoot_test_t test; test = (VasEBoot_test_t) VasEBoot_named_list_find (VAS_EBOOT_AS_NAMED_LIST (VasEBoot_test_list), name); if (test) { VasEBoot_list_remove (VAS_EBOOT_AS_LIST (test)); if (test->name) VasEBoot_free (test->name); VasEBoot_free (test); } } int VasEBoot_test_run (VasEBoot_test_t test) { VasEBoot_test_failure_t failure; test->main (); VasEBoot_printf ("%s:\n", test->name); FOR_LIST_ELEMENTS (failure, failure_list) VasEBoot_printf (" %s:%s:%u: %s\n", (failure->file ? : ""), (failure->funp ? : ""), failure->line, (failure->message ? : "")); if (!failure_list) { VasEBoot_printf ("%s: PASS\n", test->name); return VAS_EBOOT_ERR_NONE; } else { VasEBoot_printf ("%s: FAIL\n", test->name); free_failures (); return VAS_EBOOT_ERR_TEST_FAILURE; } }