[syslinux:firmware] tests: Syslinux unit tests

syslinux-bot for Matt Fleming matt.fleming at intel.com
Tue Jul 23 07:18:07 PDT 2013


Commit-ID:  82546447f46cab11f13380fe658b1f79cdd38654
Gitweb:     http://www.syslinux.org/commit/82546447f46cab11f13380fe658b1f79cdd38654
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Wed, 17 Jul 2013 14:53:08 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Tue, 23 Jul 2013 14:58:41 +0100

tests: Syslinux unit tests

Improve our faith in the validity of the Syslinux code by writing unit
tests where possible. These should be used in addition to the regression
tests - unit tests are a means of doing very fine-grained testing of
code, whereas the regression tests are end-to-end tests that exercise
abstract functionality.

Unit tests run on your development machine and above all else, their
execution time should be kept to a minimum to encourage repeated runs of
the unit testsuite.

The Syslinux header hierarchy has been reconstructed under
tests/unittest/include. This allows us to reuse header files where
appropriate by simply creating a file with the same name and including
the original, e.g.

tests/unittest/include/com32.h:

  #include <../../../com32/include/com32.h>

Places where we need to override definitions (so that the tests build in
a dev environment) obviously won't include the original header file, but
such scenarios should be kept to a minimum, since you're not really
testing any Syslinux code that way.

To execute the collection of unit tests type,

  make unittest

Sample output might look like,

  Executing unit tests
      Running library unit tests...
        [+] zonelist passed
        [+] movebits passed
        [+] memscan passed

Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 Makefile                                   |   8 +-
 com32/lib/syslinux/tests/Makefile          |  23 +++
 com32/lib/syslinux/tests/memscan.c         |  75 ++++++++++
 com32/lib/syslinux/tests/movebits.c        |  85 +++++++++++
 com32/lib/syslinux/tests/test-harness.c    |  49 +++++++
 com32/lib/syslinux/tests/test.h            |  17 +++
 com32/lib/syslinux/tests/zonelist.c        | 219 +++++++++++++++++++++++++++++
 tests/unittest/include/com32.h             |   1 +
 tests/unittest/include/core.h              |   8 ++
 tests/unittest/include/dprintf.h           |   6 +
 tests/unittest/include/klibc/compiler.h    |  15 ++
 tests/unittest/include/linux/list.h        |   9 ++
 tests/unittest/include/minmax.h            |   1 +
 tests/unittest/include/pxe.h               |   3 +
 tests/unittest/include/syslinux/align.h    |   1 +
 tests/unittest/include/syslinux/memscan.h  |   1 +
 tests/unittest/include/syslinux/movebits.h |   1 +
 tests/unittest/include/unittest.h          |  29 ++++
 18 files changed, 549 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index d90635a..e9c1654 100644
--- a/Makefile
+++ b/Makefile
@@ -72,7 +72,7 @@ include $(MAKEDIR)/syslinux.mk
 -include $(OBJDIR)/version.mk
 
 private-targets = prerel unprerel official release burn isolinux.iso \
-		  preupload upload test
+		  preupload upload test unittest regression
 
 ifeq ($(MAKECMDGOALS),)
 	MAKECMDGOALS += all
@@ -101,13 +101,17 @@ $(filter-out $(private-targets), $(MAKECMDGOALS)):
 	$(MAKE) -C $(OBJDIR) -f $(CURDIR)/Makefile SRC="$(topdir)" \
 		OBJ=$(OBJDIR) objdir=$(OBJDIR) $(MAKECMDGOALS)
 
-test:
+unittest:
 	printf "Executing unit tests\n"
 	$(MAKE) -C com32/lib/syslinux/tests all
+
+regression:
 	$(MAKE) -C tests SRC="$(topdir)/tests" OBJ="$(topdir)/tests" \
 		objdir=$(OBJDIR) \
 		-f $(topdir)/tests/Makefile all
 
+test: unittest regression
+
 # Hook to add private Makefile targets for the maintainer.
 -include $(topdir)/Makefile.private
 
diff --git a/com32/lib/syslinux/tests/Makefile b/com32/lib/syslinux/tests/Makefile
new file mode 100644
index 0000000..485a9ce
--- /dev/null
+++ b/com32/lib/syslinux/tests/Makefile
@@ -0,0 +1,23 @@
+CFLAGS = -I$(topdir)/tests/unittest/include
+
+tests = zonelist movebits memscan
+
+all: banner $(tests)
+	for t in $(tests); \
+		do printf "      [+] $$t passed\n" ; ./$$t ; done
+clean:
+	rm $(tests)
+
+banner:
+	printf "    Running library unit tests...\n"
+
+harness-files = test-harness.c
+
+zonelist: zonelist.c ../zonelist.c $(harness-files)
+movebits: movebits.c ../movebits.c $(harness-files)
+memscan: memscan.c ../memscan.c
+
+%: %.c
+	$(CC) $(CFLAGS) -o $@ $<
+
+
diff --git a/com32/lib/syslinux/tests/memscan.c b/com32/lib/syslinux/tests/memscan.c
new file mode 100644
index 0000000..bc43a3e
--- /dev/null
+++ b/com32/lib/syslinux/tests/memscan.c
@@ -0,0 +1,75 @@
+#include "test.h"
+
+#include "../memscan.c"
+
+struct memmap {
+    addr_t start;
+    size_t size;
+    enum syslinux_memmap_types type;
+    bool visited;
+};
+
+static struct memmap memmap[] = {
+    { 0x00000, 0x2000, SMT_FREE, false },
+    { 0x400000, 0x1000, SMT_TERMINAL, false},
+};
+
+#define MEMMAP_SIZE (sizeof(memmap) / sizeof(memmap[0]))
+
+/*
+ * Our dummy memory scanner. This is analogous to bios_scan_memory() or
+ * efi_scan_memory(), etc.
+ */
+static int test_scan_memory(scan_memory_callback_t callback, void *data)
+{
+    int i, rv;
+
+    for (i = 0; i < MEMMAP_SIZE; i++)
+	rv = callback(data, memmap[i].start, memmap[i].size, memmap[i].type);
+
+    return 0;
+}
+
+static int callback(void *data, addr_t start, addr_t size,
+		    enum syslinux_memmap_types type)
+{
+    int i;
+
+    for (i = 0; i < MEMMAP_SIZE; i++) {
+	if (memmap[i].start == start && memmap[i].size == size) {
+	    memmap[i].visited = true;
+	    break;
+	}
+    }
+
+    return 0;
+}
+
+static int verify_visited_all_memmap_entries(void)
+{
+    int i;
+
+    syslinux_memscan_new(test_scan_memory);
+    syslinux_scan_memory(callback, NULL);
+
+    for (i = 0; i < MEMMAP_SIZE; i++) {
+	addr_t start = memmap[i].start;
+	bool visited_entry = memmap[i].visited;
+
+	syslinux_assert(visited_entry, "Didn't pass entry %d to callback", i);
+    }
+
+    return 0;
+}
+
+static int verify_invoked_all_callbacks(void)
+{
+    syslinux_scan_memory(callback, NULL);
+}
+
+int main(int argc, char **argv)
+{
+    verify_visited_all_memmap_entries();
+
+    return 0;
+}
diff --git a/com32/lib/syslinux/tests/movebits.c b/com32/lib/syslinux/tests/movebits.c
new file mode 100644
index 0000000..09c02cb
--- /dev/null
+++ b/com32/lib/syslinux/tests/movebits.c
@@ -0,0 +1,85 @@
+#include "test.h"
+#include <setjmp.h>
+
+#include "../../../include/minmax.h"
+#include "../zonelist.c"
+#include "test-harness.c"
+
+static int move_to_terminal_region(void)
+{
+    struct syslinux_memmap *mmap;
+    addr_t dst, src;
+    size_t len;
+    int rv = -1;
+    struct mmap_entry entries[] = {
+	{ 0x00000, 0x90000, SMT_RESERVED },
+	{ 0x90000, 0x10000, SMT_TERMINAL },
+	{ 0xa0000, 0xf000, SMT_FREE },
+	{ 0x100000, 0x3000, SMT_FREE }
+    };
+
+    mmap = test_build_mmap(entries, array_sz(entries));
+    if (!mmap)
+	goto bail;
+
+    dst = 0x90000;
+    src = 0x1fff000;
+    len = 0xf000;
+
+    rv = syslinux_memmap_find(mmap, &dst, len, false, 16,
+			      0, (addr_t)-1, 0, (addr_t)-1);
+    syslinux_assert(!rv, "Expected to find 0x%x to be SMT_TERMINAL", dst);
+
+    rv = test_attempt_movelist(mmap, dst, src, len);
+    syslinux_assert(!rv, "Expected to move 0x%x to 0x%x, len 0x%x", src, dst, len);
+
+    rv = 0;
+
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+static int move_to_overlapping_region(void)
+{
+    struct syslinux_memmap *mmap;
+    addr_t dst, src;
+    size_t len;
+    int rv = -1;
+    struct mmap_entry entries[] = {
+	{ 0x00000, 0x90000, SMT_RESERVED },
+	{ 0x90000, 0x10000, SMT_TERMINAL },
+	{ 0xa0000, 0xf000, SMT_FREE },
+	{ 0x100000, 0x3000, SMT_TERMINAL },
+	{ 0x103000, 0x1000, SMT_FREE },
+    };
+
+    mmap = test_build_mmap(entries, array_sz(entries));
+    if (!mmap)
+	goto bail;
+
+    rv = test_attempt_movelist(mmap, 0x90000, 0x300000, 0x10001);
+    syslinux_assert(!rv, "Allocating across boundary region failed");
+
+    rv = test_attempt_movelist(mmap, 0xa0000, 0x4000000, 0x10000);
+    syslinux_assert(rv, "Move into undefined region succeeded");
+
+    rv = test_attempt_movelist(mmap, 0x80000, 0x200000, 0x10000);
+    syslinux_assert(rv, "Move across incompatible region boundary succeeded");
+
+    rv = test_attempt_movelist(mmap, 0x100000, 0x4000000, 0x4001);
+    syslinux_assert(rv, "Move past end of available regions succeeded");
+
+    rv = 0;
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+int main(int argc, char **argv)
+{
+    move_to_terminal_region();
+    move_to_overlapping_region();
+
+    return 0;
+}
diff --git a/com32/lib/syslinux/tests/test-harness.c b/com32/lib/syslinux/tests/test-harness.c
new file mode 100644
index 0000000..49e32f8
--- /dev/null
+++ b/com32/lib/syslinux/tests/test-harness.c
@@ -0,0 +1,49 @@
+#include "test.h"
+#include "../addlist.c"
+#include "../freelist.c"
+#include "../movebits.c"
+
+struct syslinux_memmap *test_build_mmap(struct mmap_entry *entries,
+					size_t nr_entries)
+{
+    struct syslinux_memmap *mmap;
+    int i;
+
+    mmap = syslinux_init_memmap();
+    if (!mmap)
+	goto bail;
+
+    for (i = 0; i < nr_entries; i++) {
+	enum syslinux_memmap_types type = entries[i].type;
+	addr_t start = entries[i].start;
+	addr_t size = entries[i].size;
+
+	if (syslinux_add_memmap(&mmap, start, size, type))
+	    goto bail;
+    }
+
+    return mmap;
+
+bail:
+    syslinux_free_memmap(mmap);
+    return NULL;
+}
+
+int test_attempt_movelist(struct syslinux_memmap *mmap, addr_t dst,
+			  addr_t src, size_t len)
+{
+    struct syslinux_movelist *frags = NULL;
+    struct syslinux_movelist *moves = NULL;
+    int rv;
+
+    rv = syslinux_add_movelist(&frags, dst, src, len);
+    if (rv)
+	goto bail;
+
+    rv = syslinux_compute_movelist(&moves, frags, mmap);
+
+bail:
+    syslinux_free_movelist(frags);
+    syslinux_free_movelist(moves);
+    return rv;
+}
diff --git a/com32/lib/syslinux/tests/test.h b/com32/lib/syslinux/tests/test.h
new file mode 100644
index 0000000..91ba860
--- /dev/null
+++ b/com32/lib/syslinux/tests/test.h
@@ -0,0 +1,17 @@
+#ifndef _TEST_H_
+#define _TEST_H_
+
+#include "unittest.h"
+#include "syslinux/movebits.h"
+
+#define array_sz(x)	(sizeof((x)) / sizeof((x)[0]))
+
+struct mmap_entry {
+    addr_t start;
+    addr_t size;
+    enum syslinux_memmap_types type;
+};
+
+extern struct syslinux_memmap *build_mmap(struct mmap_entry *entries,
+					  size_t nr_entries);
+#endif /* _TEST_H_ */
diff --git a/com32/lib/syslinux/tests/zonelist.c b/com32/lib/syslinux/tests/zonelist.c
new file mode 100644
index 0000000..ac7c174
--- /dev/null
+++ b/com32/lib/syslinux/tests/zonelist.c
@@ -0,0 +1,219 @@
+/*
+ * Unit test.
+ *
+ * We make heavy use of assertions to ensure that our expectations are
+ * met regarding the Syslinux library interfaces. If an assert fails we
+ * keep running the test if possible to try and save as much information
+ * regarding the failures.
+ *
+ * A unit test function should return an error if it failed to setup the
+ * infrastructure, e.g. malloc() fails. If an assertion fires, that is
+ * not mean the test infrastructure failed, merely that the test didn't
+ * pass.
+ *
+ * To work around any include path issues due to the unit tests being
+ * run on the development host we must include all headers with absolute
+ * paths.
+ */
+#include "test.h"
+#include "../zonelist.c"
+#include "test-harness.c"
+
+static int refuse_to_alloc_reserved_region(void)
+{
+    struct syslinux_memmap *mmap;
+    const char *cmdline;
+    size_t kernel_size;
+    bool relocatable = false;
+    size_t alignment = 1;
+    addr_t base;
+    int rv = -1;
+
+    mmap = syslinux_init_memmap();
+    if (!mmap)
+	goto bail;
+
+    if (syslinux_add_memmap(&mmap, 0x90000, 0x10000, SMT_RESERVED))
+	goto bail;
+
+    base = 0x90000;
+    rv = syslinux_memmap_find(mmap, &base, 0x1000, relocatable, alignment,
+			      base, base, 0, 640 * 1024);
+    syslinux_assert(rv, "Allocated reserved region 0x%x", base);
+
+    rv = 0;
+
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+static int refuse_to_alloc_above_max_address(void)
+{
+    struct syslinux_memmap *mmap;
+    addr_t base = 0x100000;
+    size_t size = 0x1000;
+    int rv = -1;
+
+    mmap = syslinux_init_memmap();
+    if (!mmap)
+	goto bail;
+
+    if (syslinux_add_memmap(&mmap, base, size, SMT_FREE))
+	goto bail;
+
+    rv = syslinux_memmap_find(mmap, &base, size, false, 16,
+			      base, base, 0, 640 * 1024);
+    syslinux_assert(!rv, "Failed to find a free region");
+
+    syslinux_assert_str(!(base < 0x100000), "Region below min address");
+    syslinux_assert_str(!(base > 0x100000), "Region above max address");
+
+    rv = 0;
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+static int alloc_region_with_zero_size(void)
+{
+    int rv;
+
+    rv = syslinux_memmap_find(NULL, 0, 0, false, 0, 0, 0, 0, 0); 
+    syslinux_assert(!rv, "Should be able to allocate a zero-size region");
+
+    return 0;
+}
+
+static int refuse_to_relocate_region(void)
+{
+    struct syslinux_memmap *mmap;
+    addr_t free_base;
+    size_t free_size;
+    int rv = -1;
+
+    mmap = syslinux_init_memmap();
+    if (!mmap)
+	goto bail;
+
+    free_base = 0x20000;
+    free_size = 0x1000000;
+    if (syslinux_add_memmap(&mmap, free_base, free_size, SMT_FREE))
+	goto bail;
+
+    free_base = 0x10000;
+    free_size = 0x7000;
+    rv = syslinux_memmap_find(mmap, &free_base, free_size, false, 1,
+			      0, (addr_t)-1, (addr_t)0, (addr_t)-1);
+    syslinux_assert(rv, "Relocated region from 0x10000 to 0x%x", free_base);
+
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+static int only_relocate_upwards(void)
+{
+    struct syslinux_memmap *mmap;
+    addr_t base;
+    int rv = -1;
+
+    mmap = syslinux_init_memmap();
+    if (!mmap)
+	goto bail;
+
+    if (syslinux_add_memmap(&mmap, 0x00010, 0x1000, SMT_FREE))
+	goto bail;
+
+    base = 0x10000;
+    rv = syslinux_memmap_find(mmap, &base, 16, true, 1, 0, (addr_t)-1,
+			      0x2000, (addr_t)-1);
+
+    syslinux_assert(rv, "Should not have found any entry in memmap");
+    syslinux_assert_str(base >= 0x10000,
+			"Relocated in wrong direction 0x%x", base);
+
+    rv = 0;
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+static int alloc_in_pxe_region(void)
+{
+    struct syslinux_memmap *mmap;
+    addr_t base;
+    int rv = -1;
+
+    mmap = syslinux_init_memmap();
+    if (!mmap)
+	goto bail;
+
+    /* Construct a memmap with a gap where the PXE region usually is */
+    if (syslinux_add_memmap(&mmap, 0x00000, 0x8f000, SMT_FREE))
+	goto bail;
+
+    if (syslinux_add_memmap(&mmap, 0x100000, 0xf000, SMT_FREE))
+	goto bail;
+
+    base = 0x90000;
+    rv = syslinux_memmap_find(mmap, &base, 0x1000, false, 16,
+			      0, (addr_t)-1, 0, (addr_t)-1);
+
+    syslinux_assert(rv, "Shouldn't have allocated none existent region");
+
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+static int demote_free_region_to_terminal(void)
+{
+    enum syslinux_memmap_types type;
+    struct syslinux_memmap *mmap;
+    int rv = -1;
+    struct mmap_entry entries[] = {
+	{ 0x100000, 0x300000, SMT_TERMINAL },
+	{ 0x400000, 0x300000, SMT_FREE },
+	{ 0x700000, 0x20000, SMT_FREE },
+	{ 0x720000, 0x20000, SMT_TERMINAL },
+    };
+
+    mmap = test_build_mmap(entries, array_sz(entries));
+    if (!mmap)
+	goto bail;
+
+    type = syslinux_memmap_type(mmap, 0x100000, 0x500000);
+    syslinux_assert_str(type == SMT_TERMINAL,
+	"Expected SMT_TERMINAL + SMT_FREE region to cause type demotion");
+
+    type = syslinux_memmap_type(mmap, 0x700000, 0x40000);
+    syslinux_assert_str(type == SMT_TERMINAL,
+	"Expected SMT_FREE + SMT_TERMINAL region to cause type demotion");
+
+    type = syslinux_memmap_type(mmap, 0x100000, 0x640000);
+    syslinux_assert_str(type == SMT_TERMINAL,
+	"Expected multiple SMT_{FREE,TERMINAL} regions to cause type demotion");
+
+    rv = 0;
+
+bail:
+    syslinux_free_memmap(mmap);
+    return rv;
+}
+
+int main(int argc, char **argv)
+{
+    refuse_to_alloc_reserved_region();
+    refuse_to_alloc_above_max_address();
+
+    alloc_region_with_zero_size();
+
+    refuse_to_relocate_region();
+    only_relocate_upwards();
+
+    alloc_in_pxe_region();
+    demote_free_region_to_terminal();
+
+    return 0;
+}
diff --git a/tests/unittest/include/com32.h b/tests/unittest/include/com32.h
new file mode 100644
index 0000000..38b63d2
--- /dev/null
+++ b/tests/unittest/include/com32.h
@@ -0,0 +1 @@
+#include "../../../com32/include/com32.h"
diff --git a/tests/unittest/include/core.h b/tests/unittest/include/core.h
new file mode 100644
index 0000000..edfb75b
--- /dev/null
+++ b/tests/unittest/include/core.h
@@ -0,0 +1,8 @@
+#ifndef _CORE_H_
+#define _CORE_H_
+
+#include <klibc/compiler.h>
+
+#define __lowmem
+
+#endif /* _CORE_H_ */
diff --git a/tests/unittest/include/dprintf.h b/tests/unittest/include/dprintf.h
new file mode 100644
index 0000000..de251e1
--- /dev/null
+++ b/tests/unittest/include/dprintf.h
@@ -0,0 +1,6 @@
+#ifndef _DPRINTF_H_
+#define _DPRINTF_H_
+
+#define dprintf 
+
+#endif /* _DPRINTF_H_ */
diff --git a/tests/unittest/include/klibc/compiler.h b/tests/unittest/include/klibc/compiler.h
new file mode 100644
index 0000000..470a51c
--- /dev/null
+++ b/tests/unittest/include/klibc/compiler.h
@@ -0,0 +1,15 @@
+#ifndef _COMPILER_H_
+#define _COMPILER_H_
+
+#define __export
+
+/* Packed structures */
+#define __packed	__attribute__((packed))
+
+/* Weak symbols */
+#define __weak
+
+/* Specific calling conventions */
+#define __cdecl
+
+#endif /* _COMPILER_H_ */
diff --git a/tests/unittest/include/linux/list.h b/tests/unittest/include/linux/list.h
new file mode 100644
index 0000000..c553a14
--- /dev/null
+++ b/tests/unittest/include/linux/list.h
@@ -0,0 +1,9 @@
+#undef container_of
+/*
+ * The container_of construct: if p is a pointer to member m of
+ * container class c, then return a pointer to the container of which
+ * *p is a member.
+ */
+#define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m)))
+
+#include <../../../com32/include/linux/list.h>
diff --git a/tests/unittest/include/minmax.h b/tests/unittest/include/minmax.h
new file mode 100644
index 0000000..dfe4504
--- /dev/null
+++ b/tests/unittest/include/minmax.h
@@ -0,0 +1 @@
+#include <../../../com32/include/minmax.h>
diff --git a/tests/unittest/include/pxe.h b/tests/unittest/include/pxe.h
new file mode 100644
index 0000000..03c4ca6
--- /dev/null
+++ b/tests/unittest/include/pxe.h
@@ -0,0 +1,3 @@
+#include <../../../com32/include/syslinux/pxe_api.h>
+
+#define PKTBUF_SIZE	2048
diff --git a/tests/unittest/include/syslinux/align.h b/tests/unittest/include/syslinux/align.h
new file mode 100644
index 0000000..d7dc3bd
--- /dev/null
+++ b/tests/unittest/include/syslinux/align.h
@@ -0,0 +1 @@
+#include <../../../com32/include/syslinux/align.h>
diff --git a/tests/unittest/include/syslinux/memscan.h b/tests/unittest/include/syslinux/memscan.h
new file mode 100644
index 0000000..6509e64
--- /dev/null
+++ b/tests/unittest/include/syslinux/memscan.h
@@ -0,0 +1 @@
+#include <../../../com32/include/syslinux/memscan.h>
diff --git a/tests/unittest/include/syslinux/movebits.h b/tests/unittest/include/syslinux/movebits.h
new file mode 100644
index 0000000..0749faa
--- /dev/null
+++ b/tests/unittest/include/syslinux/movebits.h
@@ -0,0 +1 @@
+#include <../../../com32/include/syslinux/movebits.h>
diff --git a/tests/unittest/include/unittest.h b/tests/unittest/include/unittest.h
new file mode 100644
index 0000000..9f23d80
--- /dev/null
+++ b/tests/unittest/include/unittest.h
@@ -0,0 +1,29 @@
+#ifndef _UNITTEST_H_
+#define _UNITTEST_H_
+
+#include </usr/include/sys/types.h>
+#include </usr/include/stdint.h>
+#include </usr/include/assert.h>
+#include </usr/include/stdlib.h>
+#include </usr/include/stdio.h>
+#include </usr/include/stdint.h>
+
+/*
+ * Provide a version of assert() that prints helpful error messages when
+ * the condition is false, but doesn't abort the running program.
+ */
+#define syslinux_assert(condition, ...) \
+    if (!condition) {\
+	fprintf(stderr, "Assertion failed at %s:%d: \"", __FILE__, __LINE__); \
+	fprintf(stderr, __VA_ARGS__); \
+	fprintf(stderr, "\"\n"); \
+    }
+
+#define syslinux_assert_str(condition, ...) \
+    if (!(condition)) { \
+	fprintf(stderr, "Assertion failed at %s:%d: \"", __FILE__, __LINE__); \
+	fprintf(stderr, __VA_ARGS__); \
+	fprintf(stderr, "\", expr \"%s\"\n", __STRING(condition)); \
+    }
+
+#endif /* _UNITTEST_H_ */


More information about the Syslinux-commits mailing list