diff options
Diffstat (limited to '')
-rw-r--r-- | pceplib/test/pcep_pcc_api_test.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/pceplib/test/pcep_pcc_api_test.c b/pceplib/test/pcep_pcc_api_test.c new file mode 100644 index 0000000..9106671 --- /dev/null +++ b/pceplib/test/pcep_pcc_api_test.c @@ -0,0 +1,299 @@ +/* + * This file is part of the PCEPlib, a PCEP protocol library. + * + * Copyright (C) 2020 Volta Networks https://voltanet.io/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * Author : Brady Johnson <brady@voltanet.io> + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <assert.h> +#include <netdb.h> // gethostbyname +#include <pthread.h> +#include <stdlib.h> +#include <unistd.h> + +#include <CUnit/CUnit.h> + +#include "pcep_pcc_api.h" +#include "pcep_pcc_api_test.h" +#include "pcep_socket_comm_mock.h" +#include "pcep_utils_memory.h" + +extern pcep_event_queue *session_logic_event_queue_; +extern const char MESSAGE_RECEIVED_STR[]; +extern const char UNKNOWN_EVENT_STR[]; + +/* + * Test suite setup and teardown called before AND after the test suite. + */ + +int pcep_pcc_api_test_suite_setup() +{ + pceplib_memory_reset(); + return 0; +} + +int pcep_pcc_api_test_suite_teardown() +{ + printf("\n"); + pceplib_memory_dump(); + return 0; +} + +/* + * Test case setup and teardown called before AND after each test. + */ + +void pcep_pcc_api_test_setup() +{ + setup_mock_socket_comm_info(); +} + + +void pcep_pcc_api_test_teardown() +{ + teardown_mock_socket_comm_info(); +} + +/* + * Unit test cases + */ + +void test_initialize_pcc() +{ + CU_ASSERT_TRUE(initialize_pcc()); + /* Give the PCC time to initialize */ + sleep(1); + CU_ASSERT_TRUE(destroy_pcc()); +} + +void test_connect_pce() +{ + pcep_configuration *config = create_default_pcep_configuration(); + struct hostent *host_info = gethostbyname("localhost"); + struct in_addr dest_address; + memcpy(&dest_address, host_info->h_addr, host_info->h_length); + mock_socket_comm_info *mock_info = get_mock_socket_comm_info(); + mock_info->send_message_save_message = true; + + initialize_pcc(); + + pcep_session *session = connect_pce(config, &dest_address); + + CU_ASSERT_PTR_NOT_NULL(session); + CU_ASSERT_EQUAL(mock_info->sent_message_list->num_entries, 1); + /* What gets saved in the mock is the msg byte buffer. The msg struct + * was deleted when it was sent. Instead of inspecting the msg byte + * buffer, lets just decode it. */ + uint8_t *encoded_msg = + dll_delete_first_node(mock_info->sent_message_list); + CU_ASSERT_PTR_NOT_NULL(encoded_msg); + struct pcep_message *open_msg = pcep_decode_message(encoded_msg); + CU_ASSERT_PTR_NOT_NULL(open_msg); + assert(open_msg != NULL); + assert(open_msg->msg_header != NULL); + CU_ASSERT_EQUAL(open_msg->msg_header->type, PCEP_TYPE_OPEN); + + pcep_msg_free_message(open_msg); + destroy_pcep_session(session); + destroy_pcep_configuration(config); + pceplib_free(PCEPLIB_MESSAGES, encoded_msg); + + destroy_pcc(); +} + +void test_connect_pce_ipv6() +{ + pcep_configuration *config = create_default_pcep_configuration(); + struct in6_addr dest_address; + dest_address.__in6_u.__u6_addr32[0] = 0; + dest_address.__in6_u.__u6_addr32[1] = 0; + dest_address.__in6_u.__u6_addr32[2] = 0; + dest_address.__in6_u.__u6_addr32[3] = htonl(1); + mock_socket_comm_info *mock_info = get_mock_socket_comm_info(); + mock_info->send_message_save_message = true; + + initialize_pcc(); + + pcep_session *session = connect_pce_ipv6(config, &dest_address); + + CU_ASSERT_PTR_NOT_NULL(session); + assert(session != NULL); + CU_ASSERT_TRUE(session->socket_comm_session->is_ipv6); + CU_ASSERT_EQUAL(mock_info->sent_message_list->num_entries, 1); + /* What gets saved in the mock is the msg byte buffer. The msg struct + * was deleted when it was sent. Instead of inspecting the msg byte + * buffer, lets just decode it. */ + uint8_t *encoded_msg = + dll_delete_first_node(mock_info->sent_message_list); + CU_ASSERT_PTR_NOT_NULL(encoded_msg); + struct pcep_message *open_msg = pcep_decode_message(encoded_msg); + CU_ASSERT_PTR_NOT_NULL(open_msg); + assert(open_msg != NULL); + CU_ASSERT_EQUAL(open_msg->msg_header->type, PCEP_TYPE_OPEN); + + pcep_msg_free_message(open_msg); + destroy_pcep_session(session); + destroy_pcep_configuration(config); + pceplib_free(PCEPLIB_MESSAGES, encoded_msg); + + destroy_pcc(); +} + +void test_connect_pce_with_src_ip() +{ + pcep_configuration *config = create_default_pcep_configuration(); + struct hostent *host_info = gethostbyname("localhost"); + struct in_addr dest_address; + memcpy(&dest_address, host_info->h_addr, host_info->h_length); + mock_socket_comm_info *mock_info = get_mock_socket_comm_info(); + mock_info->send_message_save_message = true; + config->src_ip.src_ipv4.s_addr = 0x0a0a0102; + + initialize_pcc(); + + pcep_session *session = connect_pce(config, &dest_address); + + CU_ASSERT_PTR_NOT_NULL(session); + CU_ASSERT_EQUAL(mock_info->sent_message_list->num_entries, 1); + uint8_t *encoded_msg = + dll_delete_first_node(mock_info->sent_message_list); + CU_ASSERT_PTR_NOT_NULL(encoded_msg); + struct pcep_message *open_msg = pcep_decode_message(encoded_msg); + CU_ASSERT_PTR_NOT_NULL(open_msg); + assert(open_msg != NULL); + assert(open_msg->msg_header != NULL); + CU_ASSERT_EQUAL(open_msg->msg_header->type, PCEP_TYPE_OPEN); + + pcep_msg_free_message(open_msg); + destroy_pcep_session(session); + destroy_pcep_configuration(config); + pceplib_free(PCEPLIB_MESSAGES, encoded_msg); + + destroy_pcc(); +} + +void test_disconnect_pce() +{ + pcep_configuration *config = create_default_pcep_configuration(); + struct hostent *host_info = gethostbyname("localhost"); + struct in_addr dest_address; + memcpy(&dest_address, host_info->h_addr, host_info->h_length); + mock_socket_comm_info *mock_info = get_mock_socket_comm_info(); + mock_info->send_message_save_message = true; + + initialize_pcc(); + + pcep_session *session = connect_pce(config, &dest_address); + disconnect_pce(session); + + CU_ASSERT_EQUAL(mock_info->sent_message_list->num_entries, 2); + + /* First there should be an open message from connect_pce() */ + uint8_t *encoded_msg = + dll_delete_first_node(mock_info->sent_message_list); + CU_ASSERT_PTR_NOT_NULL(encoded_msg); + struct pcep_message *msg = pcep_decode_message(encoded_msg); + CU_ASSERT_PTR_NOT_NULL(msg); + assert(msg != NULL); + CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_OPEN); + pcep_msg_free_message(msg); + pceplib_free(PCEPLIB_MESSAGES, encoded_msg); + + /* Then there should be a close message from disconnect_pce() */ + encoded_msg = dll_delete_first_node(mock_info->sent_message_list); + CU_ASSERT_PTR_NOT_NULL(encoded_msg); + msg = pcep_decode_message(encoded_msg); + CU_ASSERT_PTR_NOT_NULL(msg); + assert(msg != NULL); + assert(msg->msg_header != NULL); + CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_CLOSE); + + pcep_msg_free_message(msg); + destroy_pcep_session(session); + destroy_pcep_configuration(config); + pceplib_free(PCEPLIB_MESSAGES, encoded_msg); + + destroy_pcc(); +} + + +void test_send_message() +{ + pcep_configuration *config = create_default_pcep_configuration(); + struct hostent *host_info = gethostbyname("localhost"); + struct in_addr dest_address; + + initialize_pcc(); + + memcpy(&dest_address, host_info->h_addr, host_info->h_length); + pcep_session *session = connect_pce(config, &dest_address); + verify_socket_comm_times_called(0, 0, 1, 1, 0, 0, 0); + + struct pcep_message *msg = pcep_msg_create_keepalive(); + send_message(session, msg, false); + + verify_socket_comm_times_called(0, 0, 1, 2, 0, 0, 0); + + pcep_msg_free_message(msg); + destroy_pcep_session(session); + destroy_pcep_configuration(config); + + destroy_pcc(); +} + +void test_event_queue() +{ + /* This initializes the event_queue */ + CU_ASSERT_TRUE(initialize_pcc()); + + /* Verify correct behavior when the queue is empty */ + CU_ASSERT_TRUE(event_queue_is_empty()); + CU_ASSERT_EQUAL(event_queue_num_events_available(), 0); + CU_ASSERT_PTR_NULL(event_queue_get_event()); + destroy_pcep_event(NULL); + + /* Create an empty event and put it on the queue */ + pcep_event *event = pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_event)); + memset(event, 0, sizeof(pcep_event)); + pthread_mutex_lock(&session_logic_event_queue_->event_queue_mutex); + queue_enqueue(session_logic_event_queue_->event_queue, event); + pthread_mutex_unlock(&session_logic_event_queue_->event_queue_mutex); + + /* Verify correct behavior when there is an entry in the queue */ + CU_ASSERT_FALSE(event_queue_is_empty()); + CU_ASSERT_EQUAL(event_queue_num_events_available(), 1); + pcep_event *queued_event = event_queue_get_event(); + CU_ASSERT_PTR_NOT_NULL(queued_event); + CU_ASSERT_PTR_EQUAL(event, queued_event); + destroy_pcep_event(queued_event); + + CU_ASSERT_TRUE(destroy_pcc()); +} + +void test_get_event_type_str() +{ + CU_ASSERT_EQUAL(strcmp(get_event_type_str(MESSAGE_RECEIVED), + MESSAGE_RECEIVED_STR), + 0); + CU_ASSERT_EQUAL(strcmp(get_event_type_str(1000), UNKNOWN_EVENT_STR), 0); +} |