pvjc24/cv4/list-ops/test_list_ops.c
2024-03-13 13:37:25 +01:00

397 lines
9.9 KiB
C

#include <stdarg.h>
#include "list_ops.h"
#include "test-framework/unity.h"
static const int MAX_STRING_LEN = 100;
static list_t *list = NULL;
static list_t *list2 = NULL;
static list_t *actual = NULL;
static char *error_message = NULL;
void setUp(void)
{
}
static void release_lists(int count, ...)
{
va_list ptr;
va_start(ptr, count);
for (int i = 0; i < count; ++i) {
list_t **list = va_arg(ptr, list_t **);
if (*list) {
free(*list);
*list = NULL;
}
}
va_end(ptr);
}
void tearDown(void)
{
release_lists(3, &list, &list2, &actual);
if (error_message) {
free(error_message);
error_message = NULL;
}
}
static char *print_elements(size_t length, list_element_t list_elements[])
{
char *array = malloc(MAX_STRING_LEN * sizeof(char));
char *ptr = array;
for (size_t i = 0; i < length; i++) {
int printed = snprintf(ptr, MAX_STRING_LEN - (ptr - array), " %d ",
(list_elements[i]));
ptr += printed;
if (ptr - array > MAX_STRING_LEN) {
break;
}
}
return array;
}
static char *create_error_message(size_t length,
list_element_t expected_elements[],
list_element_t actual_elements[])
{
char *message = malloc(MAX_STRING_LEN * sizeof(char));
char *expected_string = print_elements(length, expected_elements);
char *actual_string = print_elements(length, actual_elements);
snprintf(message, MAX_STRING_LEN, "[%s] != [%s]", expected_string,
actual_string);
free(expected_string);
free(actual_string);
return message;
}
static void check_lists_match(size_t expected_length,
list_element_t expected_elements[],
list_t *actual)
{
// check actual list is a valid list
TEST_ASSERT_NOT_NULL(actual);
// check lengths match
TEST_ASSERT_EQUAL_MESSAGE(expected_length, actual->length,
"List lengths differ");
// check elements match in non-zero length list
if (expected_length) {
error_message = create_error_message(expected_length, expected_elements,
actual->elements);
TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(
expected_elements, actual->elements, sizeof(list_element_t),
expected_length, error_message);
free(error_message);
error_message = NULL;
}
}
static bool filter_modulo(list_element_t element)
{
return (element % 2 == 1);
}
static list_element_t map_increment(list_element_t element)
{
return element + 1;
}
static list_element_t fold_multiply(list_element_t element,
list_element_t accumulator)
{
return element * accumulator;
}
static list_element_t fold_add(list_element_t element,
list_element_t accumulator)
{
return element + accumulator;
}
static list_element_t fold_divide(list_element_t element,
list_element_t accumulator)
{
return (accumulator == 0) ? 0 : element / accumulator;
}
static void call_delete_list(list_t **list)
{
delete_list(*list);
*list = NULL;
}
static void test_append_empty_lists(void)
{
list = new_list(0, NULL);
list2 = new_list(0, NULL);
actual = append_list(list, list2);
check_lists_match(0, NULL, actual);
call_delete_list(&list);
call_delete_list(&list2);
call_delete_list(&actual);
}
static void test_append_list_to_empty_list(void)
{
TEST_IGNORE(); // delete this line to run test
list = new_list(0, NULL);
list2 = new_list(3, (list_element_t[]){ 1, 3, 4 });
size_t expected_length = 3;
list_element_t expected_elements[] = { 1, 3, 4 };
actual = append_list(list, list2);
check_lists_match(expected_length, expected_elements, actual);
call_delete_list(&list);
call_delete_list(&list2);
call_delete_list(&actual);
}
static void test_append_empty_list_to_list(void)
{
TEST_IGNORE();
list = new_list(4, (list_element_t[]){ 1, 2, 3, 4 });
list2 = new_list(0, NULL);
size_t expected_length = 4;
list_element_t expected_elements[] = { 1, 2, 3, 4 };
actual = append_list(list, list2);
check_lists_match(expected_length, expected_elements, actual);
call_delete_list(&list);
call_delete_list(&list2);
call_delete_list(&actual);
}
static void test_append_non_empty_lists(void)
{
TEST_IGNORE();
list = new_list(2, (list_element_t[]){ 1, 2 });
list2 = new_list(4, (list_element_t[]){ 2, 3, 4, 5 });
size_t expected_length = 6;
list_element_t expected_elements[] = { 1, 2, 2, 3, 4, 5 };
actual = append_list(list, list2);
check_lists_match(expected_length, expected_elements, actual);
call_delete_list(&list);
call_delete_list(&list2);
call_delete_list(&actual);
}
static void test_filter_empty_list(void)
{
TEST_IGNORE();
list = new_list(0, NULL);
actual = filter_list(list, filter_modulo);
check_lists_match(0, NULL, actual);
call_delete_list(&list);
call_delete_list(&actual);
}
static void test_filter_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(5, (list_element_t[]){ 1, 2, 3, 4, 5 });
size_t expected_length = 3;
list_element_t expected_elements[] = { 1, 3, 5 };
actual = filter_list(list, filter_modulo);
check_lists_match(expected_length, expected_elements, actual);
call_delete_list(&list);
call_delete_list(&actual);
}
static void test_length_empty_list(void)
{
TEST_IGNORE();
list = new_list(0, NULL);
size_t expected = 0;
size_t actual = length_list(list);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void test_length_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(4, (list_element_t[]){ 1, 2, 3, 4 });
size_t expected = 4;
size_t actual = length_list(list);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void test_map_empty_list(void)
{
TEST_IGNORE();
list = new_list(0, NULL);
actual = map_list(list, map_increment);
check_lists_match(0, NULL, actual);
call_delete_list(&list);
call_delete_list(&actual);
}
static void test_map_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(4, (list_element_t[]){ 1, 3, 5, 7 });
size_t expected_length = 4;
list_element_t expected_elements[] = { 2, 4, 6, 8 };
actual = map_list(list, map_increment);
check_lists_match(expected_length, expected_elements, actual);
call_delete_list(&list);
call_delete_list(&actual);
}
static void test_foldl_empty_list(void)
{
TEST_IGNORE();
list = new_list(0, NULL);
list_element_t initial = 2;
list_element_t expected = 2;
list_element_t actual = foldl_list(list, initial, fold_divide);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void
test_foldl_direction_independent_function_applied_to_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(4, (list_element_t[]){ 1, 2, 3, 4 });
list_element_t initial = 5;
list_element_t expected = 15;
list_element_t actual = foldl_list(list, initial, fold_add);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void
test_foldl_direction_dependent_function_applied_to_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(2, (list_element_t[]){ 2, 5 });
list_element_t initial = 5;
list_element_t expected = 0;
list_element_t actual = foldl_list(list, initial, fold_divide);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void test_foldr_empty_list(void)
{
TEST_IGNORE();
list = new_list(0, NULL);
list_element_t initial = 2;
list_element_t expected = 2;
list_element_t actual = foldr_list(list, initial, fold_multiply);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void
test_foldr_direction_independent_function_applied_to_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(4, (list_element_t[]){ 1, 2, 3, 4 });
list_element_t initial = 5;
list_element_t expected = 15;
list_element_t actual = foldr_list(list, initial, fold_add);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void
test_foldr_direction_dependent_function_applied_to_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(2, (list_element_t[]){ 2, 5 });
list_element_t initial = 5;
list_element_t expected = 2;
list_element_t actual = foldr_list(list, initial, fold_divide);
TEST_ASSERT_EQUAL(expected, actual);
call_delete_list(&list);
}
static void test_reverse_empty_list(void)
{
TEST_IGNORE();
list = new_list(0, NULL);
actual = reverse_list(list);
check_lists_match(0, NULL, actual);
call_delete_list(&list);
call_delete_list(&actual);
}
static void test_reverse_non_empty_list(void)
{
TEST_IGNORE();
list = new_list(4, (list_element_t[]){ 1, 3, 5, 7 });
size_t expected_length = 4;
list_element_t expected_elements[] = { 7, 5, 3, 1 };
actual = reverse_list(list);
check_lists_match(expected_length, expected_elements, actual);
call_delete_list(&list);
call_delete_list(&actual);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_append_empty_lists);
RUN_TEST(test_append_list_to_empty_list);
RUN_TEST(test_append_empty_list_to_list);
RUN_TEST(test_append_non_empty_lists);
RUN_TEST(test_filter_empty_list);
RUN_TEST(test_filter_non_empty_list);
RUN_TEST(test_length_empty_list);
RUN_TEST(test_length_non_empty_list);
RUN_TEST(test_map_empty_list);
RUN_TEST(test_map_non_empty_list);
RUN_TEST(test_foldl_empty_list);
RUN_TEST(
test_foldl_direction_independent_function_applied_to_non_empty_list);
RUN_TEST(test_foldl_direction_dependent_function_applied_to_non_empty_list);
RUN_TEST(test_foldr_empty_list);
RUN_TEST(
test_foldr_direction_independent_function_applied_to_non_empty_list);
RUN_TEST(test_foldr_direction_dependent_function_applied_to_non_empty_list);
RUN_TEST(test_reverse_empty_list);
RUN_TEST(test_reverse_non_empty_list);
return UNITY_END();
}