Commit 3d4c75ff authored by Rusty Russell's avatar Rusty Russell

list: improve test coverage to 100%

In particular, we test the corruption cases.
parent dc0aafc9
......@@ -2,6 +2,20 @@
#include <stdlib.h>
#include "list.h"
static void *corrupt(const char *abortstr,
const struct list_node *head,
const struct list_node *node,
unsigned int count)
{
if (abortstr) {
fprintf(stderr,
"%s: prev corrupt in node %p (%u) of %p\n",
abortstr, node, count, head);
abort();
}
return NULL;
}
struct list_node *list_check_node(const struct list_node *node,
const char *abortstr)
{
......@@ -10,31 +24,18 @@ struct list_node *list_check_node(const struct list_node *node,
for (p = node, n = node->next; n != node; p = n, n = n->next) {
count++;
if (n->prev != p) {
if (!abortstr)
return NULL;
fprintf(stderr,
"%s: prev corrupt in node %p (%u) of %p\n",
abortstr, n, count, node);
abort();
}
if (n->prev != p)
return corrupt(abortstr, node, n, count);
}
/* Check prev on head node. */
if (node->prev != p)
return corrupt(abortstr, node, node, 0);
return (struct list_node *)node;
}
struct list_head *list_check(const struct list_head *h, const char *abortstr)
{
if (h->n.next == &h->n) {
if (h->n.prev != &h->n) {
if (!abortstr)
return NULL;
fprintf(stderr, "%s: prev corrupt in empty %p\n",
abortstr, h);
abort();
}
return (struct list_head *)h;
}
if (!list_check_node(&h->n, abortstr))
return NULL;
return (struct list_head *)h;
......
#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <err.h>
/* We don't actually want it to exit... */
static jmp_buf aborted;
#define abort() longjmp(aborted, 1)
#define fprintf my_fprintf
static char printf_buffer[1000];
static int my_fprintf(FILE *stream, const char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = vsprintf(printf_buffer, format, ap);
va_end(ap);
return ret;
}
#include <ccan/list/list.h>
#include <ccan/tap/tap.h>
#include <ccan/list/list.c>
int main(int argc, char *argv[])
{
struct list_head list;
struct list_node n1;
char expect[100];
plan_tests(9);
/* Empty list. */
list.n.next = &list.n;
list.n.prev = &list.n;
ok1(list_check(&list, NULL) == &list);
/* Bad back ptr */
list.n.prev = &n1;
/* Non-aborting version. */
ok1(list_check(&list, NULL) == NULL);
/* Aborting version. */
sprintf(expect, "test message: prev corrupt in node %p (0) of %p\n",
&list, &list);
if (setjmp(aborted) == 0) {
list_check(&list, "test message");
fail("list_check on empty with bad back ptr didn't fail!");
} else {
ok1(strcmp(printf_buffer, expect) == 0);
}
/* n1 in list. */
list.n.next = &n1;
list.n.prev = &n1;
n1.prev = &list.n;
n1.next = &list.n;
ok1(list_check(&list, NULL) == &list);
ok1(list_check_node(&n1, NULL) == &n1);
/* Bad back ptr */
n1.prev = &n1;
ok1(list_check(&list, NULL) == NULL);
ok1(list_check_node(&n1, NULL) == NULL);
/* Aborting version. */
sprintf(expect, "test message: prev corrupt in node %p (1) of %p\n",
&n1, &list);
if (setjmp(aborted) == 0) {
list_check(&list, "test message");
fail("list_check on n1 bad back ptr didn't fail!");
} else {
ok1(strcmp(printf_buffer, expect) == 0);
}
sprintf(expect, "test message: prev corrupt in node %p (0) of %p\n",
&n1, &n1);
if (setjmp(aborted) == 0) {
list_check_node(&n1, "test message");
fail("list_check_node on n1 bad back ptr didn't fail!");
} else {
ok1(strcmp(printf_buffer, expect) == 0);
}
return exit_status();
}
#define CCAN_LIST_DEBUG 1
#include <ccan/list/list.h>
#include <ccan/tap/tap.h>
#include <ccan/list/list.c>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *argv[])
{
struct list_head list1, list2;
struct list_node n1, n2, n3;
pid_t child;
int status;
plan_tests(1);
list_head_init(&list1);
list_head_init(&list2);
list_add(&list1, &n1);
list_add(&list2, &n2);
list_add_tail(&list2, &n3);
child = fork();
if (child) {
wait(&status);
} else {
/* This should abort. */
list_del_from(&list1, &n3);
exit(0);
}
ok1(WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT);
list_del_from(&list2, &n3);
return exit_status();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment