#include <ccan/list/list.h>
#include <ccan/tap/tap.h>
#include <ccan/list/list.c>
+#include "helper.h"
struct parent {
const char *name;
struct parent parent;
struct child c1, c2, c3, *c, *n;
unsigned int i;
+ struct list_head list = LIST_HEAD_INIT(list);
+ opaque_t *q, *nq;
+ struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
- plan_tests(44);
- /* Test LIST_HEAD, list_empty and check_list */
+ plan_tests(70);
+ /* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
ok1(list_empty(&static_list));
ok1(list_check(&static_list, NULL));
+ ok1(list_empty(&list));
+ ok1(list_check(&list, NULL));
parent.num_children = 0;
list_head_init(&parent.children);
/* Test list_check */
ok1(list_check(&parent.children, NULL));
+ /* Test list_check_node */
+ ok1(list_check_node(&c1.list, NULL));
+ ok1(list_check_node(&c2.list, NULL));
+ ok1(list_check_node(&c3.list, NULL));
+
/* Test list_top */
ok1(list_top(&parent.children, struct child, list) == &c1);
+ /* Test list_pop */
+ ok1(list_pop(&parent.children, struct child, list) == &c1);
+ ok1(list_top(&parent.children, struct child, list) == &c2);
+ list_add(&parent.children, &c1.list);
+
/* Test list_tail */
ok1(list_tail(&parent.children, struct child, list) == &c3);
}
ok1(i == 3);
- /* Test list_for_each_safe and list_del. */
+ /* Test list_for_each_rev. */
i = 0;
- list_for_each_safe(&parent.children, c, n, list) {
+ list_for_each_rev(&parent.children, c, list) {
switch (i++) {
case 0:
+ ok1(c == &c3);
+ break;
+ case 1:
+ ok1(c == &c2);
+ break;
+ case 2:
ok1(c == &c1);
break;
+ }
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+
+ /* Test list_for_each_safe, list_del and list_del_from. */
+ i = 0;
+ list_for_each_safe(&parent.children, c, n, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ list_del(&c->list);
+ break;
case 1:
ok1(c == &c2);
+ list_del_from(&parent.children, &c->list);
break;
case 2:
ok1(c == &c3);
+ list_del_from(&parent.children, &c->list);
break;
}
- list_del(&c->list);
ok1(list_check(&parent.children, NULL));
if (i > 2)
break;
ok1(i == 3);
ok1(list_empty(&parent.children));
- /* Test list_top/list_tail on empty list. */
+ /* Test list_node_init: safe to list_del after this. */
+ list_node_init(&c->list);
+ list_del(&c->list);
+
+ /* Test list_del_init */
+ list_add(&parent.children, &c->list);
+ ok1(!list_empty(&parent.children));
+ list_del_init(&c->list);
+ ok1(list_empty(&parent.children));
+ /* We can call this as many times as we like. */
+ list_del_init(&c->list);
+ list_del_init(&c->list);
+
+ /* Test list_for_each_off. */
+ list_add_tail(&opaque_list,
+ (struct list_node *)create_opaque_blob());
+ list_add_tail(&opaque_list,
+ (struct list_node *)create_opaque_blob());
+ list_add_tail(&opaque_list,
+ (struct list_node *)create_opaque_blob());
+
+ i = 0;
+
+ list_for_each_off(&opaque_list, q, 0) {
+ i++;
+ ok1(if_blobs_know_the_secret(q));
+ }
+ ok1(i == 3);
+
+ /* Test list_for_each_safe_off, list_del_off and list_del_from_off. */
+ i = 0;
+ list_for_each_safe_off(&opaque_list, q, nq, 0) {
+ switch (i++) {
+ case 0:
+ ok1(if_blobs_know_the_secret(q));
+ list_del_off(q, 0);
+ destroy_opaque_blob(q);
+ break;
+ case 1:
+ ok1(if_blobs_know_the_secret(q));
+ list_del_from_off(&opaque_list, q, 0);
+ destroy_opaque_blob(q);
+ break;
+ case 2:
+ ok1(c == &c3);
+ list_del_from_off(&opaque_list, q, 0);
+ destroy_opaque_blob(q);
+ break;
+ }
+ ok1(list_check(&opaque_list, NULL));
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+ ok1(list_empty(&opaque_list));
+
+ /* Test list_top/list_tail/list_pop on empty list. */
ok1(list_top(&parent.children, struct child, list) == NULL);
ok1(list_tail(&parent.children, struct child, list) == NULL);
+ ok1(list_pop(&parent.children, struct child, list) == NULL);
return exit_status();
}