| // Copyright 2018 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/lib/listnode/listnode.h" | |
| #include <zxtest/zxtest.h> | |
| namespace { | |
| typedef struct list_elem { | |
| int value; | |
| list_node_t node; | |
| } list_elem_t; | |
| void expect_list_sorted(list_node_t* list, int count) { | |
| EXPECT_EQ(list_length(list), static_cast<unsigned int>(count)); | |
| int index = 0; | |
| list_elem_t* entry = NULL; | |
| list_for_every_entry (list, entry, list_elem_t, node) { | |
| EXPECT_EQ(entry->value, index); | |
| EXPECT_EQ(list_next_wrap_type(list, &entry->node, list_elem_t, node)->value, | |
| (index + 1) % count); | |
| EXPECT_EQ(list_prev_wrap_type(list, &entry->node, list_elem_t, node)->value, | |
| (index + count - 1) % count); | |
| index++; | |
| } | |
| } | |
| TEST(ListnodeCppTests, initialize_empty_list) { | |
| list_node_t list = LIST_INITIAL_CLEARED_VALUE; | |
| EXPECT_FALSE(list_in_list(&list)); | |
| list_initialize(&list); | |
| EXPECT_TRUE(list_in_list(&list)); | |
| EXPECT_TRUE(list_is_empty(&list)); | |
| EXPECT_EQ(list_length(&list), 0u); | |
| EXPECT_NULL(list_peek_head(&list)); | |
| EXPECT_NULL(list_peek_head_type(&list, list_elem_t, node)); | |
| EXPECT_NULL(list_peek_tail(&list)); | |
| EXPECT_NULL(list_peek_tail_type(&list, list_elem_t, node)); | |
| EXPECT_NULL(list_remove_head(&list)); | |
| EXPECT_NULL(list_remove_head_type(&list, list_elem_t, node)); | |
| EXPECT_NULL(list_remove_tail(&list)); | |
| EXPECT_NULL(list_remove_tail_type(&list, list_elem_t, node)); | |
| EXPECT_NULL(list_next(&list, &list)); | |
| EXPECT_NULL(list_next_type(&list, &list, list_elem_t, node)); | |
| EXPECT_NULL(list_next_wrap(&list, &list)); | |
| EXPECT_NULL(list_next_wrap_type(&list, &list, list_elem_t, node)); | |
| EXPECT_NULL(list_prev(&list, &list)); | |
| EXPECT_NULL(list_prev_type(&list, &list, list_elem_t, node)); | |
| EXPECT_NULL(list_prev_wrap(&list, &list)); | |
| EXPECT_NULL(list_prev_wrap_type(&list, &list, list_elem_t, node)); | |
| } | |
| TEST(ListnodeCppTests, element_add_remove) { | |
| list_elem_t first_set[5] = { | |
| {-1, {}}, {2, {}}, {3, {}}, {4, {}}, {-1, {}}, | |
| }; | |
| list_elem_t second_set[4] = { | |
| {0, {}}, | |
| {6, {}}, | |
| {1, {}}, | |
| {5, {}}, | |
| }; | |
| // Fill a list with elements from first_set. [ -1 2 3 4 -1 ] | |
| list_node_t list = LIST_INITIAL_CLEARED_VALUE; | |
| list_initialize(&list); | |
| for (int i = 0; i < 5; i++) { | |
| list_add_tail(&list, &first_set[i].node); | |
| } | |
| // Clear the first and last elements in the list, then add new elements in | |
| // numerical order. [ 0 1 2 3 4 5 ] | |
| list_remove_head(&list); | |
| list_remove_tail(&list); | |
| list_add_head(&list, &second_set[0].node); | |
| list_add_tail(&list, &second_set[1].node); | |
| list_add_after(list_peek_head(&list), &second_set[2].node); | |
| list_add_before(list_peek_tail(&list), &second_set[3].node); | |
| // The list should be sorted now. | |
| expect_list_sorted(&list, 7); | |
| // Verify list deletion. | |
| list_node_t* node = NULL; | |
| list_node_t* to_del = NULL; | |
| list_for_every_safe(&list, node, to_del) { list_delete(node); } | |
| EXPECT_TRUE(list_is_empty(&list)); | |
| } | |
| TEST(ListnodeCppTests, list_splice_split) { | |
| list_elem_t first_set[3] = { | |
| {0, {}}, | |
| {3, {}}, | |
| {4, {}}, | |
| }; | |
| list_elem_t second_set[3] = { | |
| {5, {}}, | |
| {1, {}}, | |
| {2, {}}, | |
| }; | |
| list_node_t first_list; | |
| list_initialize(&first_list); | |
| list_node_t second_list; | |
| list_initialize(&second_list); | |
| for (int i = 0; i < 3; ++i) { | |
| list_add_tail(&first_list, &first_set[i].node); | |
| list_add_tail(&second_list, &second_set[i].node); | |
| } | |
| // Splice together the initial big list. [ 0 3 4 5 1 2 ] | |
| list_splice_after(&second_list, list_peek_tail(&first_list)); | |
| EXPECT_EQ(list_length(&first_list), 6u); | |
| EXPECT_EQ(list_length(&second_list), 0u); | |
| // Split off the last two elements of the list. [ 0 3 4 5 ] [ 1 2 ] | |
| list_split_after(&first_list, list_peek_tail(&first_list)->prev->prev, &second_list); | |
| EXPECT_EQ(list_length(&first_list), 4u); | |
| EXPECT_EQ(list_length(&second_list), 2u); | |
| // Splice the split portion back in, in order. [ 0 1 2 3 4 5 ] | |
| list_splice_after(&second_list, list_peek_head(&first_list)); | |
| EXPECT_EQ(list_length(&first_list), 6u); | |
| EXPECT_EQ(list_length(&second_list), 0u); | |
| // The list should be sorted now. | |
| expect_list_sorted(&first_list, 6); | |
| // Move the lists and recheck. | |
| list_move(&first_list, &second_list); | |
| EXPECT_EQ(list_length(&first_list), 0u); | |
| EXPECT_EQ(list_length(&second_list), 6u); | |
| // The second list should be sorted now. | |
| expect_list_sorted(&second_list, 6); | |
| } | |
| } // namespace |