251 lines
6.5 KiB
C
251 lines
6.5 KiB
C
/* Include statements. */
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include "../linked_lists/single_linked_list.h"
|
|
|
|
/* Define constants. */
|
|
#define PRINT_INFO_TESTING_START "Starting tests.\n"
|
|
#define PRINT_INFO_TESTING_END "Done testing.\n"
|
|
#define ERROR_TEXT_RANDOM_LIST_FAIL_ALLOCATION "Long list test failed because of allocation errors!\n"
|
|
#define ERROR_SERIALIZATION_TEST_FAILURE "Failed the serialization test.\n"
|
|
#define SOME_TEST_FAILED "Recheck the tests, one of them failed!\n"
|
|
#define INITIAL_LIST_LENGTH 0
|
|
#define LIST_LENGTH_ONE 1
|
|
#define LIST_LENGTH_LONG_TEST 4096
|
|
#define SERIALIZATION_TEST_LIST_LENGTH 5
|
|
|
|
/* Define functions. */
|
|
node_t* generate_random_node();
|
|
linked_list_t* generate_long_random_list(int length);
|
|
static inline void set_array_value_index(void *array, size_t index, void *value);
|
|
int list_count_length(linked_list_t *list);
|
|
int test_serialization();
|
|
int test_linked_lists();
|
|
|
|
/* Starting point. */
|
|
int main() {
|
|
printf(PRINT_INFO_TESTING_START);
|
|
if (test_linked_lists()) {
|
|
printf(SOME_TEST_FAILED);
|
|
}
|
|
printf(PRINT_INFO_TESTING_END);
|
|
}
|
|
|
|
/* This function generates a random number and puts it in a newly allocated node. */
|
|
/* Caller has to free memory afterwards, returns NULL on failure. */
|
|
node_t* generate_random_node() {
|
|
/* The node to return. */
|
|
node_t* result;
|
|
int *value;
|
|
|
|
/* Attempt to allocate the node. */
|
|
result = (node_t*) malloc(sizeof(node_t));
|
|
if (result == NULL)
|
|
return NULL;
|
|
value = (int*) malloc(sizeof(int));
|
|
if (value == NULL) {
|
|
free(result);
|
|
return NULL;
|
|
}
|
|
*value = random();
|
|
|
|
/* Store and return. */
|
|
result->next = NULL;
|
|
result->data = value;
|
|
return result;
|
|
}
|
|
|
|
/* This function generates a long list with random values in the nodes, returns NULL on failures. */
|
|
/* Length denotes the length of the list. */
|
|
linked_list_t* generate_long_random_list(int length) {
|
|
/* Sanity check. */
|
|
if (length <= 0)
|
|
return NULL;
|
|
|
|
/* Variables. */
|
|
linked_list_t *list;
|
|
node_t *current;
|
|
int i;
|
|
|
|
/* Allocate the list. */
|
|
list = initialize_single_linked_list();
|
|
if (!list)
|
|
return NULL;
|
|
|
|
/* Fill the list with random nodes. */
|
|
/* First node. */
|
|
current = generate_random_node();
|
|
if (!current) {
|
|
free(list);
|
|
return NULL;
|
|
}
|
|
/* Attempt to append. */
|
|
append_node_single_linked_list(list, current);
|
|
|
|
/* Loop and add the rest. */
|
|
for (i = 1; i < length; i++) {
|
|
/* Generate and attempt to append. */
|
|
current = generate_random_node();
|
|
if (!current)
|
|
break;
|
|
append_node_single_linked_list(list, current);
|
|
}
|
|
|
|
/* Return the result. */
|
|
return list;
|
|
}
|
|
|
|
/* This function is used to set a value at an index in the array. */
|
|
static inline void set_array_value_index(void *array, size_t index, void *value) {
|
|
/* Cast. */
|
|
int *arr = (int*)array;
|
|
int *val = (int*)value;
|
|
/* Set the value. */
|
|
arr[index] = *val;
|
|
}
|
|
|
|
/* This function checks the actual length of a list. */
|
|
int list_count_length(linked_list_t *list) {
|
|
if (list == NULL || list->head == NULL)
|
|
return 0;
|
|
/* Loop and count. */
|
|
node_t *current = list->head;
|
|
int count = 0;
|
|
while (current != NULL) {
|
|
count++;
|
|
current = current->next;
|
|
}
|
|
/* Return the result. */
|
|
return count;
|
|
}
|
|
|
|
/* This function attempts to allocate a list, fill it, then serialize it. */
|
|
int test_serialization() {
|
|
/* Local variables. */
|
|
int i;
|
|
size_t length;
|
|
/* Used to allocate and store a value. */
|
|
int *value, *array;
|
|
|
|
/* Allocations. */
|
|
/* Initialize the list. */
|
|
linked_list_t *list = initialize_single_linked_list();
|
|
if (!list)
|
|
return 1;
|
|
|
|
/* Allocate the array. */
|
|
array = (int*) malloc(sizeof(int) * SERIALIZATION_TEST_LIST_LENGTH);
|
|
if (!array) {
|
|
free(list);
|
|
return 1;
|
|
}
|
|
|
|
/* Fill the list. */
|
|
for (i = 0; i < SERIALIZATION_TEST_LIST_LENGTH; i++) {
|
|
/* Allocate the value store. */
|
|
value = (int*) malloc(sizeof(int));
|
|
if (!value) {
|
|
/* Clear the list. */
|
|
clear_list_data_single_linked_list(&list, NULL);
|
|
/* Free the array. */
|
|
free(array);
|
|
/* Failed the test, technical reasons. */
|
|
return 1;
|
|
}
|
|
/* Set the value. */
|
|
*value = i;
|
|
/* Append into the list. */
|
|
append_node_data_single_linked_list(list, value);
|
|
}
|
|
|
|
/* Serialize the list and check if the serialization failed. */
|
|
if (!serialize_linked_list(list, set_array_value_index, array)) {
|
|
/* Clear the list. */
|
|
clear_list_data_single_linked_list(&list, NULL);
|
|
/* Free the array. */
|
|
free(array);
|
|
/* Failed the test. */
|
|
return 0;
|
|
}
|
|
|
|
/* Check the values. */
|
|
for (i = 0; i < SERIALIZATION_TEST_LIST_LENGTH; i++) {
|
|
if (array[i] != i) {
|
|
/* Clear the list. */
|
|
clear_list_data_single_linked_list(&list, NULL);
|
|
/* Free the array. */
|
|
free(array);
|
|
/* Failed the test. */
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* Passed the tests. */
|
|
/* Clear the list. */
|
|
clear_list_data_single_linked_list(&list, NULL);
|
|
/* Free the array. */
|
|
free(array);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* This function does the testing. */
|
|
int test_linked_lists() {
|
|
/* Local variables. */
|
|
linked_list_t *list;
|
|
node_t *node, *tail;
|
|
|
|
/* Initialize an empty list. */
|
|
list = initialize_single_linked_list();
|
|
/* Check that it was correctly created. */
|
|
assert(list != NULL);
|
|
assert(list->length == INITIAL_LIST_LENGTH);
|
|
assert(list->head == NULL);
|
|
|
|
/* Generate and store the node. */
|
|
node = generate_random_node();
|
|
|
|
/* Attempt to add it to the list. */
|
|
append_node_single_linked_list(list, node);
|
|
/* Check that the list grew and the head got set. */
|
|
assert(list->length == LIST_LENGTH_ONE);
|
|
assert(list->head != NULL && list->head == node);
|
|
assert(get_node_i_single_linked_list(list, 0) == node);
|
|
assert(get_node_index_pointer_single_linked_list(list, node) == 0);
|
|
|
|
/* Attempt to free the nodes and then the list. */
|
|
remove_node_i_data_single_linked_list(list, 0, NULL);
|
|
assert(list->length == INITIAL_LIST_LENGTH);
|
|
assert(list->head == NULL);
|
|
node = NULL;
|
|
free(list);
|
|
list = NULL;
|
|
|
|
/* Attempt to allocate a long list. */
|
|
list = generate_long_random_list(LIST_LENGTH_LONG_TEST);
|
|
if (list == NULL) {
|
|
printf(ERROR_TEXT_RANDOM_LIST_FAIL_ALLOCATION);
|
|
return 1;
|
|
}
|
|
assert(list->length == LIST_LENGTH_LONG_TEST);
|
|
assert(list->length == list_count_length(list));
|
|
/* Test the get head/tail functions. */
|
|
assert(get_node_head_single_linked_list(list) == list->head);
|
|
tail = get_node_tail_single_linked_list(list);
|
|
assert(tail != NULL && tail->next == NULL);
|
|
/* Test the indexer functions. */
|
|
assert(get_node_index_pointer_single_linked_list(list, tail) == (list->length - 1));
|
|
/* Test the freeing functions. */
|
|
clear_list_data_single_linked_list(&list, NULL);
|
|
assert(list == NULL);
|
|
|
|
/* Serialization test. */
|
|
if (!test_serialization()) {
|
|
printf(ERROR_SERIALIZATION_TEST_FAILURE);
|
|
return 1;
|
|
}
|
|
|
|
/* Ran successfully, return 0. */
|
|
return 0;
|
|
}
|