mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-10-31 16:56:31 +00:00 
			
		
		
		
	 1f8031f79a
			
		
	
	
		1f8031f79a
		
	
	
	
	
		
			
			`config.h` has all the defines from autoconf, which may include things that switch behavior of other included headers (e.g. _GNU_SOURCE enabling prototypes for additional functions.) So, the first include in any `.c` file must be either `config.h` (with the appropriate guard) or `zebra.h` (which includes `config.h` first thing.) Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
		
			
				
	
	
		
			368 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			368 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * This module is built into a separate library, and is used by several
 | |
|  * other modules for unit testing, so that real sockets dont have to be
 | |
|  * created.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include "config.h"
 | |
| #endif
 | |
| 
 | |
| #include <netinet/in.h>
 | |
| #include <stdbool.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include <CUnit/CUnit.h>
 | |
| 
 | |
| #include "pcep_socket_comm.h"
 | |
| #include "pcep_socket_comm_mock.h"
 | |
| #include "pcep_utils_queue.h"
 | |
| 
 | |
| /* reset_mock_socket_comm_info() should be used before each test */
 | |
| mock_socket_comm_info mock_socket_metadata;
 | |
| 
 | |
| void setup_mock_socket_comm_info(void)
 | |
| {
 | |
| 	mock_socket_metadata.socket_comm_session_initialize_times_called = 0;
 | |
| 	mock_socket_metadata.socket_comm_session_initialize_src_times_called =
 | |
| 		0;
 | |
| 	mock_socket_metadata.socket_comm_session_teardown_times_called = 0;
 | |
| 	mock_socket_metadata.socket_comm_session_connect_tcp_times_called = 0;
 | |
| 	mock_socket_metadata.socket_comm_session_send_message_times_called = 0;
 | |
| 	mock_socket_metadata
 | |
| 		.socket_comm_session_close_tcp_after_write_times_called = 0;
 | |
| 	mock_socket_metadata.socket_comm_session_close_tcp_times_called = 0;
 | |
| 	mock_socket_metadata.destroy_socket_comm_loop_times_called = 0;
 | |
| 	mock_socket_metadata.send_message_save_message = false;
 | |
| 	mock_socket_metadata.sent_message_list = dll_initialize();
 | |
| }
 | |
| 
 | |
| void teardown_mock_socket_comm_info(void)
 | |
| {
 | |
| 	dll_destroy(mock_socket_metadata.sent_message_list);
 | |
| }
 | |
| 
 | |
| void reset_mock_socket_comm_info(void)
 | |
| {
 | |
| 	teardown_mock_socket_comm_info();
 | |
| 	setup_mock_socket_comm_info();
 | |
| }
 | |
| 
 | |
| mock_socket_comm_info *get_mock_socket_comm_info(void)
 | |
| {
 | |
| 	return &mock_socket_metadata;
 | |
| }
 | |
| 
 | |
| void verify_socket_comm_times_called(int initialized, int teardown, int connect,
 | |
| 				     int send_message,
 | |
| 				     int close_tcp_after_write, int close_tcp,
 | |
| 				     int destroy)
 | |
| {
 | |
| 	CU_ASSERT_EQUAL(initialized,
 | |
| 			mock_socket_metadata
 | |
| 				.socket_comm_session_initialize_times_called);
 | |
| 	CU_ASSERT_EQUAL(
 | |
| 		teardown,
 | |
| 		mock_socket_metadata.socket_comm_session_teardown_times_called);
 | |
| 	CU_ASSERT_EQUAL(connect,
 | |
| 			mock_socket_metadata
 | |
| 				.socket_comm_session_connect_tcp_times_called);
 | |
| 	CU_ASSERT_EQUAL(send_message,
 | |
| 			mock_socket_metadata
 | |
| 				.socket_comm_session_send_message_times_called);
 | |
| 	CU_ASSERT_EQUAL(
 | |
| 		close_tcp_after_write,
 | |
| 		mock_socket_metadata
 | |
| 			.socket_comm_session_close_tcp_after_write_times_called);
 | |
| 	CU_ASSERT_EQUAL(close_tcp,
 | |
| 			mock_socket_metadata
 | |
| 				.socket_comm_session_close_tcp_times_called);
 | |
| 	CU_ASSERT_EQUAL(
 | |
| 		destroy,
 | |
| 		mock_socket_metadata.destroy_socket_comm_loop_times_called);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Mock the socket_comm functions used by session_logic for Unit Testing
 | |
|  */
 | |
| 
 | |
| bool initialize_socket_comm_external_infra(
 | |
| 	void *external_infra_data, ext_socket_read socket_read_cb,
 | |
| 	ext_socket_write socket_write_cb,
 | |
| 	ext_socket_pthread_create_callback thread_create_func)
 | |
| {
 | |
| 	(void)external_infra_data;
 | |
| 	(void)socket_read_cb;
 | |
| 	(void)socket_write_cb;
 | |
| 	(void)thread_create_func;
 | |
| 
 | |
| 	mock_socket_metadata
 | |
| 		.socket_comm_initialize_external_infra_times_called++;
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| bool destroy_socket_comm_loop()
 | |
| {
 | |
| 	mock_socket_metadata.destroy_socket_comm_loop_times_called++;
 | |
| 
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| pcep_socket_comm_session *
 | |
| socket_comm_session_initialize(message_received_handler msg_rcv_handler,
 | |
| 			       message_ready_to_read_handler msg_ready_handler,
 | |
| 			       message_sent_notifier msg_sent_notifier,
 | |
| 			       connection_except_notifier notifier,
 | |
| 			       struct in_addr *dst_ip, short dst_port,
 | |
| 			       uint32_t connect_timeout_millis,
 | |
| 			       const char *tcp_authentication_str,
 | |
| 			       bool is_tcp_auth_md5, void *session_data)
 | |
| {
 | |
| 	(void)msg_sent_notifier;
 | |
| 	(void)tcp_authentication_str;
 | |
| 	(void)is_tcp_auth_md5;
 | |
| 
 | |
| 	mock_socket_metadata.socket_comm_session_initialize_times_called++;
 | |
| 
 | |
| 	pcep_socket_comm_session *comm_session =
 | |
| 		malloc(sizeof(pcep_socket_comm_session));
 | |
| 	memset(comm_session, 0, sizeof(pcep_socket_comm_session));
 | |
| 
 | |
| 	comm_session->message_handler = msg_rcv_handler;
 | |
| 	comm_session->message_ready_to_read_handler = msg_ready_handler;
 | |
| 	comm_session->conn_except_notifier = notifier;
 | |
| 	comm_session->message_queue = queue_initialize();
 | |
| 	comm_session->session_data = session_data;
 | |
| 	comm_session->close_after_write = false;
 | |
| 	comm_session->connect_timeout_millis = connect_timeout_millis;
 | |
| 	comm_session->is_ipv6 = false;
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv4.sin_family = AF_INET;
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv4.sin_port =
 | |
| 		htons(dst_port);
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv4.sin_addr.s_addr =
 | |
| 		dst_ip->s_addr;
 | |
| 
 | |
| 	return comm_session;
 | |
| }
 | |
| 
 | |
| pcep_socket_comm_session *socket_comm_session_initialize_ipv6(
 | |
| 	message_received_handler msg_rcv_handler,
 | |
| 	message_ready_to_read_handler msg_ready_handler,
 | |
| 	message_sent_notifier msg_sent_notifier,
 | |
| 	connection_except_notifier notifier, struct in6_addr *dst_ip,
 | |
| 	short dst_port, uint32_t connect_timeout_millis,
 | |
| 	const char *tcp_authentication_str, bool is_tcp_auth_md5,
 | |
| 	void *session_data)
 | |
| {
 | |
| 	(void)msg_sent_notifier;
 | |
| 	(void)tcp_authentication_str;
 | |
| 	(void)is_tcp_auth_md5;
 | |
| 
 | |
| 	mock_socket_metadata.socket_comm_session_initialize_times_called++;
 | |
| 
 | |
| 	pcep_socket_comm_session *comm_session =
 | |
| 		malloc(sizeof(pcep_socket_comm_session));
 | |
| 	memset(comm_session, 0, sizeof(pcep_socket_comm_session));
 | |
| 
 | |
| 	comm_session->message_handler = msg_rcv_handler;
 | |
| 	comm_session->message_ready_to_read_handler = msg_ready_handler;
 | |
| 	comm_session->conn_except_notifier = notifier;
 | |
| 	comm_session->message_queue = queue_initialize();
 | |
| 	comm_session->session_data = session_data;
 | |
| 	comm_session->close_after_write = false;
 | |
| 	comm_session->connect_timeout_millis = connect_timeout_millis;
 | |
| 	comm_session->is_ipv6 = true;
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv6.sin6_family = AF_INET6;
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv6.sin6_port =
 | |
| 		htons(dst_port);
 | |
| 	memcpy(&comm_session->dest_sock_addr.dest_sock_addr_ipv6.sin6_addr,
 | |
| 	       dst_ip, sizeof(struct in6_addr));
 | |
| 
 | |
| 	return comm_session;
 | |
| }
 | |
| 
 | |
| pcep_socket_comm_session *socket_comm_session_initialize_with_src(
 | |
| 	message_received_handler msg_rcv_handler,
 | |
| 	message_ready_to_read_handler msg_ready_handler,
 | |
| 	message_sent_notifier msg_sent_notifier,
 | |
| 	connection_except_notifier notifier, struct in_addr *src_ip,
 | |
| 	short src_port, struct in_addr *dst_ip, short dst_port,
 | |
| 	uint32_t connect_timeout_millis, const char *tcp_authentication_str,
 | |
| 	bool is_tcp_auth_md5, void *session_data)
 | |
| {
 | |
| 	(void)msg_sent_notifier;
 | |
| 	(void)tcp_authentication_str;
 | |
| 	(void)is_tcp_auth_md5;
 | |
| 
 | |
| 	mock_socket_metadata.socket_comm_session_initialize_src_times_called++;
 | |
| 
 | |
| 	pcep_socket_comm_session *comm_session =
 | |
| 		malloc(sizeof(pcep_socket_comm_session));
 | |
| 	memset(comm_session, 0, sizeof(pcep_socket_comm_session));
 | |
| 
 | |
| 	comm_session->message_handler = msg_rcv_handler;
 | |
| 	comm_session->message_ready_to_read_handler = msg_ready_handler;
 | |
| 	comm_session->conn_except_notifier = notifier;
 | |
| 	comm_session->message_queue = queue_initialize();
 | |
| 	comm_session->session_data = session_data;
 | |
| 	comm_session->close_after_write = false;
 | |
| 	comm_session->connect_timeout_millis = connect_timeout_millis;
 | |
| 	comm_session->is_ipv6 = false;
 | |
| 	comm_session->src_sock_addr.src_sock_addr_ipv4.sin_family = AF_INET;
 | |
| 	comm_session->src_sock_addr.src_sock_addr_ipv4.sin_port =
 | |
| 		htons(src_port);
 | |
| 	comm_session->src_sock_addr.src_sock_addr_ipv4.sin_addr.s_addr =
 | |
| 		((src_ip == NULL) ? INADDR_ANY : src_ip->s_addr);
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv4.sin_family = AF_INET;
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv4.sin_port =
 | |
| 		htons(dst_port);
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv4.sin_addr.s_addr =
 | |
| 		dst_ip->s_addr;
 | |
| 
 | |
| 	return comm_session;
 | |
| }
 | |
| 
 | |
| pcep_socket_comm_session *socket_comm_session_initialize_with_src_ipv6(
 | |
| 	message_received_handler msg_rcv_handler,
 | |
| 	message_ready_to_read_handler msg_ready_handler,
 | |
| 	message_sent_notifier msg_sent_notifier,
 | |
| 	connection_except_notifier notifier, struct in6_addr *src_ip,
 | |
| 	short src_port, struct in6_addr *dst_ip, short dst_port,
 | |
| 	uint32_t connect_timeout_millis, const char *tcp_authentication_str,
 | |
| 	bool is_tcp_auth_md5, void *session_data)
 | |
| {
 | |
| 	(void)msg_sent_notifier;
 | |
| 	(void)tcp_authentication_str;
 | |
| 	(void)is_tcp_auth_md5;
 | |
| 
 | |
| 	mock_socket_metadata.socket_comm_session_initialize_src_times_called++;
 | |
| 
 | |
| 	pcep_socket_comm_session *comm_session =
 | |
| 		malloc(sizeof(pcep_socket_comm_session));
 | |
| 	memset(comm_session, 0, sizeof(pcep_socket_comm_session));
 | |
| 
 | |
| 	comm_session->message_handler = msg_rcv_handler;
 | |
| 	comm_session->message_ready_to_read_handler = msg_ready_handler;
 | |
| 	comm_session->conn_except_notifier = notifier;
 | |
| 	comm_session->message_queue = queue_initialize();
 | |
| 	comm_session->session_data = session_data;
 | |
| 	comm_session->close_after_write = false;
 | |
| 	comm_session->connect_timeout_millis = connect_timeout_millis;
 | |
| 	comm_session->is_ipv6 = true;
 | |
| 	comm_session->src_sock_addr.src_sock_addr_ipv6.sin6_family = AF_INET6;
 | |
| 	comm_session->src_sock_addr.src_sock_addr_ipv6.sin6_port =
 | |
| 		htons(src_port);
 | |
| 	if (src_ip == NULL) {
 | |
| 		comm_session->src_sock_addr.src_sock_addr_ipv6.sin6_addr =
 | |
| 			in6addr_any;
 | |
| 	} else {
 | |
| 		memcpy(&comm_session->src_sock_addr.src_sock_addr_ipv6
 | |
| 				.sin6_addr,
 | |
| 		       src_ip, sizeof(struct in6_addr));
 | |
| 	}
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv6.sin6_family = AF_INET6;
 | |
| 	comm_session->dest_sock_addr.dest_sock_addr_ipv6.sin6_port =
 | |
| 		htons(dst_port);
 | |
| 	memcpy(&comm_session->dest_sock_addr.dest_sock_addr_ipv6.sin6_addr,
 | |
| 	       dst_ip, sizeof(struct in6_addr));
 | |
| 
 | |
| 	return comm_session;
 | |
| }
 | |
| 
 | |
| bool socket_comm_session_teardown(pcep_socket_comm_session *socket_comm_session)
 | |
| {
 | |
| 	mock_socket_metadata.socket_comm_session_teardown_times_called++;
 | |
| 
 | |
| 	if (socket_comm_session != NULL) {
 | |
| 		queue_destroy(socket_comm_session->message_queue);
 | |
| 		free(socket_comm_session);
 | |
| 	}
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool socket_comm_session_connect_tcp(
 | |
| 	pcep_socket_comm_session *socket_comm_session)
 | |
| {
 | |
| 	(void)socket_comm_session;
 | |
| 
 | |
| 	mock_socket_metadata.socket_comm_session_connect_tcp_times_called++;
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| 
 | |
| void socket_comm_session_send_message(
 | |
| 	pcep_socket_comm_session *socket_comm_session,
 | |
| 	const char *encoded_message, unsigned int msg_length,
 | |
| 	bool delete_after_send)
 | |
| {
 | |
| 	(void)socket_comm_session;
 | |
| 	(void)msg_length;
 | |
| 
 | |
| 	mock_socket_metadata.socket_comm_session_send_message_times_called++;
 | |
| 
 | |
| 	if (mock_socket_metadata.send_message_save_message == true) {
 | |
| 		/* the caller/test case is responsible for freeing the message
 | |
| 		 */
 | |
| 		dll_append(mock_socket_metadata.sent_message_list,
 | |
| 			   (char *)encoded_message);
 | |
| 	} else {
 | |
| 		if (delete_after_send == true) {
 | |
| 			free((void *)encoded_message);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool socket_comm_session_close_tcp_after_write(
 | |
| 	pcep_socket_comm_session *socket_comm_session)
 | |
| {
 | |
| 	(void)socket_comm_session;
 | |
| 
 | |
| 	mock_socket_metadata
 | |
| 		.socket_comm_session_close_tcp_after_write_times_called++;
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool socket_comm_session_close_tcp(
 | |
| 	pcep_socket_comm_session *socket_comm_session)
 | |
| {
 | |
| 	(void)socket_comm_session;
 | |
| 
 | |
| 	mock_socket_metadata.socket_comm_session_close_tcp_times_called++;
 | |
| 
 | |
| 	return true;
 | |
| }
 |