mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 23:23:09 +00:00
Import the following commits from GCC as of r16-3056-gca2169c65bd169: 0d0837df697 libiberty: disable logging of list content for doubly-linked list tests
277 lines
7.5 KiB
C
277 lines
7.5 KiB
C
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "doubly-linked-list.h"
|
|
|
|
#ifndef EXIT_SUCCESS
|
|
#define EXIT_SUCCESS 0
|
|
#endif
|
|
|
|
#ifndef EXIT_FAILURE
|
|
#define EXIT_FAILURE 1
|
|
#endif
|
|
|
|
/* Implementation */
|
|
|
|
typedef int T;
|
|
|
|
typedef struct ListNodeType
|
|
{
|
|
T value;
|
|
struct ListNodeType *next;
|
|
struct ListNodeType *prev;
|
|
} ListNodeType;
|
|
|
|
ListNodeType * l_new_node (T value)
|
|
{
|
|
ListNodeType *n = malloc (sizeof (ListNodeType));
|
|
n->next = NULL;
|
|
n->prev = NULL;
|
|
n->value = value;
|
|
return n;
|
|
}
|
|
|
|
typedef struct LinkedListWrapperType
|
|
{
|
|
ListNodeType *first;
|
|
ListNodeType *last;
|
|
size_t size;
|
|
} LinkedListWrapperType;
|
|
|
|
int compare_nodes (const ListNodeType *n1, const ListNodeType *n2)
|
|
{
|
|
if (n1->value == n2->value)
|
|
return 0;
|
|
else if (n1->value < n2->value)
|
|
return -1;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
LINKED_LIST_MUTATIVE_OPS_PROTOTYPE (LinkedListWrapperType, ListNodeType, static);
|
|
LINKED_LIST_MERGE_SORT_PROTOTYPE (LinkedListWrapperType, ListNodeType, static);
|
|
|
|
LINKED_LIST_MUTATIVE_OPS_DECL (LinkedListWrapperType, ListNodeType, static)
|
|
LINKED_LIST_MERGE_SORT_DECL (LinkedListWrapperType, ListNodeType, static)
|
|
|
|
ListNodeType * find_last_node (ListNodeType *head)
|
|
{
|
|
if (head == NULL)
|
|
return NULL;
|
|
|
|
ListNodeType *n = head;
|
|
while (n->next != NULL)
|
|
n = n->next;
|
|
|
|
return n;
|
|
}
|
|
|
|
void l_print (ListNodeType *node)
|
|
{
|
|
for (ListNodeType *l = node; l != NULL; l = l->next)
|
|
printf ("%d ", l->value);
|
|
printf ("\n");
|
|
}
|
|
|
|
void l_reverse_print (ListNodeType *last_node)
|
|
{
|
|
for (ListNodeType *l = last_node; l != NULL; l = l->prev)
|
|
printf ("%d ", l->value);
|
|
printf ("\n");
|
|
}
|
|
|
|
struct test_data_t
|
|
{
|
|
T const *content;
|
|
size_t size;
|
|
};
|
|
|
|
bool run_test (const struct test_data_t *expect,
|
|
LinkedListWrapperType *current,
|
|
bool reversed)
|
|
{
|
|
ListNodeType *node = (reversed) ? current->last : current->first;
|
|
bool passed = true;
|
|
for (int i=0; i<expect->size && node != NULL; ++i)
|
|
{
|
|
if (reversed)
|
|
{
|
|
if (expect->content[expect->size - 1 - i] != node->value)
|
|
{
|
|
printf ("FAIL: mismatching expected (%d) VS current (%d).\n",
|
|
expect->content[expect->size - 1 - i], node->value);
|
|
passed = false;
|
|
}
|
|
if (node->prev == NULL && current->first != node)
|
|
{
|
|
printf ("FAIL: first is not matching the first node.\n");
|
|
passed = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (expect->content[i] != node->value)
|
|
{
|
|
printf ("FAIL: mismatching expected (%d) VS current (%d).\n",
|
|
expect->content[i], node->value);
|
|
passed = false;
|
|
}
|
|
if (node->next == NULL && current->last != node)
|
|
{
|
|
printf ("FAIL: last_ is not matching the last node.\n");
|
|
passed = false;
|
|
}
|
|
}
|
|
|
|
if (!passed)
|
|
return false;
|
|
|
|
if (reversed)
|
|
node = node->prev;
|
|
else
|
|
node = node->next;
|
|
}
|
|
|
|
if (node != NULL)
|
|
{
|
|
printf ("FAIL: the list is longer than expected.\n");
|
|
passed = false;
|
|
}
|
|
if (expect->size != current->size)
|
|
{
|
|
printf ("FAIL: size (%ld) is not matching the real size of the list (%ld).\n",
|
|
current->size, expect->size);
|
|
passed = false;
|
|
}
|
|
|
|
return passed;
|
|
}
|
|
|
|
bool check(const char *op,
|
|
const struct test_data_t *expect,
|
|
LinkedListWrapperType *wrapper)
|
|
{
|
|
bool success = true;
|
|
bool res;
|
|
|
|
#define DUMP_LIST 0
|
|
|
|
if (DUMP_LIST)
|
|
l_print (wrapper->first);
|
|
|
|
res = run_test (expect, wrapper, false);
|
|
printf ("%s: test-linked-list::%s: check forward conformity\n",
|
|
res ? "PASS": "FAIL", op);
|
|
success &= res;
|
|
|
|
if (DUMP_LIST)
|
|
l_reverse_print (wrapper->last);
|
|
|
|
res = run_test (expect, wrapper, true);
|
|
printf ("%s: test-linked-list::%s: check backward conformity\n",
|
|
res ? "PASS": "FAIL", op);
|
|
success &= res;
|
|
|
|
if (DUMP_LIST)
|
|
printf("\n");
|
|
|
|
return success;
|
|
}
|
|
|
|
const int EXPECT_0 [] = { 10, 4, 3, 1, 9, 2 };
|
|
const int EXPECT_1 [] = { 1, 2, 3, 4, 9, 10 };
|
|
const int EXPECT_2 [] = { 11, 1, 2, 3, 4, 9, 10 };
|
|
const int EXPECT_3 [] = { 11, 1, 2, 3, 4, 9, 8, 10 };
|
|
const int EXPECT_4 [] = { 11, 2, 3, 4, 9, 8, 10 };
|
|
const int EXPECT_5 [] = { 10, 2, 3, 4, 9, 8, 11 };
|
|
const int EXPECT_6 [] = { 10, 3, 2, 4, 9, 8, 11 };
|
|
const int EXPECT_7 [] = { 10, 9, 2, 4, 3, 8, 11 };
|
|
const int EXPECT_8 [] = { 2, 3, 4, 8, 9, 10, 11 };
|
|
const int EXPECT_9 [] = { 3, 4, 8, 9, 10, 11 };
|
|
const int EXPECT_10 [] = { 3, 4, 8, 9, 10 };
|
|
const struct test_data_t test_data[] = {
|
|
{ .content = EXPECT_0, .size = sizeof(EXPECT_0) / sizeof(EXPECT_0[0]) },
|
|
{ .content = EXPECT_1, .size = sizeof(EXPECT_1) / sizeof(EXPECT_1[0]) },
|
|
{ .content = EXPECT_2, .size = sizeof(EXPECT_2) / sizeof(EXPECT_2[0]) },
|
|
{ .content = EXPECT_3, .size = sizeof(EXPECT_3) / sizeof(EXPECT_3[0]) },
|
|
{ .content = EXPECT_4, .size = sizeof(EXPECT_4) / sizeof(EXPECT_4[0]) },
|
|
{ .content = EXPECT_5, .size = sizeof(EXPECT_5) / sizeof(EXPECT_5[0]) },
|
|
{ .content = EXPECT_6, .size = sizeof(EXPECT_6) / sizeof(EXPECT_6[0]) },
|
|
{ .content = EXPECT_7, .size = sizeof(EXPECT_7) / sizeof(EXPECT_7[0]) },
|
|
{ .content = EXPECT_8, .size = sizeof(EXPECT_8) / sizeof(EXPECT_8[0]) },
|
|
{ .content = EXPECT_9, .size = sizeof(EXPECT_9) / sizeof(EXPECT_9[0]) },
|
|
{ .content = EXPECT_10, .size = sizeof(EXPECT_10) / sizeof(EXPECT_10[0]) },
|
|
};
|
|
|
|
int main (void)
|
|
{
|
|
int failures = 0;
|
|
|
|
LinkedListWrapperType wrapper = {
|
|
.first = NULL,
|
|
.last = NULL,
|
|
.size = 0,
|
|
};
|
|
|
|
/* Append nodes. */
|
|
LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (10));
|
|
LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (4));
|
|
LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (3));
|
|
LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (1));
|
|
LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (9));
|
|
LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (2));
|
|
|
|
failures += ! check ("append", &test_data[0], &wrapper);
|
|
|
|
/* Sort nodes (without updating wrapper). */
|
|
wrapper.first =
|
|
LINKED_LIST_MERGE_SORT_(ListNodeType) (wrapper.first, compare_nodes);
|
|
wrapper.last = find_last_node (wrapper.first);
|
|
|
|
failures += ! check ("sort", &test_data[1], &wrapper);
|
|
|
|
/* Save a reference to this node for later. */
|
|
ListNodeType *n_to_remove = wrapper.first;
|
|
|
|
/* Prepend node. */
|
|
LINKED_LIST_PREPEND(ListNodeType) (&wrapper, l_new_node (11));
|
|
failures += ! check ("prepend", &test_data[2], &wrapper);
|
|
|
|
/* Insert node. */
|
|
LINKED_LIST_INSERT_BEFORE(ListNodeType) (&wrapper, l_new_node (8), wrapper.last);
|
|
failures += ! check ("insert_before", &test_data[3], &wrapper);
|
|
|
|
/* Remove a node. */
|
|
LINKED_LIST_REMOVE(ListNodeType) (&wrapper, n_to_remove);
|
|
failures += ! check ("remove", &test_data[4], &wrapper);
|
|
|
|
/* Swap first and last. */
|
|
LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first, wrapper.last);
|
|
failures += ! check ("swap first and last", &test_data[5], &wrapper);
|
|
|
|
/* Swap adjacent nodes. */
|
|
LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next,
|
|
wrapper.first->next->next);
|
|
failures += ! check ("swap adjacent nodes", &test_data[6], &wrapper);
|
|
|
|
/* Swap non-adjacent nodes, but neither first nor last. */
|
|
LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next,
|
|
wrapper.first->next->next->next->next);
|
|
failures += ! check ("swap non-adjacent nodes", &test_data[7], &wrapper);
|
|
|
|
/* Sort nodes. */
|
|
LINKED_LIST_MERGE_SORT(ListNodeType) (&wrapper, compare_nodes);
|
|
failures += ! check ("sort", &test_data[8], &wrapper);
|
|
|
|
/* Pop front. */
|
|
LINKED_LIST_POP_FRONT(ListNodeType) (&wrapper);
|
|
failures += ! check ("pop_front", &test_data[9], &wrapper);
|
|
|
|
/* Pop back. */
|
|
LINKED_LIST_POP_BACK(ListNodeType) (&wrapper);
|
|
failures += ! check ("pop_back", &test_data[10], &wrapper);
|
|
|
|
exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
}
|