diff --git a/include/neo/list.h b/include/neo/list.h index 7c0af72..6c1462c 100644 --- a/include/neo/list.h +++ b/include/neo/list.h @@ -129,8 +129,10 @@ void list_insert_before(listnode_t *pos, listnode_t *new_node); * @param member: Name of the `listnode_t` member embedded within `cursor` */ #define list_foreach_reverse(cursor, list, member) \ - for (cursor = _neo_list_last( list, typeof(*(cursor)), member ), \ - __tmp = _neo_list_prev(cursor, member); \ + for (typeof(cursor) __tmp = _neo_list_prev( \ + cursor = _neo_list_last( list, typeof(*(cursor)), member ), \ + member \ + ); \ !_neo_list_is_root(cursor, list, member); \ cursor = __tmp, __tmp = _neo_list_prev(__tmp, member)) diff --git a/test/list.cpp b/test/list.cpp new file mode 100644 index 0000000..4dc6204 --- /dev/null +++ b/test/list.cpp @@ -0,0 +1,197 @@ +/** See the end of this file for copyright and license terms. */ + +#include +#include + +#include +#include + +extern "C" struct list_test { + int number; + /* link is not at the beginning to ensure offsets are subtracted */ + listnode_t link; +}; + +SCENARIO( "list: items can be added and removed", "[src/list.c]" ) +{ + GIVEN( "list is initialized" ) + { + list_t list = { + ._len = 0, + }; + list_init(&list); + + REQUIRE( nlen(&list) == 0 ); + + WHEN( "one item is added" ) + { + struct list_test item1 = { + .number = 1, + }; + list_add(&list, &item1.link); + + THEN( "item is in the list" ) + { + REQUIRE( nlen(&list) == 1 ); + struct list_test *cursor; + int iterations = 0; + list_foreach(cursor, &list, link) { + iterations++; + REQUIRE( cursor == &item1 ); + REQUIRE( cursor->number == 1 ); + } + REQUIRE( iterations == 1 ); + } + + WHEN( "item is removed again" ) + { + list_del(&item1.link); + + THEN( "list is empty" ) + { + REQUIRE( nlen(&list) == 0 ); + struct list_test *cursor; + int iterations = 0; + list_foreach(cursor, &list, link) { + iterations++; + } + REQUIRE( iterations == 0 ); + } + } + + WHEN( "another item is added" ) + { + struct list_test item2 = { + .number = 2, + }; + list_add(&list, &item2.link); + + THEN( "new item is in position 2") + { + REQUIRE( nlen(&list) == 2 ); + struct list_test *cursor; + int iterations = 0; + list_foreach(cursor, &list, link) { + iterations++; + REQUIRE( cursor->number == iterations ); + } + REQUIRE( iterations == 2 ); + } + } + } + } +} + +SCENARIO( "list: items are inserted at the right position", "[src/list.c]" ) +{ + GIVEN( "list is initialized and populated" ) + { + list_t list = { + /* required because C++ i think */ + ._len = 0, + }; + list_init(&list); + + REQUIRE( nlen(&list) == 0 ); + + struct list_test item1 = { + .number = 1, + }; + list_add(&list, &item1.link); + struct list_test item2 = { + .number = 2, + }; + list_add(&list, &item2.link); + + WHEN( "item is added at the end" ) + { + struct list_test item3 = { + .number = 3, + }; + list_add(&list, &item3.link); + + THEN( "item is at the end" ) + { + struct list_test *cursor; + int number = 0; + list_foreach(cursor, &list, link) { + number++; + REQUIRE( cursor->number == number ); + } + REQUIRE( number == 3 ); + } + } + + WHEN( "item is added at the beginning" ) + { + struct list_test item0 = { + .number = 0, + }; + list_add_first(&list, &item0.link); + + THEN( "item is at the beginning" ) + { + struct list_test *cursor; + int number = -1; + list_foreach(cursor, &list, link) { + number++; + REQUIRE( cursor->number == number ); + } + REQUIRE( number == 2 ); + } + } + + WHEN( "item is inserted after position 1" ) + { + struct list_test item11 = { + .number = 11, + }; + list_insert(&item1.link, &item11.link); + + THEN( "item is at position 2" ) + { + struct list_test *cursor; + int i = 0; + static const int numbers[] = { 1, 11, 2 }; + list_foreach(cursor, &list, link) { + REQUIRE( cursor->number == numbers[i] ); + i++; + } + REQUIRE( i == 3 ); + } + } + + WHEN( "item is inserted before position 2" ) + { + struct list_test item11 = { + .number = 11, + }; + list_insert_before(&item2.link, &item11.link); + + THEN( "item is at position 2" ) + { + struct list_test *cursor; + int i = 0; + static const int numbers[] = { 1, 11, 2 }; + list_foreach(cursor, &list, link) { + REQUIRE( cursor->number == numbers[i] ); + i++; + } + REQUIRE( i == 3 ); + } + } + } +} + +/* + * This file is part of libneo. + * Copyright (c) 2021 Fefie . + * + * libneo is non-violent software: you may only use, redistribute, + * and/or modify it under the terms of the CNPLv6+ as found in + * the LICENSE file in the source code root directory or at + * . + * + * libneo comes with ABSOLUTELY NO WARRANTY, to the extent + * permitted by applicable law. See the CNPLv6+ for details. + */