blob: 3269b4be752077b2cb2b96c1d6de363fea444583 [file] [log] [blame]
/* libnih
*
* test_list.c - test suite for nih/list.c
*
* Copyright © 2006 Scott James Remnant <scott@netsplit.com>.
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <string.h>
#include <nih/alloc.h>
#include <nih/list.h>
int
test_init (void)
{
NihList entry;
int ret = 0;
printf ("Testing nih_list_init()\n");
nih_list_init (&entry);
/* Previous pointer should point back to itself */
if (entry.prev != &entry) {
printf ("BAD: prev pointer set incorrectly.\n");
ret = 1;
}
/* Next pointer should point back to itself */
if (entry.next != &entry) {
printf ("BAD: next pointer set incorrectly.\n");
ret = 1;
}
return ret;
}
int
test_new (void)
{
NihList *list;
int ret = 0;
printf ("Testing nih_list_new()\n");
list = nih_list_new ();
/* Previous pointer should point back to itself */
if (list->prev != list) {
printf ("BAD: prev pointer set incorrectly.\n");
ret = 1;
}
/* Next pointer should point back to itself */
if (list->next != list) {
printf ("BAD: next pointer set incorrectly.\n");
ret = 1;
}
/* Should have been allocated using nih_alloc */
if (nih_alloc_size (list) != sizeof (NihList)) {
printf ("BAD: nih_alloc was not used.\n");
ret = 1;
}
nih_free (list);
return ret;
}
int
test_add (void)
{
NihList *list, *entry1, *entry2, *ptr;
int ret = 0;
printf ("Testing nih_list_add()\n");
list = nih_list_new ();
entry1 = nih_list_new ();
entry2 = nih_list_new ();
printf ("...with single-entry list\n");
ptr = nih_list_add (list, entry1);
/* The added entry should be returned */
if (ptr != entry1) {
printf ("BAD: return value wasn't what we expected.\n");
ret = 1;
}
/* Head entry's previous pointer should be the new entry */
if (list->prev != entry1) {
printf ("BAD: head prev pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's next pointer should be the new entry too */
if (list->next != entry1) {
printf ("BAD: head next pointer set incorrectly.\n");
ret = 1;
}
/* New entry's next pointer should be the head */
if (entry1->next != list) {
printf ("BAD: entry next pointer set incorrectly.\n");
ret = 1;
}
/* New entry's previous pointer should be the head too */
if (entry1->prev != list) {
printf ("BAD: entry prev pointer set incorrectly.\n");
ret = 1;
}
printf ("...with multi-entry list\n");
nih_list_add (list, entry2);
/* Head entry's previous pointer should be the new entry */
if (list->prev != entry2) {
printf ("BAD: head prev pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's next pointer should be unchanged. */
if (list->next != entry1) {
printf ("BAD: head next pointer changed.\n");
ret = 1;
}
/* New entry's next pointer should be the head */
if (entry2->next != list) {
printf ("BAD: entry next pointer set incorrectly.\n");
ret = 1;
}
/* New entry's previous pointer should be the previous tail */
if (entry2->prev != entry1) {
printf ("BAD: entry prev pointer set incorrectly.\n");
ret = 1;
}
/* Previous tail's next pointer should be the new entry */
if (entry1->next != entry2) {
printf ("BAD: previous tail next pointer set incorrectly.\n");
ret = 1;
}
/* Previous tail's prev pointer should be unchanged. */
if (entry1->prev != list) {
printf ("BAD: previous tail prev pointer changed.\n");
ret = 1;
}
printf ("...with two entries from same list\n");
nih_list_add (entry1, entry2);
/* Head entry's next pointer should now be entry2 */
if (list->next != entry2) {
printf ("BAD: list head next pointer set incorrectly.\n");
ret = 1;
}
/* entry2's previous pointer should be the head entry */
if (entry2->prev != list) {
printf ("BAD: entry2 prev pointer set incorrectly.\n");
ret = 1;
}
/* entry2's next pointer should be entry1 */
if (entry2->next != entry1) {
printf ("BAD: entry2 next pointer set incorrectly.\n");
ret = 1;
}
/* entry1's previous pointer should be entry2 */
if (entry1->prev != entry2) {
printf ("BAD: entry1 prev pointer set incorrectly.\n");
ret = 1;
}
/* entry1's next pointer should be the head entry */
if (entry1->next != list) {
printf ("BAD: entry1 next pointer set incorrectly.\n");
ret = 1;
}
/* head entry's previous pointer should be entry1 */
if (list->prev != entry1) {
printf ("BAD: head prev pointer set incorrectly.\n");
ret = 1;
}
printf ("...with entry from other list\n");
ptr = nih_list_new ();
nih_list_add (ptr, entry2);
/* The entry should be removed from the old list, so the
* old list head entry's next pointer should point to the tail. */
if (list->next != entry1) {
printf ("BAD: old list head next pointer set incorrectly.\n");
ret = 1;
}
/* The entry should be removed from the old list, so the
* old list tail entry's prev pointer should point to the head. */
if (entry1->prev != list) {
printf ("BAD: old list tail prev pointer set incorrectly.\n");
ret = 1;
}
nih_list_free (list);
nih_list_free (entry1);
nih_list_free (entry2);
nih_list_free (ptr);
return ret;
}
int
test_add_after (void)
{
NihList *list, *entry1, *entry2, *ptr;
int ret = 0;
printf ("Testing nih_list_add_after()\n");
list = nih_list_new ();
entry1 = nih_list_new ();
entry2 = nih_list_new ();
printf ("...with single-entry list\n");
ptr = nih_list_add_after (list, entry1);
/* The added entry should be returned */
if (ptr != entry1) {
printf ("BAD: return value wasn't what we expected.\n");
ret = 1;
}
/* Head entry's next pointer should be the new entry */
if (list->next != entry1) {
printf ("BAD: head next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's previous pointer should be the new entry too */
if (list->prev != entry1) {
printf ("BAD: head prev pointer set incorrectly.\n");
ret = 1;
}
/* New entry's previous pointer should be the head */
if (entry1->prev != list) {
printf ("BAD: entry prev pointer set incorrectly.\n");
ret = 1;
}
/* New entry's next pointer should be the head too */
if (entry1->next != list) {
printf ("BAD: entry next pointer set incorrectly.\n");
ret = 1;
}
printf ("...with multi-entry list\n");
nih_list_add_after (list, entry2);
/* Head entry's next pointer should be the new entry */
if (list->next != entry2) {
printf ("BAD: head next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's previous pointer should be unchanged. */
if (list->prev != entry1) {
printf ("BAD: head prev pointer changed.\n");
ret = 1;
}
/* New entry's previous pointer should be the head */
if (entry2->prev != list) {
printf ("BAD: entry prev pointer set incorrectly.\n");
ret = 1;
}
/* New entry's next pointer should be the tail */
if (entry2->next != entry1) {
printf ("BAD: entry next pointer set incorrectly.\n");
ret = 1;
}
/* Tail entry's prev pointer should be the new entry */
if (entry1->prev != entry2) {
printf ("BAD: tail prev pointer set incorrectly.\n");
ret = 1;
}
/* Tail entry's next pointer should be unchanged. */
if (entry1->next != list) {
printf ("BAD: tail next pointer changed.\n");
ret = 1;
}
printf ("...with two entries from same list\n");
nih_list_add_after (entry1, entry2);
/* Head entry's next pointer should now be entry1 */
if (list->next != entry1) {
printf ("BAD: list head next pointer set incorrectly.\n");
ret = 1;
}
/* entry1's previous pointer should be the head entry */
if (entry1->prev != list) {
printf ("BAD: entry1 prev pointer set incorrectly.\n");
ret = 1;
}
/* entry1's next pointer should be entry2 */
if (entry1->next != entry2) {
printf ("BAD: entry1 next pointer set incorrectly.\n");
ret = 1;
}
/* entry2's previous pointer should be entry1 */
if (entry2->prev != entry1) {
printf ("BAD: entry2 prev pointer set incorrectly.\n");
ret = 1;
}
/* entry2's next pointer should be the head entry */
if (entry2->next != list) {
printf ("BAD: entry2 next pointer set incorrectly.\n");
ret = 1;
}
/* head entry's previous pointer should be entry2 */
if (list->prev != entry2) {
printf ("BAD: head prev pointer set incorrectly.\n");
ret = 1;
}
printf ("...with entry from other list\n");
ptr = nih_list_new ();
nih_list_add_after (ptr, entry1);
/* The entry should be removed from the old list, so the
* old list head entry's next pointer should point to the tail. */
if (list->next != entry2) {
printf ("BAD: old list head next pointer set incorrectly.\n");
ret = 1;
}
/* The entry should be removed from the old list, so the
* old list tail entry's prev pointer should point to the head. */
if (entry2->prev != list) {
printf ("BAD: old list tail prev pointer set incorrectly.\n");
ret = 1;
}
nih_free (list);
nih_free (entry1);
nih_free (entry2);
nih_free (ptr);
return ret;
}
int
test_empty (void)
{
NihList *list, *entry;
int ret = 0;
printf ("Testing NIH_LIST_EMPTY()\n");
list = nih_list_new ();
entry = nih_list_new ();
printf ("...with empty list\n");
/* The list should be empty */
if (! NIH_LIST_EMPTY (list)) {
printf ("BAD: return value wasn't what we expected.\n");
ret = 1;
}
printf ("...with non-empty list\n");
nih_list_add (list, entry);
/* The list should not be empty */
if (NIH_LIST_EMPTY (list)) {
printf ("BAD: return value wasn't what we expected.\n");
ret = 1;
}
/* Check that's true for the entry too */
if (NIH_LIST_EMPTY (entry)) {
printf ("BAD: return value wasn't what we expected.\n");
ret = 1;
}
nih_free (list);
nih_free (entry);
return ret;
}
int
test_foreach (void)
{
NihList *list, *entry[3];
int i, ret = 0;
printf ("Testing NIH_LIST_FOREACH()\n");
list = nih_list_new ();
entry[0] = nih_list_add (list, nih_list_new ());
entry[1] = nih_list_add (list, nih_list_new ());
entry[2] = nih_list_add (list, nih_list_new ());
/* Perform a test iteration */
i = 0;
NIH_LIST_FOREACH (list, iter) {
if (i > 2) {
printf ("BAD: more iterations than expected.\n");
ret = 1;
break;
}
if (iter != entry[i]) {
printf ("BAD: iteration not entry we expected.\n");
ret = 1;
}
i++;
}
nih_free (list);
nih_free (entry[0]);
nih_free (entry[1]);
nih_free (entry[2]);
return ret;
}
int
test_foreach_safe (void)
{
NihList *list, *entry[3];
int i, ret = 0;
printf ("Testing NIH_LIST_FOREACH_SAFE()\n");
list = nih_list_new ();
entry[0] = nih_list_add (list, nih_list_new ());
entry[1] = nih_list_add (list, nih_list_new ());
entry[2] = nih_list_add (list, nih_list_new ());
/* Perform a test iteration */
i = 0;
NIH_LIST_FOREACH_SAFE (list, iter) {
if (i > 2) {
printf ("BAD: more iterations than expected.\n");
ret = 1;
break;
}
if (iter != entry[i]) {
printf ("BAD: iteration not entry we expected.\n");
ret = 1;
}
nih_list_remove (entry[i]);
i++;
}
/* List should be empty */
if (! NIH_LIST_EMPTY (list)) {
printf ("BAD: list not empty.\n");
ret = 1;
}
nih_free (list);
nih_free (entry[0]);
nih_free (entry[1]);
nih_free (entry[2]);
return ret;
}
int
test_remove (void)
{
NihList *list, *entry, *tail, *ptr;
int ret = 0;
printf ("Testing nih_list_remove()\n");
list = nih_list_new ();
entry = nih_list_add (list, nih_list_new ());
tail = nih_list_add (list, nih_list_new ());
printf ("...with two-entry list\n");
ptr = nih_list_remove (entry);
/* The entry that was removed should be returned */
if (ptr != entry) {
printf ("BAD: return value is not what we expected.\n");
ret = 1;
}
/* The previous pointer should point back to itself */
if (entry->prev != entry) {
printf ("BAD: prev pointer set incorrectly.\n");
ret = 1;
}
/* The next pointer should point back to itself */
if (entry->next != entry) {
printf ("BAD: next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's next pointer should point to the tail entry */
if (list->next != tail) {
printf ("BAD: head next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's previous pointer should still point to the tail */
if (list->prev != tail) {
printf ("BAD: head prev pointer changed.\n");
ret = 1;
}
/* Tail entry's next pointer should still point to the head */
if (tail->next != list) {
printf ("BAD: tail next pointer changed.\n");
ret = 1;
}
/* Tail entry's previous pointer should point to the head entry */
if (tail->prev != list) {
printf ("BAD: tail next pointer set incorrectly.\n");
ret = 1;
}
printf ("...with one-entry list\n");
ptr = nih_list_remove (tail);
/* The entry that was removed should be returned */
if (ptr != tail) {
printf ("BAD: return value is not what we expected.\n");
ret = 1;
}
/* The previous pointer should point back to itself */
if (tail->prev != tail) {
printf ("BAD: prev pointer set incorrectly.\n");
ret = 1;
}
/* The next pointer should point back to itself */
if (tail->next != tail) {
printf ("BAD: next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's next pointer should point back to itself */
if (list->next != list) {
printf ("BAD: head next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's previous pointer should point back to itself */
if (list->prev != list) {
printf ("BAD: head prev pointer changed.\n");
ret = 1;
}
printf ("...with empty list\n");
ptr = nih_list_remove (tail);
/* The entry that was removed should be returned */
if (ptr != tail) {
printf ("BAD: return value is not what we expected.\n");
ret = 1;
}
/* The previous pointer should still point back to itself */
if (tail->prev != tail) {
printf ("BAD: prev pointer set incorrectly.\n");
ret = 1;
}
/* The next pointer should still point back to itself */
if (tail->next != tail) {
printf ("BAD: next pointer set incorrectly.\n");
ret = 1;
}
nih_free (list);
nih_free (entry);
nih_free (tail);
return ret;
}
int
test_destructor (void)
{
NihList *list, *entry, *tail;
int ret = 0, retval;
printf ("Testing nih_list_destructor()\n");
list = nih_list_new ();
entry = nih_list_add (list, nih_list_new ());
tail = nih_list_add (list, nih_list_new ());
retval = nih_list_destructor (entry);
/* Zero should be returned */
if (retval != 0) {
printf ("BAD: return value is not what we expected.\n");
ret = 1;
}
/* Head entry's next pointer should point to the tail entry */
if (list->next != tail) {
printf ("BAD: head next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's previous pointer should still point to the tail */
if (list->prev != tail) {
printf ("BAD: head prev pointer changed.\n");
ret = 1;
}
/* Tail entry's next pointer should still point to the head */
if (tail->next != list) {
printf ("BAD: tail next pointer changed.\n");
ret = 1;
}
/* Tail entry's previous pointer should point to the head entry */
if (tail->prev != list) {
printf ("BAD: tail next pointer set incorrectly.\n");
ret = 1;
}
nih_free (entry);
nih_free (list);
nih_free (tail);
return ret;
}
static int was_called;
static int
destructor_called (void *ptr)
{
was_called++;
return 0;
}
static int
test_free (void)
{
NihList *list, *entry, *tail;
int ret = 0;
list = nih_list_new ();
entry = nih_list_add (list, nih_list_new ());
tail = nih_list_add (list, nih_list_new ());
printf ("Testing nih_list_free()\n");
nih_alloc_set_destructor (entry, destructor_called);
nih_list_free (entry);
/* Destructor should have been called */
if (! was_called) {
printf ("BAD: destructor was not called.\n");
ret = 1;
}
/* Head entry's next pointer should point to the tail entry */
if (list->next != tail) {
printf ("BAD: head next pointer set incorrectly.\n");
ret = 1;
}
/* Head entry's previous pointer should still point to the tail */
if (list->prev != tail) {
printf ("BAD: head prev pointer changed.\n");
ret = 1;
}
/* Tail entry's next pointer should still point to the head */
if (tail->next != list) {
printf ("BAD: tail next pointer changed.\n");
ret = 1;
}
/* Tail entry's previous pointer should point to the head entry */
if (tail->prev != list) {
printf ("BAD: tail next pointer set incorrectly.\n");
ret = 1;
}
nih_free (list);
nih_free (tail);
return ret;
}
int
main (int argc,
char *argv[])
{
int ret = 0;
ret |= test_init ();
ret |= test_new ();
ret |= test_add ();
ret |= test_add_after ();
ret |= test_empty ();
ret |= test_foreach ();
ret |= test_foreach_safe ();
ret |= test_remove ();
ret |= test_destructor ();
ret |= test_free ();
return ret;
}