e0cffab768
* Introduce indexed list implementation * Fix CI tests for pool * Take bitset out of pool * Replace joker bitset interactions with wrappers * Add bitset tests * Add test to gitignore --------- Co-authored-by: rfehr-idexx <ric-fehr@idexx.com>
308 lines
8.5 KiB
C
308 lines
8.5 KiB
C
#include "list.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
// As simple as it gets, just needs to be initialized correctly
|
|
// - list_create
|
|
// - list_is_empty
|
|
// - list_get_len
|
|
// - list_clear
|
|
void create_and_clear_list(void)
|
|
{
|
|
List my_cool_list = list_create();
|
|
|
|
// verify no data
|
|
assert(my_cool_list.head == NULL);
|
|
assert(my_cool_list.tail == NULL);
|
|
assert(list_get_len(&my_cool_list) == 0);
|
|
assert(list_is_empty(&my_cool_list));
|
|
|
|
list_clear(&my_cool_list);
|
|
|
|
assert(list_is_empty(&my_cool_list));
|
|
}
|
|
|
|
// Push back one entry, make sure it looks as expected
|
|
// tests:
|
|
// - list_create
|
|
// - list_push_back
|
|
// - list_is_empty
|
|
// - list_get_len
|
|
// - list_get_at_idx
|
|
// - list_clear
|
|
void push_back_one_entry(void)
|
|
{
|
|
List my_cool_list = list_create();
|
|
|
|
// verify no data
|
|
assert(my_cool_list.head == NULL);
|
|
assert(my_cool_list.tail == NULL);
|
|
assert(list_get_len(&my_cool_list) == 0);
|
|
assert(list_is_empty(&my_cool_list));
|
|
|
|
int test_data = 1337;
|
|
|
|
list_push_back(&my_cool_list, &test_data);
|
|
|
|
// should have data and be the same head/tail
|
|
assert(my_cool_list.head != NULL);
|
|
assert(my_cool_list.tail != NULL);
|
|
assert(my_cool_list.head == my_cool_list.tail);
|
|
assert(list_get_len(&my_cool_list) == 1);
|
|
|
|
// pointer should be the same
|
|
assert(my_cool_list.head->data == &test_data);
|
|
// and consequently the value should be the same
|
|
assert(*(int*)(my_cool_list.head->data) == test_data);
|
|
assert(list_get_at_idx(&my_cool_list, 0) == &test_data);
|
|
assert(list_get_at_idx(&my_cool_list, 1) == NULL);
|
|
assert(!list_is_empty(&my_cool_list));
|
|
// clear the list
|
|
list_clear(&my_cool_list);
|
|
|
|
// verify no data
|
|
assert(my_cool_list.head == NULL);
|
|
assert(my_cool_list.tail == NULL);
|
|
assert(list_is_empty(&my_cool_list));
|
|
}
|
|
|
|
// Push front one entry, make sure it looks as expected
|
|
// - list_create
|
|
// - list_push_front
|
|
// - list_is_empty
|
|
// - list_get_len
|
|
// - list_get_at_idx
|
|
// - list_clear
|
|
void push_front_one_entry(void)
|
|
{
|
|
List my_cool_list = list_create();
|
|
|
|
// verify no data
|
|
assert(my_cool_list.head == NULL);
|
|
assert(my_cool_list.tail == NULL);
|
|
assert(list_get_len(&my_cool_list) == 0);
|
|
assert(list_is_empty(&my_cool_list));
|
|
|
|
int test_data = 1337;
|
|
|
|
list_push_front(&my_cool_list, &test_data);
|
|
|
|
// should have data and be the same head/tail
|
|
assert(my_cool_list.head != NULL);
|
|
assert(my_cool_list.tail != NULL);
|
|
assert(my_cool_list.head == my_cool_list.tail);
|
|
assert(list_get_len(&my_cool_list) == 1);
|
|
assert(!list_is_empty(&my_cool_list));
|
|
|
|
// pointer should be the same
|
|
assert(my_cool_list.head->data == &test_data);
|
|
// and consequently the value should be the same
|
|
assert(*(int*)(my_cool_list.head->data) == test_data);
|
|
assert(list_get_at_idx(&my_cool_list, 0) == &test_data);
|
|
assert(list_get_at_idx(&my_cool_list, 1) == NULL);
|
|
// clear the list
|
|
list_clear(&my_cool_list);
|
|
|
|
// verify no data
|
|
assert(my_cool_list.head == NULL);
|
|
assert(my_cool_list.tail == NULL);
|
|
assert(list_is_empty(&my_cool_list));
|
|
}
|
|
|
|
// This is meant to be a full test of every function including the use of
|
|
// the ListItr iterator
|
|
//
|
|
// Push back three entries. To cover the 3 states of nodes outside of single node
|
|
// lists. 3 states being, node at the front, node at the middle, and node at the end
|
|
//
|
|
// Afterwards remove one entry with `list_remove_at_idx` and then remove another
|
|
// with `list_remove_node`
|
|
//
|
|
// Lastly, push to the front the same 3 entries and verify the state of the list
|
|
// before detroying.
|
|
//
|
|
// - list_create
|
|
// - list_push_front
|
|
// - list_is_empty
|
|
// - list_get_len
|
|
// - list_get_at_idx
|
|
// - list_remove_at_idx
|
|
// - list_itr_create
|
|
// - list_itr_next
|
|
// - list_clear
|
|
// - list_itr_remove_node_current;
|
|
void push_back_three_remove_push_front_three_entries(void)
|
|
{
|
|
List my_cool_list = list_create();
|
|
|
|
// verify no data
|
|
assert(my_cool_list.head == NULL);
|
|
assert(my_cool_list.tail == NULL);
|
|
|
|
int test_data[3] = {0, 1, 2};
|
|
|
|
list_push_back(&my_cool_list, &test_data[0]);
|
|
|
|
// Make sure with one entry it looks right
|
|
assert(my_cool_list.head == my_cool_list.tail);
|
|
|
|
list_push_back(&my_cool_list, &test_data[1]);
|
|
|
|
// Now with two it should be different
|
|
assert(my_cool_list.head != my_cool_list.tail);
|
|
|
|
list_push_back(&my_cool_list, &test_data[2]);
|
|
|
|
// 3 entries?
|
|
assert(list_get_len(&my_cool_list) == 3);
|
|
|
|
// now use an iterator to examine each node
|
|
int* data;
|
|
|
|
ListItr list_itr = list_itr_create(&my_cool_list);
|
|
|
|
int itr = 0;
|
|
|
|
ListNode* prev_ln = NULL;
|
|
|
|
while((data = list_itr_next(&list_itr)))
|
|
{
|
|
assert(data != NULL);
|
|
assert(data == &test_data[itr]);
|
|
ListNode* ln = list_itr.current_node;
|
|
switch(itr)
|
|
{
|
|
case 0:
|
|
assert(ln->prev == NULL);
|
|
assert(ln->next != NULL);
|
|
assert(ln->next->prev == ln);
|
|
break;
|
|
case 1:
|
|
assert(ln->prev == prev_ln);
|
|
assert(ln->prev != NULL);
|
|
assert(ln->next != NULL);
|
|
assert(ln->next->prev == ln);
|
|
assert(ln->prev->next == ln);
|
|
break;
|
|
case 2:
|
|
assert(ln->prev != NULL);
|
|
assert(ln->next == NULL);
|
|
assert(ln->prev->next == ln);
|
|
assert(ln->prev == prev_ln);
|
|
break;
|
|
default:
|
|
assert(false); // shouldn't get here
|
|
break;
|
|
}
|
|
itr++;
|
|
prev_ln = ln;
|
|
}
|
|
|
|
// remove the middle entry
|
|
assert(list_remove_at_idx(&my_cool_list, 1));
|
|
// can't remove entry 2 now (doesn't exist)
|
|
assert(!list_remove_at_idx(&my_cool_list, 2));
|
|
assert(list_get_len(&my_cool_list) == 2);
|
|
|
|
list_itr = list_itr_create(&my_cool_list);
|
|
data = NULL;
|
|
itr = 0;
|
|
prev_ln = NULL;
|
|
while((data = list_itr_next(&list_itr)))
|
|
{
|
|
assert(data != NULL);
|
|
ListNode* ln = list_itr.current_node;
|
|
switch(itr)
|
|
{
|
|
case 0:
|
|
assert(ln->prev == NULL);
|
|
assert(ln->next != NULL);
|
|
assert(ln->next->prev == ln);
|
|
break;
|
|
case 1:
|
|
assert(ln->prev != NULL);
|
|
assert(ln->next == NULL);
|
|
assert(ln->prev->next == ln);
|
|
assert(ln->prev == prev_ln);
|
|
list_itr_remove_current_node(&list_itr);
|
|
break;
|
|
default:
|
|
assert(false); // shouldn't get here
|
|
break;
|
|
}
|
|
itr++;
|
|
prev_ln = ln;
|
|
}
|
|
|
|
assert(list_get_len(&my_cool_list) == 1);
|
|
assert(my_cool_list.head == my_cool_list.tail);
|
|
|
|
// now push the same 3 pointers to the front of the list
|
|
list_push_front(&my_cool_list, &test_data[0]);
|
|
list_push_front(&my_cool_list, &test_data[1]);
|
|
list_push_front(&my_cool_list, &test_data[2]);
|
|
|
|
// now, the list should be in the order...
|
|
// test_data[2] -> test_data[1] -> test_data[0] -> test_data[0]
|
|
list_itr = list_itr_create(&my_cool_list);
|
|
data = NULL;
|
|
itr = 0;
|
|
while((data = list_itr_next(&list_itr)))
|
|
{
|
|
assert(data != NULL);
|
|
ListNode* ln = list_itr.current_node;
|
|
|
|
switch(itr)
|
|
{
|
|
case 0:
|
|
assert(ln->data == &test_data[2]);
|
|
break;
|
|
case 1:
|
|
assert(ln->data == &test_data[1]);
|
|
break;
|
|
case 2:
|
|
assert(ln->data == &test_data[0]);
|
|
break;
|
|
case 3:
|
|
assert(ln->data == &test_data[0]);
|
|
break;
|
|
default:
|
|
assert(false); // shouldn't get here
|
|
break;
|
|
}
|
|
itr++;
|
|
}
|
|
|
|
assert(list_get_len(&my_cool_list) == 4);
|
|
|
|
// clear the list
|
|
list_clear(&my_cool_list);
|
|
|
|
// verify no data
|
|
assert(my_cool_list.head == NULL);
|
|
assert(my_cool_list.tail == NULL);
|
|
assert(list_is_empty(&my_cool_list));
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
printf("Testing List Create and Clear.\n");
|
|
create_and_clear_list();
|
|
|
|
printf("Testing List Push Back.\n");
|
|
push_back_one_entry();
|
|
|
|
printf("Testing List Push Front.\n");
|
|
push_front_one_entry();
|
|
printf("Testing List Complete Exercise.\n");
|
|
push_back_three_remove_push_front_three_entries();
|
|
|
|
printf("-------------------------------------------------------------------------------\n");
|
|
printf("List Tests Passed :)\n");
|
|
printf("-------------------------------------------------------------------------------\n");
|
|
|
|
return 0;
|
|
}
|