summaryrefslogtreecommitdiffstats
path: root/pceplib/test
diff options
context:
space:
mode:
Diffstat (limited to 'pceplib/test')
-rw-r--r--pceplib/test/pcep_msg_messages_test.c560
-rw-r--r--pceplib/test/pcep_msg_messages_test.h48
-rw-r--r--pceplib/test/pcep_msg_messages_tests.c260
-rw-r--r--pceplib/test/pcep_msg_object_error_types_test.c88
-rw-r--r--pceplib/test/pcep_msg_object_error_types_test.h37
-rw-r--r--pceplib/test/pcep_msg_objects_test.c1312
-rw-r--r--pceplib/test/pcep_msg_objects_test.h64
-rwxr-xr-xpceplib/test/pcep_msg_tests_valgrind.sh2
-rw-r--r--pceplib/test/pcep_msg_tlvs_test.c725
-rw-r--r--pceplib/test/pcep_msg_tlvs_test.h51
-rw-r--r--pceplib/test/pcep_msg_tools_test.c1367
-rw-r--r--pceplib/test/pcep_msg_tools_test.h48
-rw-r--r--pceplib/test/pcep_pcc_api_test.c299
-rw-r--r--pceplib/test/pcep_pcc_api_test.h43
-rw-r--r--pceplib/test/pcep_pcc_api_tests.c92
-rwxr-xr-xpceplib/test/pcep_pcc_api_tests_valgrind.sh2
-rw-r--r--pceplib/test/pcep_session_logic_loop_test.c245
-rw-r--r--pceplib/test/pcep_session_logic_loop_test.h40
-rw-r--r--pceplib/test/pcep_session_logic_states_test.c933
-rw-r--r--pceplib/test/pcep_session_logic_states_test.h52
-rw-r--r--pceplib/test/pcep_session_logic_test.c381
-rw-r--r--pceplib/test/pcep_session_logic_test.h43
-rw-r--r--pceplib/test/pcep_session_logic_tests.c205
-rwxr-xr-xpceplib/test/pcep_session_logic_tests_valgrind.sh2
-rw-r--r--pceplib/test/pcep_socket_comm_loop_test.c198
-rw-r--r--pceplib/test/pcep_socket_comm_loop_test.h38
-rw-r--r--pceplib/test/pcep_socket_comm_test.c325
-rw-r--r--pceplib/test/pcep_socket_comm_test.h42
-rw-r--r--pceplib/test/pcep_socket_comm_tests.c132
-rwxr-xr-xpceplib/test/pcep_socket_comm_tests_valgrind.sh2
-rwxr-xr-xpceplib/test/pcep_tests_valgrind.sh15
-rw-r--r--pceplib/test/pcep_timers_event_loop_test.c166
-rw-r--r--pceplib/test/pcep_timers_event_loop_test.h38
-rw-r--r--pceplib/test/pcep_timers_test.c113
-rw-r--r--pceplib/test/pcep_timers_test.h40
-rw-r--r--pceplib/test/pcep_timers_tests.c117
-rwxr-xr-xpceplib/test/pcep_timers_tests_valgrind.sh2
-rw-r--r--pceplib/test/pcep_utils_counters_test.c261
-rw-r--r--pceplib/test/pcep_utils_counters_test.h43
-rw-r--r--pceplib/test/pcep_utils_double_linked_list_test.c315
-rw-r--r--pceplib/test/pcep_utils_double_linked_list_test.h38
-rw-r--r--pceplib/test/pcep_utils_memory_test.c245
-rw-r--r--pceplib/test/pcep_utils_memory_test.h33
-rw-r--r--pceplib/test/pcep_utils_ordered_list_test.c257
-rw-r--r--pceplib/test/pcep_utils_ordered_list_test.h39
-rw-r--r--pceplib/test/pcep_utils_queue_test.c163
-rw-r--r--pceplib/test/pcep_utils_queue_test.h36
-rw-r--r--pceplib/test/pcep_utils_tests.c140
-rwxr-xr-xpceplib/test/pcep_utils_tests_valgrind.sh2
-rw-r--r--pceplib/test/subdir.am122
50 files changed, 9821 insertions, 0 deletions
diff --git a/pceplib/test/pcep_msg_messages_test.c b/pceplib/test/pcep_msg_messages_test.c
new file mode 100644
index 0000000..e3a74f9
--- /dev/null
+++ b/pceplib/test/pcep_msg_messages_test.c
@@ -0,0 +1,560 @@
+/*
+ * 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 <stdlib.h>
+#include <assert.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_msg_encoding.h"
+#include "pcep_msg_messages.h"
+#include "pcep_msg_objects.h"
+#include "pcep_msg_tools.h"
+#include "pcep_utils_double_linked_list.h"
+#include "pcep_utils_memory.h"
+#include "pcep_msg_messages_test.h"
+
+/*
+ * Notice:
+ * All of these message Unit Tests encode the created messages by explicitly
+ * calling pcep_encode_message() thus testing the message creation and the
+ * message encoding.
+ */
+
+static struct pcep_versioning *versioning = NULL;
+
+int pcep_messages_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ return 0;
+}
+
+int pcep_messages_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+void pcep_messages_test_setup()
+{
+ versioning = create_default_pcep_versioning();
+}
+
+void pcep_messages_test_teardown()
+{
+ destroy_pcep_versioning(versioning);
+}
+
+void test_pcep_msg_create_open()
+{
+ uint8_t keepalive = 30;
+ uint8_t deadtimer = 60;
+ uint8_t sid = 255;
+
+ struct pcep_message *message =
+ pcep_msg_create_open(keepalive, deadtimer, sid);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 1);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length(PCEP_OBJ_CLASS_OPEN,
+ PCEP_OBJ_TYPE_OPEN));
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_OPEN);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ /* Just check the class and type, the rest of the hdr fields
+ * are verified in pcep-objects-test.c */
+ struct pcep_object_open *open_obj =
+ (struct pcep_object_open *)message->obj_list->head->data;
+ CU_ASSERT_EQUAL(open_obj->header.object_class, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_EQUAL(open_obj->header.object_type, PCEP_OBJ_TYPE_OPEN);
+
+ CU_ASSERT_EQUAL(open_obj->open_deadtimer, deadtimer);
+ CU_ASSERT_EQUAL(open_obj->open_keepalive, keepalive);
+ CU_ASSERT_EQUAL(open_obj->open_sid, sid);
+ CU_ASSERT_EQUAL(open_obj->open_version, PCEP_OBJECT_OPEN_VERSION);
+ pcep_msg_free_message(message);
+}
+
+
+void test_pcep_msg_create_request()
+{
+ /* First test with NULL objects */
+ struct pcep_message *message =
+ pcep_msg_create_request(NULL, NULL, NULL);
+ CU_ASSERT_PTR_NULL(message);
+
+ /* Test IPv4 */
+ struct pcep_object_rp *rp_obj =
+ pcep_obj_create_rp(0, false, false, false, false, 10, NULL);
+ struct in_addr src_addr = {}, dst_addr = {};
+ struct pcep_object_endpoints_ipv4 *ipv4_obj =
+ pcep_obj_create_endpoint_ipv4(&src_addr, &dst_addr);
+ message = pcep_msg_create_request(rp_obj, ipv4_obj, NULL);
+
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 2);
+ CU_ASSERT_EQUAL(
+ message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length_by_hdr(&rp_obj->header)
+ + pcep_object_get_length_by_hdr(&ipv4_obj->header));
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCREQ);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+ pcep_msg_free_message(message);
+
+ /* Test IPv6 */
+ rp_obj = pcep_obj_create_rp(0, false, false, false, false, 10, NULL);
+ struct in6_addr src_addr_ipv6 = {}, dst_addr_ipv6 = {};
+ struct pcep_object_endpoints_ipv6 *ipv6_obj =
+ pcep_obj_create_endpoint_ipv6(&src_addr_ipv6, &dst_addr_ipv6);
+ message = pcep_msg_create_request_ipv6(rp_obj, ipv6_obj, NULL);
+
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 2);
+ CU_ASSERT_EQUAL(
+ message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length_by_hdr(&rp_obj->header)
+ + pcep_object_get_length_by_hdr(&ipv6_obj->header));
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCREQ);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+ pcep_msg_free_message(message);
+
+ /* The objects get deleted with the message, so they need to be created
+ * again */
+ rp_obj = pcep_obj_create_rp(0, false, false, false, false, 10, NULL);
+ ipv4_obj = pcep_obj_create_endpoint_ipv4(&src_addr, &dst_addr);
+ struct pcep_object_bandwidth *bandwidth_obj =
+ pcep_obj_create_bandwidth(4.2);
+ double_linked_list *obj_list = dll_initialize();
+ dll_append(obj_list, bandwidth_obj);
+ message = pcep_msg_create_request(rp_obj, ipv4_obj, obj_list);
+
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 3);
+ CU_ASSERT_EQUAL(
+ message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length_by_hdr(&rp_obj->header)
+ + pcep_object_get_length_by_hdr(&ipv4_obj->header)
+ + pcep_object_get_length_by_hdr(
+ &bandwidth_obj->header));
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCREQ);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+ pcep_msg_free_message(message);
+}
+
+
+void test_pcep_msg_create_request_svec()
+{
+}
+
+
+void test_pcep_msg_create_reply_nopath()
+{
+ struct pcep_object_rp *rp_obj =
+ pcep_obj_create_rp(0, false, false, false, false, 10, NULL);
+ struct pcep_object_nopath *nopath_obj = pcep_obj_create_nopath(
+ false, false, PCEP_NOPATH_TLV_ERR_NO_TLV);
+ double_linked_list *obj_list = dll_initialize();
+ dll_append(obj_list, nopath_obj);
+
+ struct pcep_message *message = pcep_msg_create_reply(rp_obj, obj_list);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 2);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ (MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length_by_hdr(&rp_obj->header)
+ + pcep_object_get_length_by_hdr(&nopath_obj->header)));
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCREP);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+ pcep_msg_free_message(message);
+}
+
+
+void test_pcep_msg_create_reply()
+{
+ /* First test with NULL ero and rp objects */
+ struct pcep_message *message = pcep_msg_create_reply(NULL, NULL);
+
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 0);
+ CU_ASSERT_EQUAL(message->encoded_message_length, MESSAGE_HEADER_LENGTH);
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCREP);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+ pcep_msg_free_message(message);
+
+ double_linked_list *ero_subobj_list = dll_initialize();
+ struct pcep_object_ro_subobj *ero_subobj =
+ (struct pcep_object_ro_subobj *)
+ pcep_obj_create_ro_subobj_32label(true, 1, 10);
+ dll_append(ero_subobj_list, ero_subobj);
+ struct pcep_object_ro *ero = pcep_obj_create_ero(ero_subobj_list);
+
+ double_linked_list *object_list = dll_initialize();
+ dll_append(object_list, ero);
+ struct pcep_object_rp *rp_obj =
+ pcep_obj_create_rp(0, false, false, false, false, 10, NULL);
+ message = pcep_msg_create_reply(rp_obj, object_list);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 2);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length_by_hdr(&rp_obj->header)
+ + OBJECT_HEADER_LENGTH
+ + OBJECT_RO_SUBOBJ_HEADER_LENGTH
+ + 6 /* size of the 32label */);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCREP);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+ pcep_msg_free_message(message);
+}
+
+
+void test_pcep_msg_create_close()
+{
+ uint8_t reason = PCEP_CLOSE_REASON_UNREC_MSG;
+
+ struct pcep_message *message = pcep_msg_create_close(reason);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 1);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length(PCEP_OBJ_CLASS_CLOSE,
+ PCEP_OBJ_TYPE_CLOSE));
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_CLOSE);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ /* Just check the class and type, the rest of the hdr fields
+ * are verified in pcep-objects-test.c */
+ struct pcep_object_close *close_obj =
+ (struct pcep_object_close *)message->obj_list->head->data;
+ assert(close_obj != NULL);
+ CU_ASSERT_EQUAL(close_obj->header.object_class, PCEP_OBJ_CLASS_CLOSE);
+ CU_ASSERT_EQUAL(close_obj->header.object_type, PCEP_OBJ_TYPE_CLOSE);
+ CU_ASSERT_EQUAL(close_obj->reason, reason);
+ pcep_msg_free_message(message);
+}
+
+
+void test_pcep_msg_create_error()
+{
+ uint8_t error_type = PCEP_ERRT_RECEPTION_OF_INV_OBJECT;
+ uint8_t error_value = PCEP_ERRV_KEEPALIVEWAIT_TIMED_OUT;
+
+ struct pcep_message *message =
+ pcep_msg_create_error(error_type, error_value);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 1);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + pcep_object_get_length(PCEP_OBJ_CLASS_ERROR,
+ PCEP_OBJ_TYPE_ERROR));
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_ERROR);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ /* Just check the class and type, the rest of the hdr fields
+ * are verified in pcep-objects-test.c */
+ struct pcep_object_error *error_obj =
+ (struct pcep_object_error *)message->obj_list->head->data;
+ CU_ASSERT_EQUAL(error_obj->header.object_class, PCEP_OBJ_CLASS_ERROR);
+ CU_ASSERT_EQUAL(error_obj->header.object_type, PCEP_OBJ_TYPE_ERROR);
+
+ CU_ASSERT_EQUAL(error_obj->error_type, error_type);
+ CU_ASSERT_EQUAL(error_obj->error_value, error_value);
+ pcep_msg_free_message(message);
+}
+
+
+void test_pcep_msg_create_keepalive()
+{
+ struct pcep_message *message = pcep_msg_create_keepalive();
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 0);
+ CU_ASSERT_EQUAL(message->encoded_message_length, MESSAGE_HEADER_LENGTH);
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_KEEPALIVE);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+ pcep_msg_free_message(message);
+}
+
+void test_pcep_msg_create_report()
+{
+ double_linked_list *obj_list = dll_initialize();
+
+ /* Should return NULL if obj_list is empty */
+ struct pcep_message *message = pcep_msg_create_report(NULL);
+ CU_ASSERT_PTR_NULL(message);
+
+ struct pcep_object_lsp *lsp =
+ pcep_obj_create_lsp(100, PCEP_LSP_OPERATIONAL_UP, true, true,
+ true, true, true, NULL);
+ dll_append(obj_list, lsp);
+ message = pcep_msg_create_report(obj_list);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 1);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + lsp->header.encoded_object_length);
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_REPORT);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ pcep_msg_free_message(message);
+}
+
+void test_pcep_msg_create_update()
+{
+ double_linked_list *obj_list = dll_initialize();
+ double_linked_list *ero_subobj_list = dll_initialize();
+
+ struct pcep_message *message = pcep_msg_create_update(NULL);
+ CU_ASSERT_PTR_NULL(message);
+
+ /* Should return NULL if obj_list is empty */
+ message = pcep_msg_create_update(obj_list);
+ CU_ASSERT_PTR_NULL(message);
+ if (message != NULL) {
+ pcep_msg_free_message(message);
+ message = NULL;
+ }
+
+ struct pcep_object_srp *srp = pcep_obj_create_srp(false, 100, NULL);
+ struct pcep_object_lsp *lsp =
+ pcep_obj_create_lsp(100, PCEP_LSP_OPERATIONAL_UP, true, true,
+ true, true, true, NULL);
+ dll_append(ero_subobj_list, pcep_obj_create_ro_subobj_asn(0x0102));
+ struct pcep_object_ro *ero = pcep_obj_create_ero(ero_subobj_list);
+
+ /* Should return NULL if obj_list does not have 3 entries */
+ dll_append(obj_list, srp);
+ dll_append(obj_list, lsp);
+ message = pcep_msg_create_update(obj_list);
+ CU_ASSERT_PTR_NULL(message);
+
+ dll_append(obj_list, ero);
+ if (message != NULL) {
+ pcep_msg_free_message(message);
+ message = NULL;
+ }
+ message = pcep_msg_create_update(obj_list);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 3);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + srp->header.encoded_object_length
+ + lsp->header.encoded_object_length
+ + ero->header.encoded_object_length);
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_UPDATE);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ pcep_msg_free_message(message);
+}
+
+void test_pcep_msg_create_initiate()
+{
+ double_linked_list *obj_list = dll_initialize();
+ double_linked_list *ero_subobj_list = dll_initialize();
+
+ /* Should return NULL if obj_list is empty */
+ struct pcep_message *message = pcep_msg_create_initiate(NULL);
+ CU_ASSERT_PTR_NULL(message);
+ if (message != NULL) {
+ pcep_msg_free_message(message);
+ message = NULL;
+ }
+
+ struct pcep_object_srp *srp = pcep_obj_create_srp(false, 100, NULL);
+ struct pcep_object_lsp *lsp =
+ pcep_obj_create_lsp(100, PCEP_LSP_OPERATIONAL_UP, true, true,
+ true, true, true, NULL);
+ dll_append(ero_subobj_list, pcep_obj_create_ro_subobj_asn(0x0102));
+ struct pcep_object_ro *ero = pcep_obj_create_ero(ero_subobj_list);
+
+ /* Should return NULL if obj_list does not have 2 entries */
+ dll_append(obj_list, srp);
+ message = pcep_msg_create_initiate(obj_list);
+ CU_ASSERT_PTR_NULL(message);
+ if (message != NULL) {
+ pcep_msg_free_message(message);
+ message = NULL;
+ }
+
+ dll_append(obj_list, lsp);
+ dll_append(obj_list, ero);
+ message = pcep_msg_create_initiate(obj_list);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->msg_header);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 3);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + srp->header.encoded_object_length
+ + lsp->header.encoded_object_length
+ + ero->header.encoded_object_length);
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_INITIATE);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ pcep_msg_free_message(message);
+}
+
+void test_pcep_msg_create_notify(void)
+{
+ struct pcep_object_notify *notify_obj = pcep_obj_create_notify(
+ PCEP_NOTIFY_TYPE_PENDING_REQUEST_CANCELLED,
+ PCEP_NOTIFY_VALUE_PCC_CANCELLED_REQUEST);
+
+ /* Should return NULL if the notify obj is empty */
+ struct pcep_message *message = pcep_msg_create_notify(NULL, NULL);
+ CU_ASSERT_PTR_NULL(message);
+
+ message = pcep_msg_create_notify(notify_obj, NULL);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 1);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + notify_obj->header.encoded_object_length);
+ assert(message->msg_header != NULL);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCNOTF);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ pcep_msg_free_message(message);
+
+ struct pcep_object_rp *rp_obj =
+ pcep_obj_create_rp(0, false, false, false, false, 10, NULL);
+ double_linked_list *obj_list = dll_initialize();
+ dll_append(obj_list, rp_obj);
+ notify_obj = pcep_obj_create_notify(
+ PCEP_NOTIFY_TYPE_PENDING_REQUEST_CANCELLED,
+ PCEP_NOTIFY_VALUE_PCC_CANCELLED_REQUEST);
+
+ message = pcep_msg_create_notify(notify_obj, obj_list);
+ CU_ASSERT_PTR_NOT_NULL(message);
+ pcep_encode_message(message, versioning);
+ assert(message != NULL);
+ CU_ASSERT_PTR_NOT_NULL(message->obj_list);
+ assert(message->obj_list != NULL);
+ CU_ASSERT_EQUAL(message->obj_list->num_entries, 2);
+ CU_ASSERT_EQUAL(message->encoded_message_length,
+ MESSAGE_HEADER_LENGTH
+ + notify_obj->header.encoded_object_length
+ + rp_obj->header.encoded_object_length);
+ CU_ASSERT_EQUAL(message->msg_header->type, PCEP_TYPE_PCNOTF);
+ CU_ASSERT_EQUAL(message->msg_header->pcep_version,
+ PCEP_MESSAGE_HEADER_VERSION);
+
+ pcep_msg_free_message(message);
+}
diff --git a/pceplib/test/pcep_msg_messages_test.h b/pceplib/test/pcep_msg_messages_test.h
new file mode 100644
index 0000000..a3295c7
--- /dev/null
+++ b/pceplib/test/pcep_msg_messages_test.h
@@ -0,0 +1,48 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_MSG_MSG_TEST_H_
+#define PCEP_MSG_MSG_TEST_H_
+
+/* functions to be tested from pcep-messages.c */
+int pcep_messages_test_suite_setup(void);
+int pcep_messages_test_suite_teardown(void);
+void pcep_messages_test_setup(void);
+void pcep_messages_test_teardown(void);
+void test_pcep_msg_create_open(void);
+void test_pcep_msg_create_request(void);
+void test_pcep_msg_create_request_svec(void);
+void test_pcep_msg_create_reply_nopath(void);
+void test_pcep_msg_create_reply(void);
+void test_pcep_msg_create_close(void);
+void test_pcep_msg_create_error(void);
+void test_pcep_msg_create_keepalive(void);
+void test_pcep_msg_create_report(void);
+void test_pcep_msg_create_update(void);
+void test_pcep_msg_create_initiate(void);
+void test_pcep_msg_create_notify(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_msg_messages_tests.c b/pceplib/test/pcep_msg_messages_tests.c
new file mode 100644
index 0000000..f24a797
--- /dev/null
+++ b/pceplib/test/pcep_msg_messages_tests.c
@@ -0,0 +1,260 @@
+/*
+ * 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 <CUnit/Basic.h>
+#include <CUnit/CUnit.h>
+#include <CUnit/TestDB.h>
+
+#include "pcep_msg_messages_test.h"
+#include "pcep_msg_tools_test.h"
+#include "pcep_msg_object_error_types.h"
+#include "pcep_msg_object_error_types_test.h"
+#include "pcep_msg_tlvs_test.h"
+#include "pcep_msg_objects_test.h"
+
+
+int main(int argc, char **argv)
+{
+ /* Unused parameters cause compilation warnings */
+ (void)argc;
+ (void)argv;
+
+ CU_initialize_registry();
+
+ CU_pSuite messages_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP Messages Test Suite", pcep_messages_test_suite_setup,
+ pcep_messages_test_suite_teardown, /* suite setup and cleanup
+ function pointers */
+ pcep_messages_test_setup, pcep_messages_test_teardown);
+ CU_add_test(messages_suite, "test_pcep_msg_create_open",
+ test_pcep_msg_create_open);
+ CU_add_test(messages_suite, "test_pcep_msg_create_request",
+ test_pcep_msg_create_request);
+ CU_add_test(messages_suite, "test_pcep_msg_create_request_svec",
+ test_pcep_msg_create_request_svec);
+ CU_add_test(messages_suite, "test_pcep_msg_create_reply_nopath",
+ test_pcep_msg_create_reply_nopath);
+ CU_add_test(messages_suite, "test_pcep_msg_create_reply",
+ test_pcep_msg_create_reply);
+ CU_add_test(messages_suite, "test_pcep_msg_create_close",
+ test_pcep_msg_create_close);
+ CU_add_test(messages_suite, "test_pcep_msg_create_error",
+ test_pcep_msg_create_error);
+ CU_add_test(messages_suite, "test_pcep_msg_create_keepalive",
+ test_pcep_msg_create_keepalive);
+ CU_add_test(messages_suite, "test_pcep_msg_create_report",
+ test_pcep_msg_create_report);
+ CU_add_test(messages_suite, "test_pcep_msg_create_update",
+ test_pcep_msg_create_update);
+ CU_add_test(messages_suite, "test_pcep_msg_create_initiate",
+ test_pcep_msg_create_initiate);
+ CU_add_test(messages_suite, "test_pcep_msg_create_notify",
+ test_pcep_msg_create_notify);
+
+ CU_pSuite tlvs_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP TLVs Test Suite", pcep_tlvs_test_suite_setup,
+ pcep_tlvs_test_suite_teardown, /* suite setup and cleanup
+ function pointers */
+ pcep_tlvs_test_setup, pcep_tlvs_test_teardown);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_stateful_pce_capability",
+ test_pcep_tlv_create_stateful_pce_capability);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_speaker_entity_id",
+ test_pcep_tlv_create_speaker_entity_id);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_lsp_db_version",
+ test_pcep_tlv_create_lsp_db_version);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_path_setup_type",
+ test_pcep_tlv_create_path_setup_type);
+ CU_add_test(tlvs_suite,
+ "test_pcep_tlv_create_path_setup_type_capability",
+ test_pcep_tlv_create_path_setup_type_capability);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_sr_pce_capability",
+ test_pcep_tlv_create_sr_pce_capability);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_symbolic_path_name",
+ test_pcep_tlv_create_symbolic_path_name);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_ipv4_lsp_identifiers",
+ test_pcep_tlv_create_ipv4_lsp_identifiers);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_ipv6_lsp_identifiers",
+ test_pcep_tlv_create_ipv6_lsp_identifiers);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_srpag_pol_id_ipv4",
+ test_pcep_tlv_create_srpag_pol_id_ipv4);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_srpag_pol_id_ipv6",
+ test_pcep_tlv_create_srpag_pol_id_ipv6);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_srpag_pol_name",
+ test_pcep_tlv_create_srpag_pol_name);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_srpag_cp_id",
+ test_pcep_tlv_create_srpag_cp_id);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_srpag_cp_pref",
+ test_pcep_tlv_create_srpag_cp_pref);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_lsp_error_code",
+ test_pcep_tlv_create_lsp_error_code);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_rsvp_ipv4_error_spec",
+ test_pcep_tlv_create_rsvp_ipv4_error_spec);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_rsvp_ipv6_error_spec",
+ test_pcep_tlv_create_rsvp_ipv6_error_spec);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_nopath_vector",
+ test_pcep_tlv_create_nopath_vector);
+ CU_add_test(tlvs_suite, "test_pcep_tlv_create_arbitrary",
+ test_pcep_tlv_create_arbitrary);
+
+ CU_pSuite objects_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP Objects Test Suite", pcep_objects_test_suite_setup,
+ pcep_objects_test_suite_teardown, /* suite setup and cleanup
+ function pointers */
+ pcep_objects_test_setup, pcep_objects_test_teardown);
+ CU_add_test(objects_suite, "test_pcep_obj_create_open",
+ test_pcep_obj_create_open);
+ CU_add_test(objects_suite, "test_pcep_obj_create_open",
+ test_pcep_obj_create_open_with_tlvs);
+ CU_add_test(objects_suite, "test_pcep_obj_create_rp",
+ test_pcep_obj_create_rp);
+ CU_add_test(objects_suite, "test_pcep_obj_create_nopath",
+ test_pcep_obj_create_nopath);
+ CU_add_test(objects_suite, "test_pcep_obj_create_enpoint_ipv4",
+ test_pcep_obj_create_endpoint_ipv4);
+ CU_add_test(objects_suite, "test_pcep_obj_create_enpoint_ipv6",
+ test_pcep_obj_create_endpoint_ipv6);
+ CU_add_test(objects_suite, "test_pcep_obj_create_association_ipv4",
+ test_pcep_obj_create_association_ipv4);
+ CU_add_test(objects_suite, "test_pcep_obj_create_association_ipv6",
+ test_pcep_obj_create_association_ipv6);
+ CU_add_test(objects_suite, "test_pcep_obj_create_bandwidth",
+ test_pcep_obj_create_bandwidth);
+ CU_add_test(objects_suite, "test_pcep_obj_create_metric",
+ test_pcep_obj_create_metric);
+ CU_add_test(objects_suite, "test_pcep_obj_create_lspa",
+ test_pcep_obj_create_lspa);
+ CU_add_test(objects_suite, "test_pcep_obj_create_svec",
+ test_pcep_obj_create_svec);
+ CU_add_test(objects_suite, "test_pcep_obj_create_error",
+ test_pcep_obj_create_error);
+ CU_add_test(objects_suite, "test_pcep_obj_create_close",
+ test_pcep_obj_create_close);
+ CU_add_test(objects_suite, "test_pcep_obj_create_srp",
+ test_pcep_obj_create_srp);
+ CU_add_test(objects_suite, "test_pcep_obj_create_lsp",
+ test_pcep_obj_create_lsp);
+ CU_add_test(objects_suite, "test_pcep_obj_create_vendor_info",
+ test_pcep_obj_create_vendor_info);
+
+ CU_add_test(objects_suite, "test_pcep_obj_create_ero",
+ test_pcep_obj_create_ero);
+ CU_add_test(objects_suite, "test_pcep_obj_create_rro",
+ test_pcep_obj_create_rro);
+ CU_add_test(objects_suite, "test_pcep_obj_create_iro",
+ test_pcep_obj_create_iro);
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_ipv4",
+ test_pcep_obj_create_ro_subobj_ipv4);
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_ipv6",
+ test_pcep_obj_create_ro_subobj_ipv6);
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_unnum",
+ test_pcep_obj_create_ro_subobj_unnum);
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_32label",
+ test_pcep_obj_create_ro_subobj_32label);
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_asn",
+ test_pcep_obj_create_ro_subobj_asn);
+
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_sr_nonai",
+ test_pcep_obj_create_ro_subobj_sr_nonai);
+ CU_add_test(objects_suite,
+ "test_pcep_obj_create_ro_subobj_sr_ipv4_node",
+ test_pcep_obj_create_ro_subobj_sr_ipv4_node);
+ CU_add_test(objects_suite,
+ "test_pcep_obj_create_ro_subobj_sr_ipv6_node",
+ test_pcep_obj_create_ro_subobj_sr_ipv6_node);
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_sr_ipv4_adj",
+ test_pcep_obj_create_ro_subobj_sr_ipv4_adj);
+ CU_add_test(objects_suite, "test_pcep_obj_create_ro_subobj_sr_ipv6_adj",
+ test_pcep_obj_create_ro_subobj_sr_ipv6_adj);
+ CU_add_test(objects_suite,
+ "test_pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj",
+ test_pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj);
+ CU_add_test(objects_suite,
+ "test_pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj",
+ test_pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj);
+
+ CU_pSuite tools_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP Tools Test Suite", pcep_tools_test_suite_setup,
+ pcep_tools_test_suite_teardown, pcep_tools_test_setup,
+ pcep_tools_test_teardown);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_initiate",
+ test_pcep_msg_read_pcep_initiate);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_initiate2",
+ test_pcep_msg_read_pcep_initiate2);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_update",
+ test_pcep_msg_read_pcep_update);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_open",
+ test_pcep_msg_read_pcep_open);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_open_initiate",
+ test_pcep_msg_read_pcep_open_initiate);
+ CU_add_test(tools_suite, "test_validate_message_header",
+ test_validate_message_header);
+ CU_add_test(tools_suite, "test_validate_message_objects",
+ test_validate_message_objects);
+ CU_add_test(tools_suite, "test_validate_message_objects_invalid",
+ test_validate_message_objects_invalid);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_open_cisco_pce",
+ test_pcep_msg_read_pcep_open_cisco_pce);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_update_cisco_pce",
+ test_pcep_msg_read_pcep_update_cisco_pce);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_report_cisco_pcc",
+ test_pcep_msg_read_pcep_report_cisco_pcc);
+ CU_add_test(tools_suite, "test_pcep_msg_read_pcep_initiate_cisco_pcc",
+ test_pcep_msg_read_pcep_initiate_cisco_pcc);
+
+ CU_pSuite obj_errors_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP Object Error Types Test Suite",
+ pcep_object_error_types_test_suite_setup,
+ pcep_object_error_types_test_suite_teardown,
+ pcep_object_error_types_test_setup,
+ pcep_object_error_types_test_teardown);
+ CU_add_test(obj_errors_suite, "test_get_error_type_str",
+ test_get_error_type_str);
+ CU_add_test(obj_errors_suite, "test_get_error_value_str",
+ test_get_error_value_str);
+
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ CU_FailureRecord *failure_record = CU_get_failure_list();
+ if (failure_record != NULL) {
+ printf("\nFailed tests:\n\t [Suite] [Test] [File:line-number]\n");
+ do {
+ printf("\t [%s] [%s] [%s:%d]\n",
+ failure_record->pSuite->pName,
+ failure_record->pTest->pName,
+ failure_record->strFileName,
+ failure_record->uiLineNumber);
+ failure_record = failure_record->pNext;
+
+ } while (failure_record != NULL);
+ }
+
+ CU_pRunSummary run_summary = CU_get_run_summary();
+ int result = run_summary->nTestsFailed;
+ CU_cleanup_registry();
+
+ return result;
+}
diff --git a/pceplib/test/pcep_msg_object_error_types_test.c b/pceplib/test/pcep_msg_object_error_types_test.c
new file mode 100644
index 0000000..b146375
--- /dev/null
+++ b/pceplib/test/pcep_msg_object_error_types_test.c
@@ -0,0 +1,88 @@
+/*
+ * 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 <stdio.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_msg_object_error_types.h"
+#include "pcep_msg_object_error_types_test.h"
+#include "pcep_utils_logging.h"
+#include "pcep_utils_memory.h"
+
+int pcep_object_error_types_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ set_logging_level(LOG_DEBUG);
+ return 0;
+}
+
+int pcep_object_error_types_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+void pcep_object_error_types_test_setup(void)
+{
+}
+
+void pcep_object_error_types_test_teardown(void)
+{
+}
+
+void test_get_error_type_str()
+{
+ const char *error_type_str;
+ int i = 0;
+ for (; i < MAX_ERROR_TYPE; i++) {
+ error_type_str = get_error_type_str(i);
+ CU_ASSERT_PTR_NOT_NULL(error_type_str);
+ }
+
+ CU_ASSERT_PTR_NULL(get_error_type_str(-1));
+ CU_ASSERT_PTR_NULL(get_error_type_str(MAX_ERROR_TYPE));
+}
+
+void test_get_error_value_str()
+{
+ const char *error_value_str;
+ int i = 0, j = 0;
+
+ for (; i < MAX_ERROR_TYPE; i++) {
+ for (; j < MAX_ERROR_VALUE; j++) {
+ error_value_str = get_error_value_str(i, j);
+ CU_ASSERT_PTR_NOT_NULL(error_value_str);
+ }
+ }
+
+ CU_ASSERT_PTR_NULL(get_error_value_str(-1, 0));
+ CU_ASSERT_PTR_NULL(get_error_value_str(MAX_ERROR_TYPE, 0));
+ CU_ASSERT_PTR_NULL(get_error_value_str(1, -1));
+ CU_ASSERT_PTR_NULL(get_error_value_str(1, MAX_ERROR_VALUE));
+}
diff --git a/pceplib/test/pcep_msg_object_error_types_test.h b/pceplib/test/pcep_msg_object_error_types_test.h
new file mode 100644
index 0000000..863517d
--- /dev/null
+++ b/pceplib/test/pcep_msg_object_error_types_test.h
@@ -0,0 +1,37 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_MSG_OBJECT_ERROR_TYPES_TEST_
+#define PCEP_MSG_OBJECT_ERROR_TYPES_TEST_
+
+int pcep_object_error_types_test_suite_setup(void);
+int pcep_object_error_types_test_suite_teardown(void);
+void pcep_object_error_types_test_setup(void);
+void pcep_object_error_types_test_teardown(void);
+void test_get_error_type_str(void);
+void test_get_error_value_str(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_msg_objects_test.c b/pceplib/test/pcep_msg_objects_test.c
new file mode 100644
index 0000000..a92bbe4
--- /dev/null
+++ b/pceplib/test/pcep_msg_objects_test.c
@@ -0,0 +1,1312 @@
+/*
+ * 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 <stdlib.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_msg_encoding.h"
+#include "pcep_msg_objects.h"
+#include "pcep_msg_tools.h"
+#include "pcep_utils_memory.h"
+#include "pcep_msg_objects_test.h"
+
+/*
+ * Notice:
+ * All of these object Unit Tests encode the created objects by explicitly
+ * calling pcep_encode_object() thus testing the object creation and the object
+ * encoding. All APIs expect IPs to be in network byte order.
+ */
+
+static struct pcep_versioning *versioning = NULL;
+static uint8_t object_buf[2000];
+
+void reset_objects_buffer(void);
+
+int pcep_objects_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ return 0;
+}
+
+int pcep_objects_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+void reset_objects_buffer()
+{
+ memset(object_buf, 0, 2000);
+}
+
+void pcep_objects_test_setup()
+{
+ versioning = create_default_pcep_versioning();
+ reset_objects_buffer();
+}
+
+void pcep_objects_test_teardown()
+{
+ destroy_pcep_versioning(versioning);
+}
+
+/* Internal util verification function */
+static void verify_pcep_obj_header2(uint8_t obj_class, uint8_t obj_type,
+ uint16_t obj_length, const uint8_t *obj_buf)
+{
+ /* Object Header
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Object-Class | OT |Res|P|I| Object Length (bytes) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+ /* Not using CU_ASSERT_EQUAL here, so that in case of failure,
+ * we can provide more info in the error message. */
+ if (obj_buf[0] != obj_class) {
+ fprintf(stderr,
+ "Test failure obj_class expected [%d] found [%d]\n",
+ obj_class, obj_buf[0]);
+ CU_FAIL("Object Header Class");
+ }
+
+ uint8_t found8 = (obj_buf[1] >> 4) & 0x0f;
+ if (obj_type != found8) {
+ fprintf(stderr,
+ "Test failure obj_class [%d] obj_type expected [%d] found [%d]\n",
+ obj_class, obj_type, found8);
+ CU_FAIL("Object Header Type");
+ }
+
+ uint8_t exp8 = 0;
+ found8 = obj_buf[1] & 0x0f;
+ if (exp8 != found8) {
+ fprintf(stderr,
+ "Test failure obj_class [%d] flags expected [%d] found [%d]\n",
+ obj_class, exp8, found8);
+ CU_FAIL("Object Header Flags");
+ }
+
+ uint16_t found16 = ntohs(*((uint16_t *)(obj_buf + 2)));
+ if (obj_length != found16) {
+ fprintf(stderr,
+ "Test failure obj_class [%d] obj_length expected [%d] found [%d]\n",
+ obj_class, obj_length, found16);
+ CU_FAIL("Object Header Length");
+ }
+}
+
+/* Internal util verification function */
+static void verify_pcep_obj_header(uint8_t obj_class, uint8_t obj_type,
+ struct pcep_object_header *obj_hdr)
+{
+ assert(obj_hdr != NULL);
+ verify_pcep_obj_header2(obj_class, obj_type,
+ pcep_object_get_length_by_hdr(obj_hdr),
+ obj_hdr->encoded_object);
+}
+
+void test_pcep_obj_create_open()
+{
+ uint8_t deadtimer = 60;
+ uint8_t keepalive = 30;
+ uint8_t sid = 1;
+
+ struct pcep_object_open *open =
+ pcep_obj_create_open(keepalive, deadtimer, sid, NULL);
+
+ CU_ASSERT_PTR_NOT_NULL(open);
+ pcep_encode_object(&open->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_OPEN, PCEP_OBJ_TYPE_OPEN,
+ &open->header);
+
+ CU_ASSERT_EQUAL(open->header.encoded_object[4],
+ (PCEP_OBJECT_OPEN_VERSION << 5) & 0xe0);
+ CU_ASSERT_EQUAL(open->header.encoded_object[4] & 0x1f, 0);
+ CU_ASSERT_EQUAL(open->header.encoded_object[5], keepalive);
+ CU_ASSERT_EQUAL(open->header.encoded_object[6], deadtimer);
+ CU_ASSERT_EQUAL(open->header.encoded_object[7], sid);
+
+ pcep_obj_free_object((struct pcep_object_header *)open);
+}
+
+void test_pcep_obj_create_open_with_tlvs()
+{
+ uint8_t deadtimer = 60;
+ uint8_t keepalive = 30;
+ uint8_t sid = 1;
+ double_linked_list *tlv_list = dll_initialize();
+
+ struct pcep_object_tlv_stateful_pce_capability *tlv =
+ pcep_tlv_create_stateful_pce_capability(true, true, true, true,
+ true, true);
+ dll_append(tlv_list, tlv);
+ struct pcep_object_open *open =
+ pcep_obj_create_open(keepalive, deadtimer, sid, tlv_list);
+
+ CU_ASSERT_PTR_NOT_NULL(open);
+ assert(open != NULL);
+ pcep_encode_object(&open->header, versioning, object_buf);
+ verify_pcep_obj_header2(PCEP_OBJ_CLASS_OPEN, PCEP_OBJ_TYPE_OPEN,
+ pcep_object_get_length_by_hdr(&open->header)
+ + sizeof(uint32_t) * 2,
+ open->header.encoded_object);
+ CU_ASSERT_PTR_NOT_NULL(open->header.tlv_list);
+ assert(open->header.tlv_list != NULL);
+ CU_ASSERT_EQUAL(open->header.tlv_list->num_entries, 1);
+
+ CU_ASSERT_EQUAL(open->header.encoded_object[4],
+ (PCEP_OBJECT_OPEN_VERSION << 5) & 0xe0);
+ CU_ASSERT_EQUAL(open->header.encoded_object[4] & 0x1f, 0);
+ CU_ASSERT_EQUAL(open->header.encoded_object[5], keepalive);
+ CU_ASSERT_EQUAL(open->header.encoded_object[6], deadtimer);
+ CU_ASSERT_EQUAL(open->header.encoded_object[7], sid);
+
+ pcep_obj_free_object((struct pcep_object_header *)open);
+}
+
+void test_pcep_obj_create_rp()
+{
+ uint32_t reqid = 15;
+ uint8_t invalid_priority = 100;
+ uint8_t priority = 7;
+
+ struct pcep_object_rp *rp = pcep_obj_create_rp(
+ invalid_priority, true, false, false, true, reqid, NULL);
+ CU_ASSERT_PTR_NULL(rp);
+
+ rp = pcep_obj_create_rp(priority, true, false, false, true, reqid,
+ NULL);
+ CU_ASSERT_PTR_NOT_NULL(rp);
+ pcep_encode_object(&rp->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_RP, PCEP_OBJ_TYPE_RP,
+ &rp->header);
+
+ CU_ASSERT_EQUAL(rp->header.encoded_object[4], 0);
+ CU_ASSERT_EQUAL(rp->header.encoded_object[5], 0);
+ CU_ASSERT_EQUAL(rp->header.encoded_object[6], 0);
+ CU_ASSERT_EQUAL((rp->header.encoded_object[7] & 0x07), priority);
+ CU_ASSERT_TRUE(rp->header.encoded_object[7] & OBJECT_RP_FLAG_R);
+ CU_ASSERT_TRUE(rp->header.encoded_object[7] & OBJECT_RP_FLAG_OF);
+ CU_ASSERT_TRUE(rp->header.encoded_object[7] & ~OBJECT_RP_FLAG_B);
+ CU_ASSERT_TRUE(rp->header.encoded_object[7] & ~OBJECT_RP_FLAG_O);
+ CU_ASSERT_EQUAL(*((uint32_t *)(rp->header.encoded_object + 8)),
+ htonl(reqid));
+
+ pcep_obj_free_object((struct pcep_object_header *)rp);
+}
+
+void test_pcep_obj_create_nopath()
+{
+ uint8_t ni = 8;
+ uint32_t errorcode = 42;
+
+ struct pcep_object_nopath *nopath =
+ pcep_obj_create_nopath(ni, true, errorcode);
+
+ CU_ASSERT_PTR_NOT_NULL(nopath);
+ pcep_encode_object(&nopath->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_NOPATH, PCEP_OBJ_TYPE_NOPATH,
+ &nopath->header);
+
+ CU_ASSERT_EQUAL(nopath->header.encoded_object[4], ni);
+ CU_ASSERT_TRUE(nopath->header.encoded_object[5] & OBJECT_NOPATH_FLAG_C);
+ CU_ASSERT_EQUAL(nopath->header.encoded_object[6], 0);
+ CU_ASSERT_EQUAL(nopath->header.encoded_object[7], 0);
+
+ /* Verify the TLV */
+ assert(nopath != NULL);
+ assert(nopath->header.tlv_list != NULL);
+ CU_ASSERT_PTR_NOT_NULL(nopath->header.tlv_list);
+ struct pcep_object_tlv_nopath_vector *tlv =
+ (struct pcep_object_tlv_nopath_vector *)
+ nopath->header.tlv_list->head->data;
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, 4);
+ CU_ASSERT_EQUAL(tlv->header.type, 1);
+ CU_ASSERT_EQUAL(tlv->error_code, errorcode);
+
+ CU_ASSERT_EQUAL(*((uint16_t *)(nopath->header.encoded_object + 8)),
+ htons(PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR));
+ CU_ASSERT_EQUAL(*((uint16_t *)(nopath->header.encoded_object + 10)),
+ htons(4));
+ CU_ASSERT_EQUAL(*((uint32_t *)(nopath->header.encoded_object + 12)),
+ htonl(errorcode));
+
+ pcep_obj_free_object((struct pcep_object_header *)nopath);
+}
+void test_pcep_obj_create_association_ipv4()
+{
+
+ uint16_t all_assoc_groups = 0xffff;
+ struct in_addr src;
+ inet_pton(AF_INET, "192.168.1.2", &src);
+
+ struct pcep_object_association_ipv4 *assoc =
+ pcep_obj_create_association_ipv4(
+ false, PCEP_ASSOCIATION_TYPE_SR_POLICY_ASSOCIATION_TYPE,
+ all_assoc_groups, src);
+ CU_ASSERT_PTR_NOT_NULL(assoc);
+ assert(assoc != NULL);
+ CU_ASSERT_EQUAL(assoc->association_type,
+ PCEP_ASSOCIATION_TYPE_SR_POLICY_ASSOCIATION_TYPE);
+ CU_ASSERT_EQUAL(assoc->association_id, all_assoc_groups);
+ CU_ASSERT_EQUAL(assoc->header.object_class, PCEP_OBJ_CLASS_ASSOCIATION);
+ CU_ASSERT_EQUAL(assoc->header.object_type,
+ PCEP_OBJ_TYPE_ASSOCIATION_IPV4);
+ CU_ASSERT_EQUAL(assoc->src.s_addr, src.s_addr);
+
+ pcep_obj_free_object((struct pcep_object_header *)assoc);
+}
+
+void test_pcep_obj_create_association_ipv6()
+{
+ uint32_t all_assoc_groups = 0xffff;
+ struct in6_addr src;
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &src);
+
+ struct pcep_object_association_ipv6 *assoc =
+ pcep_obj_create_association_ipv6(
+ false, PCEP_ASSOCIATION_TYPE_SR_POLICY_ASSOCIATION_TYPE,
+ all_assoc_groups, src);
+ CU_ASSERT_PTR_NOT_NULL(assoc);
+ assert(assoc != NULL);
+ CU_ASSERT_EQUAL(assoc->association_type,
+ PCEP_ASSOCIATION_TYPE_SR_POLICY_ASSOCIATION_TYPE);
+ CU_ASSERT_EQUAL(assoc->association_id, all_assoc_groups);
+ CU_ASSERT_EQUAL(assoc->header.object_class, PCEP_OBJ_CLASS_ASSOCIATION);
+ CU_ASSERT_EQUAL(assoc->header.object_type,
+ PCEP_OBJ_TYPE_ASSOCIATION_IPV6);
+ CU_ASSERT_EQUAL(assoc->src.__in6_u.__u6_addr32[0],
+ (src.__in6_u.__u6_addr32[0]));
+ CU_ASSERT_EQUAL(assoc->src.__in6_u.__u6_addr32[1],
+ (src.__in6_u.__u6_addr32[1]));
+ CU_ASSERT_EQUAL(assoc->src.__in6_u.__u6_addr32[2],
+ (src.__in6_u.__u6_addr32[2]));
+ CU_ASSERT_EQUAL(assoc->src.__in6_u.__u6_addr32[3],
+ (src.__in6_u.__u6_addr32[3]));
+
+ pcep_obj_free_object((struct pcep_object_header *)assoc);
+}
+
+void test_pcep_obj_create_endpoint_ipv4()
+{
+ struct in_addr src_ipv4, dst_ipv4;
+ inet_pton(AF_INET, "192.168.1.2", &src_ipv4);
+ inet_pton(AF_INET, "172.168.1.2", &dst_ipv4);
+
+ struct pcep_object_endpoints_ipv4 *ipv4 =
+ pcep_obj_create_endpoint_ipv4(NULL, NULL);
+ CU_ASSERT_PTR_NULL(ipv4);
+
+ ipv4 = pcep_obj_create_endpoint_ipv4(&src_ipv4, NULL);
+ CU_ASSERT_PTR_NULL(ipv4);
+
+ ipv4 = pcep_obj_create_endpoint_ipv4(NULL, &dst_ipv4);
+ CU_ASSERT_PTR_NULL(ipv4);
+
+ ipv4 = pcep_obj_create_endpoint_ipv4(&src_ipv4, &dst_ipv4);
+ CU_ASSERT_PTR_NOT_NULL(ipv4);
+ pcep_encode_object(&ipv4->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_ENDPOINTS,
+ PCEP_OBJ_TYPE_ENDPOINT_IPV4, &ipv4->header);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ipv4->header.encoded_object + 4)),
+ src_ipv4.s_addr);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ipv4->header.encoded_object + 8)),
+ dst_ipv4.s_addr);
+
+ pcep_obj_free_object((struct pcep_object_header *)ipv4);
+}
+
+void test_pcep_obj_create_endpoint_ipv6()
+{
+ struct in6_addr src_ipv6, dst_ipv6;
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &src_ipv6);
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:8446", &dst_ipv6);
+
+ struct pcep_object_endpoints_ipv6 *ipv6 =
+ pcep_obj_create_endpoint_ipv6(NULL, NULL);
+ CU_ASSERT_PTR_NULL(ipv6);
+
+ ipv6 = pcep_obj_create_endpoint_ipv6(&src_ipv6, NULL);
+ CU_ASSERT_PTR_NULL(ipv6);
+
+ ipv6 = pcep_obj_create_endpoint_ipv6(NULL, &dst_ipv6);
+ CU_ASSERT_PTR_NULL(ipv6);
+
+ ipv6 = pcep_obj_create_endpoint_ipv6(&src_ipv6, &dst_ipv6);
+ CU_ASSERT_PTR_NOT_NULL(ipv6);
+ pcep_encode_object(&ipv6->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_ENDPOINTS,
+ PCEP_OBJ_TYPE_ENDPOINT_IPV6, &ipv6->header);
+ uint32_t *uint32_ptr = (uint32_t *)(ipv6->header.encoded_object + 4);
+ CU_ASSERT_EQUAL(uint32_ptr[0], src_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[1], src_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], src_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], src_ipv6.__in6_u.__u6_addr32[3]);
+ CU_ASSERT_EQUAL(uint32_ptr[4], dst_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[5], dst_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[6], dst_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[7], dst_ipv6.__in6_u.__u6_addr32[3]);
+
+ pcep_obj_free_object((struct pcep_object_header *)ipv6);
+}
+
+void test_pcep_obj_create_bandwidth()
+{
+ /* 1.8 => binary 1.11001101
+ * exponent = 127 => 0111 1111
+ * fraction = 1100 1101 0000 0000 0000 000 */
+ float bandwidth = 1.8;
+
+ struct pcep_object_bandwidth *bw = pcep_obj_create_bandwidth(bandwidth);
+
+ CU_ASSERT_PTR_NOT_NULL(bw);
+ pcep_encode_object(&bw->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_BANDWIDTH,
+ PCEP_OBJ_TYPE_BANDWIDTH_REQ, &bw->header);
+ CU_ASSERT_EQUAL(bw->header.encoded_object[4], 0x3f);
+ CU_ASSERT_EQUAL(bw->header.encoded_object[5], 0xe6);
+ CU_ASSERT_EQUAL(bw->header.encoded_object[6], 0x66);
+ CU_ASSERT_EQUAL(bw->header.encoded_object[7], 0x66);
+
+ pcep_obj_free_object((struct pcep_object_header *)bw);
+}
+
+void test_pcep_obj_create_metric()
+{
+ uint8_t type = PCEP_METRIC_BORDER_NODE_COUNT;
+ /* https://en.wikipedia.org/wiki/IEEE_754-1985
+ * 0.15625 = 1/8 + 1/32 = binary 0.00101 = 1.01 x 10^-3
+ * Exponent bias = 127, so exponent = (127-3) = 124 = 0111 1100
+ * Sign Exponent Fraction
+ * (8 bits) (23 bits)
+ * 0.15625 => 0 0111 1100 010 0000 ... 0000 */
+ float value = 0.15625;
+
+ struct pcep_object_metric *metric =
+ pcep_obj_create_metric(type, true, true, value);
+
+ CU_ASSERT_PTR_NOT_NULL(metric);
+ pcep_encode_object(&metric->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_METRIC, PCEP_OBJ_TYPE_METRIC,
+ &metric->header);
+ CU_ASSERT_EQUAL(metric->header.encoded_object[4], 0);
+ CU_ASSERT_EQUAL(metric->header.encoded_object[5], 0);
+ CU_ASSERT_TRUE(metric->header.encoded_object[6] & OBJECT_METRIC_FLAC_B);
+ CU_ASSERT_TRUE(metric->header.encoded_object[6] & OBJECT_METRIC_FLAC_C);
+ CU_ASSERT_EQUAL(metric->header.encoded_object[7], type);
+ /* See comments above for explanation of these values */
+ CU_ASSERT_EQUAL(metric->header.encoded_object[8], 0x3e);
+ CU_ASSERT_EQUAL(metric->header.encoded_object[9], 0x20);
+ CU_ASSERT_EQUAL(metric->header.encoded_object[10], 0x00);
+ CU_ASSERT_EQUAL(metric->header.encoded_object[11], 0x00);
+
+ pcep_obj_free_object((struct pcep_object_header *)metric);
+}
+
+void test_pcep_obj_create_lspa()
+{
+ uint32_t exclude_any = 10;
+ uint32_t include_any = 20;
+ uint32_t include_all = 30;
+ uint8_t prio = 0;
+ uint8_t hold_prio = 10;
+
+ struct pcep_object_lspa *lspa = pcep_obj_create_lspa(
+ exclude_any, include_any, include_all, prio, hold_prio, true);
+
+ CU_ASSERT_PTR_NOT_NULL(lspa);
+ pcep_encode_object(&lspa->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_LSPA, PCEP_OBJ_TYPE_LSPA,
+ &lspa->header);
+ uint32_t *uint32_ptr = (uint32_t *)(lspa->header.encoded_object + 4);
+ CU_ASSERT_EQUAL(uint32_ptr[0], htonl(exclude_any));
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(include_any));
+ CU_ASSERT_EQUAL(uint32_ptr[2], htonl(include_all));
+ CU_ASSERT_EQUAL(lspa->header.encoded_object[16], prio);
+ CU_ASSERT_EQUAL(lspa->header.encoded_object[17], hold_prio);
+ CU_ASSERT_TRUE(lspa->header.encoded_object[18] & OBJECT_LSPA_FLAG_L);
+ CU_ASSERT_EQUAL(lspa->header.encoded_object[19], 0);
+
+ pcep_obj_free_object((struct pcep_object_header *)lspa);
+}
+
+void test_pcep_obj_create_svec()
+{
+ struct pcep_object_svec *svec =
+ pcep_obj_create_svec(true, true, true, NULL);
+ CU_ASSERT_PTR_NULL(svec);
+
+ double_linked_list *id_list = dll_initialize();
+ uint32_t *uint32_ptr =
+ pceplib_malloc(PCEPLIB_MESSAGES, sizeof(uint32_t));
+ *uint32_ptr = 10;
+ dll_append(id_list, uint32_ptr);
+
+ svec = pcep_obj_create_svec(true, true, true, id_list);
+ CU_ASSERT_PTR_NOT_NULL(svec);
+ assert(svec != NULL);
+ pcep_encode_object(&svec->header, versioning, object_buf);
+ verify_pcep_obj_header2(PCEP_OBJ_CLASS_SVEC, PCEP_OBJ_TYPE_SVEC,
+ (OBJECT_HEADER_LENGTH + sizeof(uint32_t) * 2),
+ svec->header.encoded_object);
+ CU_ASSERT_EQUAL(svec->header.encoded_object[4], 0);
+ CU_ASSERT_EQUAL(svec->header.encoded_object[5], 0);
+ CU_ASSERT_EQUAL(svec->header.encoded_object[6], 0);
+ CU_ASSERT_TRUE(svec->header.encoded_object[7] & OBJECT_SVEC_FLAG_S);
+ CU_ASSERT_TRUE(svec->header.encoded_object[7] & OBJECT_SVEC_FLAG_N);
+ CU_ASSERT_TRUE(svec->header.encoded_object[7] & OBJECT_SVEC_FLAG_L);
+ CU_ASSERT_EQUAL(*((uint32_t *)(svec->header.encoded_object + 8)),
+ htonl(*uint32_ptr));
+
+ pcep_obj_free_object((struct pcep_object_header *)svec);
+}
+
+void test_pcep_obj_create_error()
+{
+ uint8_t error_type = PCEP_ERRT_SESSION_FAILURE;
+ uint8_t error_value = PCEP_ERRV_RECVD_INVALID_OPEN_MSG;
+
+ struct pcep_object_error *error =
+ pcep_obj_create_error(error_type, error_value);
+
+ CU_ASSERT_PTR_NOT_NULL(error);
+ pcep_encode_object(&error->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_ERROR, PCEP_OBJ_TYPE_ERROR,
+ &error->header);
+ CU_ASSERT_EQUAL(error->header.encoded_object[4], 0);
+ CU_ASSERT_EQUAL(error->header.encoded_object[5], 0);
+ CU_ASSERT_EQUAL(error->header.encoded_object[6], error_type);
+ CU_ASSERT_EQUAL(error->header.encoded_object[7], error_value);
+
+ pcep_obj_free_object((struct pcep_object_header *)error);
+}
+
+void test_pcep_obj_create_close()
+{
+ uint8_t reason = PCEP_CLOSE_REASON_DEADTIMER;
+
+ struct pcep_object_close *close = pcep_obj_create_close(reason);
+
+ CU_ASSERT_PTR_NOT_NULL(close);
+ pcep_encode_object(&close->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_CLOSE, PCEP_OBJ_TYPE_CLOSE,
+ &close->header);
+ CU_ASSERT_EQUAL(close->header.encoded_object[4], 0);
+ CU_ASSERT_EQUAL(close->header.encoded_object[5], 0);
+ CU_ASSERT_EQUAL(close->header.encoded_object[6], 0);
+ CU_ASSERT_EQUAL(close->header.encoded_object[7], reason);
+
+ pcep_obj_free_object((struct pcep_object_header *)close);
+}
+
+void test_pcep_obj_create_srp()
+{
+ bool lsp_remove = true;
+ uint32_t srp_id_number = 0x89674523;
+ struct pcep_object_srp *srp =
+ pcep_obj_create_srp(lsp_remove, srp_id_number, NULL);
+
+ CU_ASSERT_PTR_NOT_NULL(srp);
+ pcep_encode_object(&srp->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_SRP, PCEP_OBJ_TYPE_SRP,
+ &srp->header);
+ CU_ASSERT_EQUAL(srp->header.encoded_object[4], 0);
+ CU_ASSERT_EQUAL(srp->header.encoded_object[5], 0);
+ CU_ASSERT_EQUAL(srp->header.encoded_object[6], 0);
+ CU_ASSERT_TRUE(srp->header.encoded_object[7] & OBJECT_SRP_FLAG_R);
+ CU_ASSERT_EQUAL(*((uint32_t *)(srp->header.encoded_object + 8)),
+ htonl(srp_id_number));
+
+ pcep_obj_free_object((struct pcep_object_header *)srp);
+}
+
+void test_pcep_obj_create_lsp()
+{
+ uint32_t plsp_id = 0x000fffff;
+ enum pcep_lsp_operational_status status = PCEP_LSP_OPERATIONAL_ACTIVE;
+ bool c_flag = true;
+ bool a_flag = true;
+ bool r_flag = true;
+ bool s_flag = true;
+ bool d_flag = true;
+
+ /* Should return for invalid plsp_id */
+ struct pcep_object_lsp *lsp =
+ pcep_obj_create_lsp(0x001fffff, status, c_flag, a_flag, r_flag,
+ s_flag, d_flag, NULL);
+ CU_ASSERT_PTR_NULL(lsp);
+
+ /* Should return for invalid status */
+ lsp = pcep_obj_create_lsp(plsp_id, 8, c_flag, a_flag, r_flag, s_flag,
+ d_flag, NULL);
+ CU_ASSERT_PTR_NULL(lsp);
+
+ lsp = pcep_obj_create_lsp(plsp_id, status, c_flag, a_flag, r_flag,
+ s_flag, d_flag, NULL);
+
+ CU_ASSERT_PTR_NOT_NULL(lsp);
+ pcep_encode_object(&lsp->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_LSP, PCEP_OBJ_TYPE_LSP,
+ &lsp->header);
+ CU_ASSERT_EQUAL((ntohl(*((uint32_t *)(lsp->header.encoded_object + 4)))
+ >> 12) & 0x000fffff,
+ plsp_id);
+ CU_ASSERT_EQUAL((lsp->header.encoded_object[7] >> 4) & 0x07, status);
+ CU_ASSERT_TRUE(lsp->header.encoded_object[7] & OBJECT_LSP_FLAG_A);
+ CU_ASSERT_TRUE(lsp->header.encoded_object[7] & OBJECT_LSP_FLAG_C);
+ CU_ASSERT_TRUE(lsp->header.encoded_object[7] & OBJECT_LSP_FLAG_D);
+ CU_ASSERT_TRUE(lsp->header.encoded_object[7] & OBJECT_LSP_FLAG_R);
+ CU_ASSERT_TRUE(lsp->header.encoded_object[7] & OBJECT_LSP_FLAG_S);
+
+ pcep_obj_free_object((struct pcep_object_header *)lsp);
+}
+
+void test_pcep_obj_create_vendor_info()
+{
+ uint32_t enterprise_number = 0x01020304;
+ uint32_t enterprise_specific_info = 0x05060708;
+
+ struct pcep_object_vendor_info *obj = pcep_obj_create_vendor_info(
+ enterprise_number, enterprise_specific_info);
+
+ CU_ASSERT_PTR_NOT_NULL(obj);
+ pcep_encode_object(&obj->header, versioning, object_buf);
+ verify_pcep_obj_header(PCEP_OBJ_CLASS_VENDOR_INFO,
+ PCEP_OBJ_TYPE_VENDOR_INFO, &obj->header);
+ uint32_t *uint32_ptr = (uint32_t *)(obj->header.encoded_object + 4);
+ CU_ASSERT_EQUAL(uint32_ptr[0], htonl(enterprise_number));
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(enterprise_specific_info));
+
+ pcep_obj_free_object((struct pcep_object_header *)obj);
+}
+
+/* Internal test function. The only difference between pcep_obj_create_ero(),
+ * pcep_obj_create_iro(), and pcep_obj_create_rro() is the object_class
+ * and the object_type.
+ */
+typedef struct pcep_object_ro *(*ro_func)(double_linked_list *);
+static void test_pcep_obj_create_object_common(ro_func func_to_test,
+ uint8_t object_class,
+ uint8_t object_type)
+{
+ double_linked_list *ero_list = dll_initialize();
+
+ struct pcep_object_ro *ero = func_to_test(NULL);
+ CU_ASSERT_PTR_NOT_NULL(ero);
+ assert(ero != NULL);
+ pcep_encode_object(&ero->header, versioning, object_buf);
+ verify_pcep_obj_header2(object_class, object_type, OBJECT_HEADER_LENGTH,
+ ero->header.encoded_object);
+ pcep_obj_free_object((struct pcep_object_header *)ero);
+
+ reset_objects_buffer();
+ ero = func_to_test(ero_list);
+ CU_ASSERT_PTR_NOT_NULL(ero);
+ assert(ero != NULL);
+ pcep_encode_object(&ero->header, versioning, object_buf);
+ verify_pcep_obj_header2(object_class, object_type, OBJECT_HEADER_LENGTH,
+ ero->header.encoded_object);
+ pcep_obj_free_object((struct pcep_object_header *)ero);
+
+ reset_objects_buffer();
+ struct pcep_ro_subobj_32label *ro_subobj =
+ pcep_obj_create_ro_subobj_32label(false, 0, 101);
+ ero_list = dll_initialize();
+ dll_append(ero_list, ro_subobj);
+ ero = func_to_test(ero_list);
+ CU_ASSERT_PTR_NOT_NULL(ero);
+ assert(ero != NULL);
+ pcep_encode_object(&ero->header, versioning, object_buf);
+ /* 4 bytes for obj header +
+ * 2 bytes for ro_subobj header +
+ * 2 bytes for lable c-type and flags +
+ * 4 bytes for label */
+ verify_pcep_obj_header2(object_class, object_type,
+ OBJECT_HEADER_LENGTH + sizeof(uint32_t) * 2,
+ ero->header.encoded_object);
+ pcep_obj_free_object((struct pcep_object_header *)ero);
+}
+
+void test_pcep_obj_create_ero()
+{
+ test_pcep_obj_create_object_common(
+ pcep_obj_create_ero, PCEP_OBJ_CLASS_ERO, PCEP_OBJ_TYPE_ERO);
+}
+
+void test_pcep_obj_create_rro()
+{
+ test_pcep_obj_create_object_common(
+ pcep_obj_create_rro, PCEP_OBJ_CLASS_RRO, PCEP_OBJ_TYPE_RRO);
+}
+
+void test_pcep_obj_create_iro()
+{
+ test_pcep_obj_create_object_common(
+ pcep_obj_create_iro, PCEP_OBJ_CLASS_IRO, PCEP_OBJ_TYPE_IRO);
+}
+
+/* Internal util function to wrap an RO Subobj in a RO and encode it */
+static struct pcep_object_ro *encode_ro_subobj(struct pcep_object_ro_subobj *sr)
+{
+ double_linked_list *sr_subobj_list = dll_initialize();
+ dll_append(sr_subobj_list, sr);
+ struct pcep_object_ro *ro = pcep_obj_create_ero(sr_subobj_list);
+ pcep_encode_object(&ro->header, versioning, object_buf);
+
+ return ro;
+}
+
+static void verify_pcep_obj_ro_header(struct pcep_object_ro *ro,
+ struct pcep_object_ro_subobj *ro_subobj,
+ uint8_t ro_subobj_type, bool loose_hop,
+ uint16_t length)
+{
+ (void)ro_subobj;
+
+ verify_pcep_obj_header2(PCEP_OBJ_CLASS_ERO, PCEP_OBJ_TYPE_ERO, length,
+ ro->header.encoded_object);
+
+ /* TODO consider printing the stack trace:
+ * https://stackoverflow.com/questions/105659/how-can-one-grab-a-stack-trace-in-c
+ */
+
+ /* Not using CU_ASSERT_EQUAL here, so that in case of failure,
+ * we can provide more info in the error message. */
+ uint8_t found_type = (ro->header.encoded_object[4]
+ & 0x7f); /* remove the Loose hop bit */
+ if (found_type != ro_subobj_type) {
+ fprintf(stderr,
+ "Test failure ro_sub_obj_type expected [%d] found [%d]\n",
+ ro_subobj_type, found_type);
+ CU_FAIL("Sub Object Header Type");
+ }
+
+ bool loose_hop_found = (ro->header.encoded_object[4] & 0x80);
+ if (loose_hop != loose_hop_found) {
+ fprintf(stderr,
+ "Test failure ro_sub_obj Loose Hop bit expected [%d] found [%d]\n",
+ loose_hop, loose_hop_found);
+ CU_FAIL("Sub Object Header Loose Hop bit");
+ }
+
+ if (length - 4 != ro->header.encoded_object[5]) {
+ fprintf(stderr,
+ "Test failure ro_sub_obj length expected [%d] found [%d]\n",
+ length - 4, ro->header.encoded_object[5]);
+ CU_FAIL("Sub Object Length");
+ }
+}
+
+static void
+verify_pcep_obj_ro_sr_header(struct pcep_object_ro *ro,
+ struct pcep_object_ro_subobj *ro_subobj,
+ uint8_t nai_type, bool loose_hop, uint16_t length)
+{
+ verify_pcep_obj_ro_header(ro, ro_subobj, RO_SUBOBJ_TYPE_SR, loose_hop,
+ length);
+ uint8_t found_nai_type = ((ro->header.encoded_object[6] >> 4) & 0x0f);
+ if (nai_type != found_nai_type) {
+ fprintf(stderr,
+ "Test failure ro_sr_sub_obj nai_type expected [%d] found [%d]\n",
+ nai_type, found_nai_type);
+ CU_FAIL("Sub Object SR NAI Type");
+ }
+}
+
+void test_pcep_obj_create_ro_subobj_ipv4()
+{
+ struct in_addr ro_ipv4;
+ inet_pton(AF_INET, "192.168.1.2", &ro_ipv4);
+ uint8_t prefix_len = 8;
+
+ struct pcep_ro_subobj_ipv4 *ipv4 =
+ pcep_obj_create_ro_subobj_ipv4(true, NULL, prefix_len, false);
+ CU_ASSERT_PTR_NULL(ipv4);
+
+ ipv4 = pcep_obj_create_ro_subobj_ipv4(false, &ro_ipv4, prefix_len,
+ true);
+ CU_ASSERT_PTR_NOT_NULL(ipv4);
+ struct pcep_object_ro *ro = encode_ro_subobj(&ipv4->ro_subobj);
+ verify_pcep_obj_ro_header(ro, &ipv4->ro_subobj, RO_SUBOBJ_TYPE_IPV4,
+ false, sizeof(uint32_t) * 3);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 6)),
+ ro_ipv4.s_addr);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[10], prefix_len);
+ CU_ASSERT_TRUE(ro->header.encoded_object[11]
+ & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ reset_objects_buffer();
+ ipv4 = pcep_obj_create_ro_subobj_ipv4(true, &ro_ipv4, prefix_len,
+ false);
+ CU_ASSERT_PTR_NOT_NULL(ipv4);
+ ro = encode_ro_subobj(&ipv4->ro_subobj);
+ verify_pcep_obj_ro_header(ro, &ipv4->ro_subobj, RO_SUBOBJ_TYPE_IPV4,
+ true, sizeof(uint32_t) * 3);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 6)),
+ ro_ipv4.s_addr);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[10], prefix_len);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[11], 0);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_ipv6()
+{
+ struct in6_addr ro_ipv6;
+ uint8_t prefix_len = 16;
+
+ struct pcep_ro_subobj_ipv6 *ipv6 =
+ pcep_obj_create_ro_subobj_ipv6(true, NULL, prefix_len, true);
+ CU_ASSERT_PTR_NULL(ipv6);
+
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &ro_ipv6);
+ ipv6 = pcep_obj_create_ro_subobj_ipv6(false, &ro_ipv6, prefix_len,
+ true);
+ CU_ASSERT_PTR_NOT_NULL(ipv6);
+ struct pcep_object_ro *ro = encode_ro_subobj(&ipv6->ro_subobj);
+ verify_pcep_obj_ro_header(ro, &ipv6->ro_subobj, RO_SUBOBJ_TYPE_IPV6,
+ false, sizeof(uint32_t) * 6);
+ uint32_t *uint32_ptr = (uint32_t *)(ro->header.encoded_object + 6);
+ CU_ASSERT_EQUAL(uint32_ptr[0], ro_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[1], ro_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], ro_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], ro_ipv6.__in6_u.__u6_addr32[3]);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[22], prefix_len);
+ CU_ASSERT_TRUE(ro->header.encoded_object[23]
+ & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ reset_objects_buffer();
+ ipv6 = pcep_obj_create_ro_subobj_ipv6(true, &ro_ipv6, prefix_len,
+ false);
+ CU_ASSERT_PTR_NOT_NULL(ipv6);
+ ro = encode_ro_subobj(&ipv6->ro_subobj);
+ verify_pcep_obj_ro_header(ro, &ipv6->ro_subobj, RO_SUBOBJ_TYPE_IPV6,
+ true, sizeof(uint32_t) * 6);
+ uint32_ptr = (uint32_t *)(ro->header.encoded_object + 6);
+ CU_ASSERT_EQUAL(uint32_ptr[0], ro_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[1], ro_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], ro_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], ro_ipv6.__in6_u.__u6_addr32[3]);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[22], prefix_len);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[23], 0);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_unnum()
+{
+ struct in_addr router_id;
+ uint32_t if_id = 123;
+
+ struct pcep_ro_subobj_unnum *unnum =
+ pcep_obj_create_ro_subobj_unnum(NULL, if_id);
+ CU_ASSERT_PTR_NULL(unnum);
+
+ inet_pton(AF_INET, "192.168.1.2", &router_id);
+ unnum = pcep_obj_create_ro_subobj_unnum(&router_id, if_id);
+ CU_ASSERT_PTR_NOT_NULL(unnum);
+ struct pcep_object_ro *ro = encode_ro_subobj(&unnum->ro_subobj);
+ verify_pcep_obj_ro_header(ro, &unnum->ro_subobj, RO_SUBOBJ_TYPE_UNNUM,
+ false, sizeof(uint32_t) * 4);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[6], 0);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[7], 0);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 8)),
+ router_id.s_addr);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 12)),
+ htonl(if_id));
+
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_32label()
+{
+ uint8_t class_type = 1;
+ uint32_t label = 0xeeffaabb;
+
+ struct pcep_ro_subobj_32label *label32 =
+ pcep_obj_create_ro_subobj_32label(true, class_type, label);
+ CU_ASSERT_PTR_NOT_NULL(label32);
+ struct pcep_object_ro *ro = encode_ro_subobj(&label32->ro_subobj);
+ verify_pcep_obj_ro_header(ro, &label32->ro_subobj, RO_SUBOBJ_TYPE_LABEL,
+ false, sizeof(uint32_t) * 3);
+ CU_ASSERT_TRUE(ro->header.encoded_object[6]
+ & OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL);
+ CU_ASSERT_EQUAL(ro->header.encoded_object[7], class_type);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 8)),
+ htonl(label));
+
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_asn()
+{
+ uint16_t asn = 0x0102;
+
+ struct pcep_ro_subobj_asn *asn_obj = pcep_obj_create_ro_subobj_asn(asn);
+ CU_ASSERT_PTR_NOT_NULL(asn_obj);
+ struct pcep_object_ro *ro = encode_ro_subobj(&asn_obj->ro_subobj);
+ verify_pcep_obj_ro_header(ro, &asn_obj->ro_subobj, RO_SUBOBJ_TYPE_ASN,
+ false, sizeof(uint32_t) * 2);
+ CU_ASSERT_EQUAL(*((uint16_t *)(ro->header.encoded_object + 6)),
+ htons(asn));
+
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_sr_nonai()
+{
+ uint32_t sid = 0x01020304;
+
+ struct pcep_ro_subobj_sr *sr =
+ pcep_obj_create_ro_subobj_sr_nonai(false, sid, false, false);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ struct pcep_object_ro *ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_ABSENT, false,
+ sizeof(uint32_t) * 3);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_M);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ reset_objects_buffer();
+ sr = pcep_obj_create_ro_subobj_sr_nonai(true, sid, true, true);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_ABSENT, true,
+ sizeof(uint32_t) * 3);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_M);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_sr_ipv4_node()
+{
+ uint32_t sid = 0x01020304;
+ struct in_addr ipv4_node_id;
+ inet_pton(AF_INET, "192.168.1.2", &ipv4_node_id);
+
+ /* (loose_hop, sid_absent, c_flag, m_flag, sid, ipv4_node_id) */
+ struct pcep_ro_subobj_sr *sr = pcep_obj_create_ro_subobj_sr_ipv4_node(
+ true, false, true, true, sid, NULL);
+ CU_ASSERT_PTR_NULL(sr);
+
+ /* Test the sid is absent */
+ sr = pcep_obj_create_ro_subobj_sr_ipv4_node(true, true, false, false,
+ sid, &ipv4_node_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ assert(sr != NULL);
+ struct pcep_object_ro *ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV4_NODE, true,
+ sizeof(uint32_t) * 3);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_M);
+ CU_ASSERT_EQUAL(sr->sid, 0);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 8)),
+ ipv4_node_id.s_addr);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ /* Test the sid is present */
+ reset_objects_buffer();
+ inet_pton(AF_INET, "192.168.1.2", &ipv4_node_id);
+ sr = pcep_obj_create_ro_subobj_sr_ipv4_node(false, false, true, true,
+ sid, &ipv4_node_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ assert(sr != NULL);
+ ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV4_NODE, false,
+ sizeof(uint32_t) * 4);
+ assert(ro != NULL);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_M);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 8)),
+ htonl(sid));
+ CU_ASSERT_EQUAL(*((uint32_t *)(ro->header.encoded_object + 12)),
+ ipv4_node_id.s_addr);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_sr_ipv6_node()
+{
+ uint32_t sid = 0x01020304;
+ struct in6_addr ipv6_node_id;
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &ipv6_node_id);
+
+ /* (loose_hop, sid_absent, c_flag, m_flag, sid, ipv6_node_id) */
+ struct pcep_ro_subobj_sr *sr = pcep_obj_create_ro_subobj_sr_ipv6_node(
+ false, true, true, true, sid, NULL);
+ CU_ASSERT_PTR_NULL(sr);
+
+ /* Test the sid is absent */
+ sr = pcep_obj_create_ro_subobj_sr_ipv6_node(true, true, true, true, sid,
+ &ipv6_node_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ struct pcep_object_ro *ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV6_NODE, true,
+ sizeof(uint32_t) * 6);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_M);
+ uint32_t *uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], ipv6_node_id.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[1], ipv6_node_id.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], ipv6_node_id.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], ipv6_node_id.__in6_u.__u6_addr32[3]);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ /* Test the sid is present */
+ reset_objects_buffer();
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &ipv6_node_id);
+ sr = pcep_obj_create_ro_subobj_sr_ipv6_node(false, false, true, true,
+ sid, &ipv6_node_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV6_NODE, false,
+ sizeof(uint32_t) * 7);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_M);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], htonl(sid));
+ CU_ASSERT_EQUAL(uint32_ptr[1], ipv6_node_id.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], ipv6_node_id.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], ipv6_node_id.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[4], ipv6_node_id.__in6_u.__u6_addr32[3]);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_sr_ipv4_adj()
+{
+ struct in_addr local_ipv4;
+ struct in_addr remote_ipv4;
+ inet_pton(AF_INET, "192.168.1.2", &local_ipv4);
+ inet_pton(AF_INET, "172.168.1.2", &remote_ipv4);
+
+ uint32_t sid = ENCODE_SR_ERO_SID(3, 7, 0, 188);
+ CU_ASSERT_EQUAL(sid, 16060);
+
+ /* (loose_hop, sid_absent, c_flag, m_flag, sid, local_ipv4, remote_ipv4)
+ */
+ struct pcep_ro_subobj_sr *sr = pcep_obj_create_ro_subobj_sr_ipv4_adj(
+ false, true, true, true, sid, NULL, NULL);
+ CU_ASSERT_PTR_NULL(sr);
+
+ sr = pcep_obj_create_ro_subobj_sr_ipv4_adj(false, true, true, true, sid,
+ &local_ipv4, NULL);
+ CU_ASSERT_PTR_NULL(sr);
+
+ sr = pcep_obj_create_ro_subobj_sr_ipv4_adj(false, true, true, true, sid,
+ NULL, &remote_ipv4);
+ CU_ASSERT_PTR_NULL(sr);
+
+ /* Test the sid is absent */
+ sr = pcep_obj_create_ro_subobj_sr_ipv4_adj(true, true, true, true, sid,
+ &local_ipv4, &remote_ipv4);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ struct pcep_object_ro *ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY, true,
+ sizeof(uint32_t) * 4);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_M);
+ assert(sr != NULL);
+ CU_ASSERT_EQUAL(sr->sid, 0);
+ uint32_t *uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], local_ipv4.s_addr);
+ CU_ASSERT_EQUAL(uint32_ptr[1], remote_ipv4.s_addr);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ /* Test the sid is present */
+ inet_pton(AF_INET, "192.168.1.2", &local_ipv4);
+ inet_pton(AF_INET, "172.168.1.2", &remote_ipv4);
+ reset_objects_buffer();
+ sr = pcep_obj_create_ro_subobj_sr_ipv4_adj(
+ false, false, true, true, sid, &local_ipv4, &remote_ipv4);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY, false,
+ sizeof(uint32_t) * 5);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_M);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], htonl(sid));
+ CU_ASSERT_EQUAL(uint32_ptr[1], local_ipv4.s_addr);
+ CU_ASSERT_EQUAL(uint32_ptr[2], remote_ipv4.s_addr);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_sr_ipv6_adj()
+{
+ uint32_t sid = 0x01020304;
+ struct in6_addr local_ipv6;
+ struct in6_addr remote_ipv6;
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:8221", &local_ipv6);
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &remote_ipv6);
+
+ /* (loose_hop, sid_absent, c_flag, m_flag, sid, local_ipv6, remote_ipv6)
+ */
+ struct pcep_ro_subobj_sr *sr = pcep_obj_create_ro_subobj_sr_ipv6_adj(
+ false, true, true, true, sid, NULL, NULL);
+ CU_ASSERT_PTR_NULL(sr);
+
+ sr = pcep_obj_create_ro_subobj_sr_ipv6_adj(false, true, true, true, sid,
+ &local_ipv6, NULL);
+ CU_ASSERT_PTR_NULL(sr);
+
+ sr = pcep_obj_create_ro_subobj_sr_ipv6_adj(false, true, true, true, sid,
+ NULL, &remote_ipv6);
+ CU_ASSERT_PTR_NULL(sr);
+
+ /* Test the sid is absent */
+ sr = pcep_obj_create_ro_subobj_sr_ipv6_adj(true, true, true, true, sid,
+ &local_ipv6, &remote_ipv6);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ assert(sr != NULL);
+ struct pcep_object_ro *ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY, true,
+ sizeof(uint32_t) * 10);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_M);
+ CU_ASSERT_EQUAL(sr->sid, 0);
+ uint32_t *uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], local_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[1], local_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], local_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], local_ipv6.__in6_u.__u6_addr32[3]);
+
+ CU_ASSERT_EQUAL(uint32_ptr[4], remote_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[5], remote_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[6], remote_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[7], remote_ipv6.__in6_u.__u6_addr32[3]);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ /* Test the sid is present */
+ reset_objects_buffer();
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:8221", &local_ipv6);
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &remote_ipv6);
+ sr = pcep_obj_create_ro_subobj_sr_ipv6_adj(
+ false, false, true, false, sid, &local_ipv6, &remote_ipv6);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY, false,
+ sizeof(uint32_t) * 11);
+ /* All flags are false */
+ CU_ASSERT_EQUAL(ro->header.encoded_object[7], 0);
+ uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], htonl(sid));
+ CU_ASSERT_EQUAL(uint32_ptr[1], local_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], local_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], local_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[4], local_ipv6.__in6_u.__u6_addr32[3]);
+
+ CU_ASSERT_EQUAL(uint32_ptr[5], remote_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[6], remote_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[7], remote_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[8], remote_ipv6.__in6_u.__u6_addr32[3]);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
+
+void test_pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj()
+{
+ uint32_t sid = 0x01020304;
+ uint32_t local_node_id = 0x11223344;
+ uint32_t local_if_id = 0x55667788;
+ uint32_t remote_node_id = 0x99aabbcc;
+ uint32_t remote_if_id = 0xddeeff11;
+
+ /* (loose_hop, sid_absent, c_flag, m_flag,
+ sid, local_node_id, local_if_id, remote_node_id, remote_if_id) */
+
+ /* Test the sid is absent */
+ struct pcep_ro_subobj_sr *sr =
+ pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj(
+ true, true, true, true, sid, local_node_id, local_if_id,
+ remote_node_id, remote_if_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ struct pcep_object_ro *ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(
+ ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY, true,
+ sizeof(uint32_t) * 6);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_M);
+ assert(sr != NULL);
+ CU_ASSERT_EQUAL(sr->sid, 0);
+ uint32_t *uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], local_node_id);
+ CU_ASSERT_EQUAL(uint32_ptr[1], local_if_id);
+ CU_ASSERT_EQUAL(uint32_ptr[2], remote_node_id);
+ CU_ASSERT_EQUAL(uint32_ptr[3], remote_if_id);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ /* Test the sid is present */
+ reset_objects_buffer();
+ sr = pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj(
+ false, false, true, true, sid, local_node_id, local_if_id,
+ remote_node_id, remote_if_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(
+ ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY, false,
+ sizeof(uint32_t) * 7);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_M);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], htonl(sid));
+ CU_ASSERT_EQUAL(uint32_ptr[1], local_node_id);
+ CU_ASSERT_EQUAL(uint32_ptr[2], local_if_id);
+ CU_ASSERT_EQUAL(uint32_ptr[3], remote_node_id);
+ CU_ASSERT_EQUAL(uint32_ptr[4], remote_if_id);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ /* TODO Test draft07 types */
+}
+
+void test_pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj()
+{
+ uint32_t sid = 0x01020304;
+ uint32_t local_if_id = 0x11002200;
+ uint32_t remote_if_id = 0x00110022;
+ struct in6_addr local_ipv6;
+ struct in6_addr remote_ipv6;
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:8221", &local_ipv6);
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &remote_ipv6);
+
+ /* (loose_hop, sid_absent, c_flag, m_flag, sid, local_ipv6, local_if_id,
+ * remote_ipv6, remote_if_id */
+ struct pcep_ro_subobj_sr *sr =
+ pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj(
+ false, true, true, true, sid, NULL, local_if_id, NULL,
+ remote_if_id);
+ CU_ASSERT_PTR_NULL(sr);
+
+ sr = pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj(
+ false, true, true, true, sid, &local_ipv6, local_if_id, NULL,
+ remote_if_id);
+ CU_ASSERT_PTR_NULL(sr);
+
+ sr = pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj(
+ false, true, true, true, sid, NULL, local_if_id, &remote_ipv6,
+ remote_if_id);
+ CU_ASSERT_PTR_NULL(sr);
+
+ /* Test the sid is absent */
+ sr = pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj(
+ true, true, true, true, sid, &local_ipv6, local_if_id,
+ &remote_ipv6, remote_if_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ struct pcep_object_ro *ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(
+ ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY, true,
+ sizeof(uint32_t) * 12);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_M);
+ assert(sr != NULL);
+ CU_ASSERT_EQUAL(sr->sid, 0);
+ uint32_t *uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], local_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[1], local_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], local_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], local_ipv6.__in6_u.__u6_addr32[3]);
+ CU_ASSERT_EQUAL(uint32_ptr[4], local_if_id);
+
+ CU_ASSERT_EQUAL(uint32_ptr[5], remote_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[6], remote_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[7], remote_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[8], remote_ipv6.__in6_u.__u6_addr32[3]);
+ CU_ASSERT_EQUAL(uint32_ptr[9], remote_if_id);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+
+ /* Test the sid is present */
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:8221", &local_ipv6);
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &remote_ipv6);
+ reset_objects_buffer();
+ sr = pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj(
+ false, false, true, true, sid, &local_ipv6, local_if_id,
+ &remote_ipv6, remote_if_id);
+ CU_ASSERT_PTR_NOT_NULL(sr);
+ ro = encode_ro_subobj(&sr->ro_subobj);
+ verify_pcep_obj_ro_sr_header(
+ ro, &sr->ro_subobj,
+ PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY, false,
+ sizeof(uint32_t) * 13);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_C);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & OBJECT_SUBOBJ_SR_FLAG_M);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_S);
+ CU_ASSERT_TRUE(ro->header.encoded_object[7] & ~OBJECT_SUBOBJ_SR_FLAG_F);
+ uint32_ptr = (uint32_t *)(ro->header.encoded_object + 8);
+ CU_ASSERT_EQUAL(uint32_ptr[0], htonl(sid));
+ CU_ASSERT_EQUAL(uint32_ptr[1], local_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[2], local_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[3], local_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[4], local_ipv6.__in6_u.__u6_addr32[3]);
+ CU_ASSERT_EQUAL(uint32_ptr[5], local_if_id);
+
+ CU_ASSERT_EQUAL(uint32_ptr[6], remote_ipv6.__in6_u.__u6_addr32[0]);
+ CU_ASSERT_EQUAL(uint32_ptr[7], remote_ipv6.__in6_u.__u6_addr32[1]);
+ CU_ASSERT_EQUAL(uint32_ptr[8], remote_ipv6.__in6_u.__u6_addr32[2]);
+ CU_ASSERT_EQUAL(uint32_ptr[9], remote_ipv6.__in6_u.__u6_addr32[3]);
+ CU_ASSERT_EQUAL(uint32_ptr[10], remote_if_id);
+ pcep_obj_free_object((struct pcep_object_header *)ro);
+}
diff --git a/pceplib/test/pcep_msg_objects_test.h b/pceplib/test/pcep_msg_objects_test.h
new file mode 100644
index 0000000..0f08193
--- /dev/null
+++ b/pceplib/test/pcep_msg_objects_test.h
@@ -0,0 +1,64 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+
+#ifndef PCEP_MSG_OBJECTS_TEST_H_
+#define PCEP_MSG_OBJECTS_TEST_H_
+
+int pcep_objects_test_suite_setup(void);
+int pcep_objects_test_suite_teardown(void);
+void pcep_objects_test_setup(void);
+void pcep_objects_test_teardown(void);
+void test_pcep_obj_create_open(void);
+void test_pcep_obj_create_open_with_tlvs(void);
+void test_pcep_obj_create_rp(void);
+void test_pcep_obj_create_nopath(void);
+void test_pcep_obj_create_endpoint_ipv4(void);
+void test_pcep_obj_create_endpoint_ipv6(void);
+void test_pcep_obj_create_association_ipv4(void);
+void test_pcep_obj_create_association_ipv6(void);
+void test_pcep_obj_create_bandwidth(void);
+void test_pcep_obj_create_metric(void);
+void test_pcep_obj_create_lspa(void);
+void test_pcep_obj_create_svec(void);
+void test_pcep_obj_create_error(void);
+void test_pcep_obj_create_close(void);
+void test_pcep_obj_create_srp(void);
+void test_pcep_obj_create_lsp(void);
+void test_pcep_obj_create_vendor_info(void);
+void test_pcep_obj_create_ero(void);
+void test_pcep_obj_create_rro(void);
+void test_pcep_obj_create_iro(void);
+void test_pcep_obj_create_ro_subobj_ipv4(void);
+void test_pcep_obj_create_ro_subobj_ipv6(void);
+void test_pcep_obj_create_ro_subobj_unnum(void);
+void test_pcep_obj_create_ro_subobj_32label(void);
+void test_pcep_obj_create_ro_subobj_asn(void);
+void test_pcep_obj_create_ro_subobj_sr_nonai(void);
+void test_pcep_obj_create_ro_subobj_sr_ipv4_node(void);
+void test_pcep_obj_create_ro_subobj_sr_ipv6_node(void);
+void test_pcep_obj_create_ro_subobj_sr_ipv4_adj(void);
+void test_pcep_obj_create_ro_subobj_sr_ipv6_adj(void);
+void test_pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj(void);
+void test_pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj(void);
+
+#endif
diff --git a/pceplib/test/pcep_msg_tests_valgrind.sh b/pceplib/test/pcep_msg_tests_valgrind.sh
new file mode 100755
index 0000000..4a9a999
--- /dev/null
+++ b/pceplib/test/pcep_msg_tests_valgrind.sh
@@ -0,0 +1,2 @@
+source pceplib/test/pcep_tests_valgrind.sh
+valgrind_test pceplib/test/pcep_msg_tests
diff --git a/pceplib/test/pcep_msg_tlvs_test.c b/pceplib/test/pcep_msg_tlvs_test.c
new file mode 100644
index 0000000..888925f
--- /dev/null
+++ b/pceplib/test/pcep_msg_tlvs_test.c
@@ -0,0 +1,725 @@
+/*
+ * 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
+
+#ifdef __FreeBSD__
+#include <sys/endian.h>
+#else
+#include <endian.h>
+#endif /* __FreeBSD__ */
+#include <assert.h>
+#include <stdlib.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_msg_encoding.h"
+#include "pcep_msg_objects.h"
+#include "pcep_msg_tlvs.h"
+#include "pcep_msg_tools.h"
+#include "pcep_utils_memory.h"
+#include "pcep_msg_tlvs_test.h"
+
+/*
+ * Notice:
+ * All of these TLV Unit Tests encode the created TLVs by explicitly calling
+ * pcep_encode_tlv() thus testing the TLV creation and the TLV encoding.
+ * All APIs expect IPs to be in network byte order.
+ */
+
+static struct pcep_versioning *versioning = NULL;
+static uint8_t tlv_buf[2000];
+
+void reset_tlv_buffer(void);
+
+int pcep_tlvs_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ return 0;
+}
+
+int pcep_tlvs_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+void reset_tlv_buffer()
+{
+ memset(tlv_buf, 0, 2000);
+}
+
+void pcep_tlvs_test_setup()
+{
+ versioning = create_default_pcep_versioning();
+ reset_tlv_buffer();
+}
+
+void pcep_tlvs_test_teardown()
+{
+ destroy_pcep_versioning(versioning);
+}
+
+void test_pcep_tlv_create_stateful_pce_capability()
+{
+ struct pcep_object_tlv_stateful_pce_capability *tlv =
+ pcep_tlv_create_stateful_pce_capability(true, true, true, true,
+ true, true);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t));
+ CU_ASSERT_TRUE(tlv->flag_u_lsp_update_capability);
+ CU_ASSERT_TRUE(tlv->flag_s_include_db_version);
+ CU_ASSERT_TRUE(tlv->flag_i_lsp_instantiation_capability);
+ CU_ASSERT_TRUE(tlv->flag_t_triggered_resync);
+ CU_ASSERT_TRUE(tlv->flag_d_delta_lsp_sync);
+ CU_ASSERT_TRUE(tlv->flag_f_triggered_initial_sync);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[7], 0x3f);
+ /* TODO add a new function: verify_tlv_header(tlv->header.encoded_tlv)
+ * to all tests */
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_speaker_entity_id()
+{
+ struct pcep_object_tlv_speaker_entity_identifier *tlv =
+ pcep_tlv_create_speaker_entity_id(NULL);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ double_linked_list *list = dll_initialize();
+ tlv = pcep_tlv_create_speaker_entity_id(list);
+ CU_ASSERT_PTR_NULL(tlv);
+ if (tlv != NULL) {
+ pceplib_free(PCEPLIB_INFRA, tlv);
+ tlv = NULL;
+ }
+
+ uint32_t *speaker_entity =
+ pceplib_malloc(PCEPLIB_MESSAGES, sizeof(uint32_t));
+ *speaker_entity = 42;
+ dll_append(list, speaker_entity);
+ tlv = pcep_tlv_create_speaker_entity_id(list);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t));
+ CU_ASSERT_PTR_NOT_NULL(tlv->speaker_entity_id_list);
+ assert(tlv->speaker_entity_id_list != NULL);
+ CU_ASSERT_EQUAL(tlv->speaker_entity_id_list->num_entries, 1);
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(*speaker_entity));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_lsp_db_version()
+{
+ uint64_t lsp_db_version = 0xf005ba11ba5eba11;
+ struct pcep_object_tlv_lsp_db_version *tlv =
+ pcep_tlv_create_lsp_db_version(lsp_db_version);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint64_t));
+ CU_ASSERT_EQUAL(tlv->lsp_db_version, lsp_db_version);
+ CU_ASSERT_EQUAL(*((uint64_t *)(tlv->header.encoded_tlv + 4)),
+ be64toh(lsp_db_version));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_path_setup_type()
+{
+ uint8_t pst = 0x89;
+
+ struct pcep_object_tlv_path_setup_type *tlv =
+ pcep_tlv_create_path_setup_type(pst);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t));
+ CU_ASSERT_EQUAL(tlv->path_setup_type, pst);
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(0x000000FF & pst));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_path_setup_type_capability()
+{
+ /* The sub_tlv list is optional */
+
+ /* Should return NULL if pst_list is NULL */
+ struct pcep_object_tlv_path_setup_type_capability *tlv =
+ pcep_tlv_create_path_setup_type_capability(NULL, NULL);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ /* Should return NULL if pst_list is empty */
+ double_linked_list *pst_list = dll_initialize();
+ tlv = pcep_tlv_create_path_setup_type_capability(pst_list, NULL);
+ CU_ASSERT_PTR_NULL(tlv);
+ if (tlv != NULL) {
+ pcep_obj_free_tlv(&tlv->header);
+ tlv = NULL;
+ }
+
+ /* Should still return NULL if pst_list is NULL */
+ double_linked_list *sub_tlv_list = dll_initialize();
+ tlv = pcep_tlv_create_path_setup_type_capability(NULL, sub_tlv_list);
+ CU_ASSERT_PTR_NULL(tlv);
+ if (tlv != NULL) {
+ pcep_obj_free_tlv(&tlv->header);
+ tlv = NULL;
+ }
+
+ /* Should still return NULL if pst_list is empty */
+ tlv = pcep_tlv_create_path_setup_type_capability(pst_list,
+ sub_tlv_list);
+ CU_ASSERT_PTR_NULL(tlv);
+ if (tlv != NULL) {
+ pcep_obj_free_tlv(&tlv->header);
+ tlv = NULL;
+ }
+
+ /* Test only populating the pst list */
+ uint8_t *pst1 = pceplib_malloc(PCEPLIB_MESSAGES, 1);
+ uint8_t *pst2 = pceplib_malloc(PCEPLIB_MESSAGES, 1);
+ uint8_t *pst3 = pceplib_malloc(PCEPLIB_MESSAGES, 1);
+ *pst1 = 1;
+ *pst2 = 2;
+ *pst3 = 3;
+ dll_append(pst_list, pst1);
+ dll_append(pst_list, pst2);
+ dll_append(pst_list, pst3);
+ tlv = pcep_tlv_create_path_setup_type_capability(pst_list,
+ sub_tlv_list);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ if (tlv == NULL) {
+ CU_ASSERT_TRUE(tlv != NULL);
+ return;
+ }
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t) * 2);
+ CU_ASSERT_PTR_NOT_NULL(tlv->pst_list);
+ assert(tlv != NULL);
+ CU_ASSERT_EQUAL(tlv->pst_list->num_entries, 3);
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(0x00000003));
+ CU_ASSERT_EQUAL(uint32_ptr[2], htonl(0x01020300));
+ pcep_obj_free_tlv(&tlv->header);
+
+ /* Now test populating both the pst_list and the sub_tlv_list */
+ reset_tlv_buffer();
+ struct pcep_object_tlv_header *sub_tlv =
+ (struct pcep_object_tlv_header *)
+ pcep_tlv_create_sr_pce_capability(true, true, 0);
+ pst_list = dll_initialize();
+ sub_tlv_list = dll_initialize();
+ pst1 = pceplib_malloc(PCEPLIB_MESSAGES, 1);
+ *pst1 = 1;
+ dll_append(pst_list, pst1);
+ dll_append(sub_tlv_list, sub_tlv);
+ tlv = pcep_tlv_create_path_setup_type_capability(pst_list,
+ sub_tlv_list);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length,
+ sizeof(uint32_t) * 2 + TLV_HEADER_LENGTH
+ + sub_tlv->encoded_tlv_length);
+ CU_ASSERT_PTR_NOT_NULL(tlv->pst_list);
+ CU_ASSERT_PTR_NOT_NULL(tlv->sub_tlv_list);
+ uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ uint16_t *uint16_ptr = (uint16_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint16_ptr[0],
+ htons(PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY));
+ CU_ASSERT_EQUAL(uint16_ptr[1], htons(tlv->header.encoded_tlv_length));
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(0x00000001));
+ CU_ASSERT_EQUAL(uint32_ptr[2], htonl(0x01000000));
+ /* Verify the Sub-TLV */
+ uint16_ptr = (uint16_t *)(tlv->header.encoded_tlv + 12);
+ CU_ASSERT_EQUAL(uint16_ptr[0],
+ htons(PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY));
+ CU_ASSERT_EQUAL(uint16_ptr[1], htons(4));
+ CU_ASSERT_EQUAL(uint16_ptr[2], 0);
+ CU_ASSERT_EQUAL(uint16_ptr[3], htons(0x0300));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_sr_pce_capability()
+{
+ struct pcep_object_tlv_sr_pce_capability *tlv =
+ pcep_tlv_create_sr_pce_capability(true, true, 8);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t));
+ uint16_t *uint16_ptr = (uint16_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint16_ptr[0],
+ htons(PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY));
+ CU_ASSERT_EQUAL(uint16_ptr[1], htons(tlv->header.encoded_tlv_length));
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(0x00000308));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_symbolic_path_name()
+{
+ /* char *symbolic_path_name, uint16_t symbolic_path_name_length); */
+ char path_name[16] = "Some Path Name";
+ uint16_t path_name_length = 14;
+ struct pcep_object_tlv_symbolic_path_name *tlv =
+ pcep_tlv_create_symbolic_path_name(path_name, path_name_length);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, path_name_length);
+ /* Test the padding is correct */
+ CU_ASSERT_EQUAL(0, strncmp((char *)&(tlv->header.encoded_tlv[4]),
+ &path_name[0], 4));
+ CU_ASSERT_EQUAL(0, strncmp((char *)&(tlv->header.encoded_tlv[8]),
+ &path_name[4], 4));
+ CU_ASSERT_EQUAL(0, strncmp((char *)&(tlv->header.encoded_tlv[12]),
+ &path_name[8], 4));
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[16], 'm');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[17], 'e');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[18], 0);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[19], 0);
+ pcep_obj_free_tlv(&tlv->header);
+
+ reset_tlv_buffer();
+ tlv = pcep_tlv_create_symbolic_path_name(path_name, 3);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ printf("El tlv es %p", tlv);
+ assert(tlv != NULL); // crash si FALSE
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, 3);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[4], 'S');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[5], 'o');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[6], 'm');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[7], 0);
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_ipv4_lsp_identifiers()
+{
+ struct in_addr sender_ip, endpoint_ip;
+ uint16_t lsp_id = 7;
+ uint16_t tunnel_id = 16;
+ struct in_addr extended_tunnel_id;
+ extended_tunnel_id.s_addr = 256;
+ inet_pton(AF_INET, "192.168.1.1", &sender_ip);
+ inet_pton(AF_INET, "192.168.1.2", &endpoint_ip);
+
+ struct pcep_object_tlv_ipv4_lsp_identifier *tlv =
+ pcep_tlv_create_ipv4_lsp_identifiers(NULL, &endpoint_ip, lsp_id,
+ tunnel_id,
+ &extended_tunnel_id);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ tlv = pcep_tlv_create_ipv4_lsp_identifiers(
+ &sender_ip, NULL, lsp_id, tunnel_id, &extended_tunnel_id);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ tlv = pcep_tlv_create_ipv4_lsp_identifiers(
+ NULL, NULL, lsp_id, tunnel_id, &extended_tunnel_id);
+ CU_ASSERT_PTR_NULL(tlv);
+ assert(tlv == NULL);
+
+ tlv = pcep_tlv_create_ipv4_lsp_identifiers(&sender_ip, &endpoint_ip,
+ lsp_id, tunnel_id,
+ &extended_tunnel_id);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t) * 4);
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1], sender_ip.s_addr);
+ CU_ASSERT_EQUAL(uint32_ptr[2],
+ (uint32_t)(htons(tunnel_id) << 16) | htons(lsp_id));
+ CU_ASSERT_EQUAL(uint32_ptr[3], extended_tunnel_id.s_addr);
+ CU_ASSERT_EQUAL(uint32_ptr[4], endpoint_ip.s_addr);
+ pcep_obj_free_tlv(&tlv->header);
+
+ reset_tlv_buffer();
+ tlv = pcep_tlv_create_ipv4_lsp_identifiers(&sender_ip, &endpoint_ip,
+ lsp_id, tunnel_id, NULL);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t) * 4);
+ uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1], sender_ip.s_addr);
+ CU_ASSERT_EQUAL(uint32_ptr[2],
+ (uint32_t)(htons(tunnel_id) << 16) | htons(lsp_id));
+ CU_ASSERT_EQUAL(uint32_ptr[3], INADDR_ANY);
+ CU_ASSERT_EQUAL(uint32_ptr[4], endpoint_ip.s_addr);
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_ipv6_lsp_identifiers()
+{
+ struct in6_addr sender_ip, endpoint_ip;
+ uint16_t lsp_id = 3;
+ uint16_t tunnel_id = 16;
+ uint32_t extended_tunnel_id[4];
+
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &sender_ip);
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:8446", &endpoint_ip);
+ extended_tunnel_id[0] = 1;
+ extended_tunnel_id[1] = 2;
+ extended_tunnel_id[2] = 3;
+ extended_tunnel_id[3] = 4;
+
+ struct pcep_object_tlv_ipv6_lsp_identifier *tlv =
+ pcep_tlv_create_ipv6_lsp_identifiers(
+ NULL, &endpoint_ip, lsp_id, tunnel_id,
+ (struct in6_addr *)&extended_tunnel_id);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ tlv = pcep_tlv_create_ipv6_lsp_identifiers(
+ &sender_ip, NULL, lsp_id, tunnel_id,
+ (struct in6_addr *)&extended_tunnel_id);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ tlv = pcep_tlv_create_ipv6_lsp_identifiers(
+ NULL, NULL, lsp_id, tunnel_id,
+ (struct in6_addr *)&extended_tunnel_id);
+ CU_ASSERT_PTR_NULL(tlv);
+ assert(tlv == NULL);
+
+ tlv = pcep_tlv_create_ipv6_lsp_identifiers(
+ &sender_ip, &endpoint_ip, lsp_id, tunnel_id,
+ (struct in6_addr *)&extended_tunnel_id);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, 52);
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[5],
+ (uint32_t)(htons(tunnel_id) << 16) | htons(lsp_id));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+void test_pcep_tlv_create_srpag_pol_id_ipv4()
+{
+ uint32_t color = 1;
+ struct in_addr src;
+ inet_pton(AF_INET, "192.168.1.2", &src);
+
+ struct pcep_object_tlv_srpag_pol_id *tlv =
+ pcep_tlv_create_srpag_pol_id_ipv4(color, (void *)&src);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, (PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID));
+ CU_ASSERT_EQUAL(
+ tlv->header.encoded_tlv_length,
+ (8 /*draft-barth-pce-segment-routing-policy-cp-04#5.1*/));
+ CU_ASSERT_EQUAL(tlv->color, (color));
+ uint32_t aux_color = htonl(color); // Is color right encoded
+ CU_ASSERT_EQUAL(0, memcmp(&tlv_buf[0] + TLV_HEADER_LENGTH, &aux_color,
+ sizeof(color)));
+ CU_ASSERT_EQUAL(tlv->end_point.ipv4.s_addr, (src.s_addr));
+ // Are simetrical?
+ struct pcep_object_tlv_header *dec_hdr = pcep_decode_tlv(tlv_buf);
+ struct pcep_object_tlv_srpag_pol_id *dec_tlv =
+ (struct pcep_object_tlv_srpag_pol_id *)dec_hdr;
+ CU_ASSERT_EQUAL(tlv->color, dec_tlv->color);
+
+ pceplib_free(PCEPLIB_MESSAGES, dec_hdr);
+ pcep_obj_free_tlv(&tlv->header);
+}
+void test_pcep_tlv_create_srpag_pol_id_ipv6()
+{
+
+ uint32_t color = 1;
+ struct in6_addr src;
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &src);
+
+ struct pcep_object_tlv_srpag_pol_id *tlv =
+ pcep_tlv_create_srpag_pol_id_ipv6(color, &src);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, (PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID));
+ CU_ASSERT_EQUAL(
+ tlv->header.encoded_tlv_length,
+ (20 /*draft-barth-pce-segment-routing-policy-cp-04#5.1*/));
+ CU_ASSERT_EQUAL(tlv->color, (color));
+ CU_ASSERT_EQUAL(0, memcmp(&tlv->end_point.ipv6, &src, sizeof(src)));
+
+ uint32_t aux_color = htonl(color);
+ CU_ASSERT_EQUAL(0, memcmp(&aux_color, tlv_buf + TLV_HEADER_LENGTH,
+ sizeof(tlv->color)));
+ // Are simetrical?
+ struct pcep_object_tlv_header *dec_hdr = pcep_decode_tlv(tlv_buf);
+ struct pcep_object_tlv_srpag_pol_id *dec_tlv =
+ (struct pcep_object_tlv_srpag_pol_id *)dec_hdr;
+ CU_ASSERT_EQUAL(tlv->color, dec_tlv->color);
+
+ pceplib_free(PCEPLIB_MESSAGES, dec_hdr);
+ pcep_obj_free_tlv(&tlv->header);
+}
+void test_pcep_tlv_create_srpag_pol_name()
+{
+ const char *pol_name = "Some Pol Name";
+
+ struct pcep_object_tlv_srpag_pol_name *tlv =
+ pcep_tlv_create_srpag_pol_name(pol_name, strlen(pol_name));
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ (PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME));
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length,
+ (normalize_pcep_tlv_length(strlen(pol_name))));
+ CU_ASSERT_EQUAL(0, strcmp(pol_name, (char *)tlv->name));
+
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_srpag_cp_id()
+{
+ // draft-ietf-spring-segment-routing-policy-06.pdf#2.3
+ // 10 PCEP, 20 BGP SR Policy, 30 Via Configuration
+ uint8_t proto_origin = 10;
+ uint32_t ASN = 0;
+ struct in6_addr with_mapped_ipv4;
+ inet_pton(AF_INET6, "::ffff:192.0.2.128", &with_mapped_ipv4);
+ uint32_t discriminator = 0;
+
+ struct pcep_object_tlv_srpag_cp_id *tlv = pcep_tlv_create_srpag_cp_id(
+ proto_origin, ASN, &with_mapped_ipv4, discriminator);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ (PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID));
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length,
+ (sizeof(proto_origin) + sizeof(ASN)
+ + sizeof(with_mapped_ipv4) + sizeof(discriminator)));
+ CU_ASSERT_EQUAL(tlv->proto, (proto_origin));
+ CU_ASSERT_EQUAL(tlv->orig_asn, (ASN));
+ CU_ASSERT_EQUAL(0, memcmp(&tlv->orig_addres, &with_mapped_ipv4,
+ sizeof(with_mapped_ipv4)));
+ CU_ASSERT_EQUAL(tlv->discriminator, (discriminator));
+ // Are simetrical?
+ struct pcep_object_tlv_header *dec_hdr = pcep_decode_tlv(tlv_buf);
+ struct pcep_object_tlv_srpag_cp_id *dec_tlv =
+ (struct pcep_object_tlv_srpag_cp_id *)dec_hdr;
+ CU_ASSERT_EQUAL(tlv->proto, dec_tlv->proto);
+
+ pceplib_free(PCEPLIB_MESSAGES, dec_hdr);
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_srpag_cp_pref()
+{
+ uint32_t preference_default = 100;
+
+ struct pcep_object_tlv_srpag_cp_pref *tlv =
+ pcep_tlv_create_srpag_cp_pref(preference_default);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type,
+ (PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE));
+ printf(" encoded length vs sizeof pref (%d) vs (%ld)\n",
+ tlv->header.encoded_tlv_length, sizeof(preference_default));
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length,
+ sizeof(preference_default));
+ CU_ASSERT_EQUAL(tlv->preference, (preference_default));
+ uint32_t aux_pref = htonl(preference_default); // Is pref right encoded
+ CU_ASSERT_EQUAL(0, memcmp(tlv_buf + TLV_HEADER_LENGTH, &aux_pref,
+ sizeof(preference_default)));
+ // Are simetrical?
+ struct pcep_object_tlv_header *dec_hdr = pcep_decode_tlv(tlv_buf);
+ struct pcep_object_tlv_srpag_cp_pref *dec_tlv =
+ (struct pcep_object_tlv_srpag_cp_pref *)dec_hdr;
+ CU_ASSERT_EQUAL(tlv->preference, dec_tlv->preference);
+
+ pceplib_free(PCEPLIB_MESSAGES, dec_hdr);
+ pcep_obj_free_tlv(&tlv->header);
+}
+void test_pcep_tlv_create_lsp_error_code()
+{
+ struct pcep_object_tlv_lsp_error_code *tlv =
+ pcep_tlv_create_lsp_error_code(
+ PCEP_TLV_LSP_ERROR_CODE_RSVP_SIGNALING_ERROR);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, sizeof(uint32_t));
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1],
+ htonl(PCEP_TLV_LSP_ERROR_CODE_RSVP_SIGNALING_ERROR));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_rsvp_ipv4_error_spec()
+{
+ struct in_addr error_node_ip;
+ inet_pton(AF_INET, "192.168.1.1", &error_node_ip);
+ uint8_t error_code = 8;
+ uint16_t error_value = 0xaabb;
+
+ struct pcep_object_tlv_rsvp_error_spec *tlv =
+ pcep_tlv_create_rsvp_ipv4_error_spec(NULL, error_code,
+ error_value);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ tlv = pcep_tlv_create_rsvp_ipv4_error_spec(&error_node_ip, error_code,
+ error_value);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, 12);
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_rsvp_ipv6_error_spec()
+{
+ struct in6_addr error_node_ip;
+ inet_pton(AF_INET6, "2001:db8::8a2e:370:7334", &error_node_ip);
+ uint8_t error_code = 8;
+ uint16_t error_value = 0xaabb;
+
+ struct pcep_object_tlv_rsvp_error_spec *tlv =
+ pcep_tlv_create_rsvp_ipv6_error_spec(NULL, error_code,
+ error_value);
+ CU_ASSERT_PTR_NULL(tlv);
+
+ tlv = pcep_tlv_create_rsvp_ipv6_error_spec(&error_node_ip, error_code,
+ error_value);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, 24);
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_nopath_vector()
+{
+ uint32_t enterprise_number = 0x01020304;
+ uint32_t enterprise_specific_info = 0x05060708;
+
+ struct pcep_object_tlv_vendor_info *tlv = pcep_tlv_create_vendor_info(
+ enterprise_number, enterprise_specific_info);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, PCEP_OBJ_TLV_TYPE_VENDOR_INFO);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, 8);
+ uint32_t *uint32_ptr = (uint32_t *)tlv->header.encoded_tlv;
+ CU_ASSERT_EQUAL(uint32_ptr[1], htonl(enterprise_number));
+ CU_ASSERT_EQUAL(uint32_ptr[2], htonl(enterprise_specific_info));
+
+ pcep_obj_free_tlv(&tlv->header);
+}
+
+void test_pcep_tlv_create_arbitrary()
+{
+ char data[16] = "Some Data";
+ uint16_t data_length = 9;
+ uint16_t tlv_id_unknown = 1; // 65505; // Whatever id to be created
+ struct pcep_object_tlv_arbitrary *tlv = pcep_tlv_create_tlv_arbitrary(
+ data, data_length, tlv_id_unknown);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, tlv_id_unknown);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, data_length);
+ /* Test the padding is correct */
+ CU_ASSERT_EQUAL(
+ 0, strncmp((char *)&(tlv->header.encoded_tlv[4]), &data[0], 4));
+ CU_ASSERT_EQUAL(
+ 0, strncmp((char *)&(tlv->header.encoded_tlv[8]), &data[4], 4));
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[11], 't');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[12], 'a');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[13], 0);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[14], 0);
+ pcep_obj_free_tlv(&tlv->header);
+
+ reset_tlv_buffer();
+ tlv = pcep_tlv_create_tlv_arbitrary(data, 3, tlv_id_unknown);
+ CU_ASSERT_PTR_NOT_NULL(tlv);
+ assert(tlv != NULL);
+ pcep_encode_tlv(&tlv->header, versioning, tlv_buf);
+ CU_ASSERT_EQUAL(tlv->header.type, tlv_id_unknown);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv_length, 3);
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[4], 'S');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[5], 'o');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[6], 'm');
+ CU_ASSERT_EQUAL(tlv->header.encoded_tlv[7], 0);
+
+ pcep_obj_free_tlv(&tlv->header);
+}
diff --git a/pceplib/test/pcep_msg_tlvs_test.h b/pceplib/test/pcep_msg_tlvs_test.h
new file mode 100644
index 0000000..a961d7e
--- /dev/null
+++ b/pceplib/test/pcep_msg_tlvs_test.h
@@ -0,0 +1,51 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+#ifndef PCEP_MSG_TLVS_TEST_H_
+#define PCEP_MSG_TLVS_TEST_H_
+
+int pcep_tlvs_test_suite_setup(void);
+int pcep_tlvs_test_suite_teardown(void);
+void pcep_tlvs_test_setup(void);
+void pcep_tlvs_test_teardown(void);
+void test_pcep_tlv_create_stateful_pce_capability(void);
+void test_pcep_tlv_create_speaker_entity_id(void);
+void test_pcep_tlv_create_lsp_db_version(void);
+void test_pcep_tlv_create_path_setup_type(void);
+void test_pcep_tlv_create_path_setup_type_capability(void);
+void test_pcep_tlv_create_sr_pce_capability(void);
+void test_pcep_tlv_create_symbolic_path_name(void);
+void test_pcep_tlv_create_ipv4_lsp_identifiers(void);
+void test_pcep_tlv_create_ipv6_lsp_identifiers(void);
+void test_pcep_tlv_create_lsp_error_code(void);
+void test_pcep_tlv_create_rsvp_ipv4_error_spec(void);
+void test_pcep_tlv_create_rsvp_ipv6_error_spec(void);
+void test_pcep_tlv_create_srpag_pol_id_ipv4(void);
+void test_pcep_tlv_create_srpag_pol_id_ipv6(void);
+void test_pcep_tlv_create_srpag_pol_name(void);
+void test_pcep_tlv_create_srpag_cp_id(void);
+void test_pcep_tlv_create_srpag_cp_pref(void);
+void test_pcep_tlv_create_nopath_vector(void);
+void test_pcep_tlv_create_arbitrary(void);
+
+
+#endif
diff --git a/pceplib/test/pcep_msg_tools_test.c b/pceplib/test/pcep_msg_tools_test.c
new file mode 100644
index 0000000..ffbe802
--- /dev/null
+++ b/pceplib/test/pcep_msg_tools_test.c
@@ -0,0 +1,1367 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#include <CUnit/CUnit.h>
+
+#include <zebra.h>
+
+#include "pcep_msg_encoding.h"
+#include "pcep_msg_messages.h"
+#include "pcep_msg_tools.h"
+#include "pcep_msg_tools_test.h"
+#include "pcep_utils_double_linked_list.h"
+#include "pcep_utils_logging.h"
+#include "pcep_utils_memory.h"
+
+const uint8_t any_obj_class = 255;
+
+uint16_t pcep_open_hexbyte_strs_length = 28;
+const char *pcep_open_odl_hexbyte_strs[] = {
+ "20", "01", "00", "1c", "01", "10", "00", "18", "20", "1e",
+ "78", "55", "00", "10", "00", "04", "00", "00", "00", "3f",
+ "00", "1a", "00", "04", "00", "00", "00", "00"};
+
+/* PCEP INITIATE str received from ODL with 4 objects: [SRP, LSP, Endpoints,
+ * ERO] The LSP has a SYMBOLIC_PATH_NAME TLV. The ERO has 2 IPV4 Endpoints. */
+uint16_t pcep_initiate_hexbyte_strs_length = 68;
+const char *pcep_initiate_hexbyte_strs[] = {
+ "20", "0c", "00", "44", "21", "12", "00", "0c", "00", "00", "00", "00",
+ "00", "00", "00", "01", "20", "10", "00", "14", "00", "00", "00", "09",
+ "00", "11", "00", "08", "66", "61", "39", "33", "33", "39", "32", "39",
+ "04", "10", "00", "0c", "7f", "00", "00", "01", "28", "28", "28", "28",
+ "07", "10", "00", "14", "01", "08", "0a", "00", "01", "01", "18", "00",
+ "01", "08", "0a", "00", "07", "04", "18", "00"};
+
+uint16_t pcep_initiate2_hexbyte_strs_length = 72;
+const char *pcep_initiate2_hexbyte_strs[] = {
+ "20", "0c", "00", "48", "21", "12", "00", "14", "00", "00", "00", "00",
+ "00", "00", "00", "01", "00", "1c", "00", "04", "00", "00", "00", "01",
+ "20", "10", "00", "14", "00", "00", "00", "09", "00", "11", "00", "08",
+ "36", "65", "31", "31", "38", "39", "32", "31", "04", "10", "00", "0c",
+ "c0", "a8", "14", "05", "01", "01", "01", "01", "07", "10", "00", "10",
+ "05", "0c", "10", "01", "03", "e8", "a0", "00", "01", "01", "01", "01"};
+
+uint16_t pcep_update_hexbyte_strs_length = 48;
+const char *pcep_update_hexbyte_strs[] = {
+ "20", "0b", "00", "30", "21", "12", "00", "14", "00", "00", "00", "00",
+ "00", "00", "00", "01", "00", "1c", "00", "04", "00", "00", "00", "01",
+ "20", "10", "00", "08", "00", "02", "a0", "09", "07", "10", "00", "10",
+ "05", "0c", "10", "01", "03", "e8", "a0", "00", "01", "01", "01", "01"};
+
+/* Test that pcep_msg_read() can read multiple messages in 1 call */
+uint16_t pcep_open_initiate_hexbyte_strs_length = 100;
+const char *pcep_open_initiate_odl_hexbyte_strs[] = {
+ "20", "01", "00", "1c", "01", "10", "00", "18", "20", "1e", "78", "55",
+ "00", "10", "00", "04", "00", "00", "00", "3f", "00", "1a", "00", "04",
+ "00", "00", "00", "00", "20", "0c", "00", "48", "21", "12", "00", "14",
+ "00", "00", "00", "00", "00", "00", "00", "01", "00", "1c", "00", "04",
+ "00", "00", "00", "01", "20", "10", "00", "14", "00", "00", "00", "09",
+ "00", "11", "00", "08", "36", "65", "31", "31", "38", "39", "32", "31",
+ "04", "10", "00", "0c", "c0", "a8", "14", "05", "01", "01", "01", "01",
+ "07", "10", "00", "10", "05", "0c", "10", "01", "03", "e8", "a0", "00",
+ "01", "01", "01", "01"};
+
+uint16_t pcep_open_cisco_pce_hexbyte_strs_length = 28;
+const char *pcep_open_cisco_pce_hexbyte_strs[] = {
+ "20", "01", "00", "1c", "01", "10", "00", "18", "20", "3c",
+ "78", "00", "00", "10", "00", "04", "00", "00", "00", "05",
+ "00", "1a", "00", "04", "00", "00", "00", "0a"};
+
+uint16_t pcep_update_cisco_pce_hexbyte_strs_length = 100;
+const char *pcep_update_cisco_pce_hexbyte_strs[] = {
+ "20", "0b", "00", "64", "21", "10", "00", "14", "00", "00", "00", "00",
+ "00", "00", "00", "01", "00", "1c", "00", "04", "00", "00", "00", "01",
+ "20", "10", "00", "18", "80", "00", "f0", "89", "00", "07", "00", "0c",
+ "00", "00", "00", "09", "00", "03", "00", "04", "00", "00", "00", "01",
+ "07", "10", "00", "28", "24", "0c", "10", "01", "04", "65", "50", "00",
+ "0a", "0a", "0a", "05", "24", "0c", "10", "01", "04", "65", "20", "00",
+ "0a", "0a", "0a", "02", "24", "0c", "10", "01", "04", "65", "10", "00",
+ "0a", "0a", "0a", "01", "06", "10", "00", "0c", "00", "00", "00", "02",
+ "41", "f0", "00", "00"};
+
+uint16_t pcep_report_cisco_pcc_hexbyte_strs_length = 148;
+const char *pcep_report_cisco_pcc_hexbyte_strs[] = {
+ "20", "0a", "00", "94", "21", "10", "00", "14", "00", "00", "00", "00",
+ "00", "00", "00", "00", "00", "1c", "00", "04", "00", "00", "00", "01",
+ "20", "10", "00", "3c", "80", "00", "f0", "09", "00", "12", "00", "10",
+ "0a", "0a", "0a", "06", "00", "02", "00", "0f", "0a", "0a", "0a", "06",
+ "0a", "0a", "0a", "01", "00", "11", "00", "0d", "63", "66", "67", "5f",
+ "52", "36", "2d", "74", "6f", "2d", "52", "31", "00", "00", "00", "00",
+ "ff", "e1", "00", "06", "00", "00", "05", "dd", "70", "00", "00", "00",
+ "07", "10", "00", "04", "09", "10", "00", "14", "00", "00", "00", "00",
+ "00", "00", "00", "00", "00", "00", "00", "00", "07", "07", "01", "00",
+ "05", "12", "00", "08", "00", "00", "00", "00", "05", "52", "00", "08",
+ "00", "00", "00", "00", "06", "10", "00", "0c", "00", "00", "00", "02",
+ "00", "00", "00", "00", "06", "10", "00", "0c", "00", "00", "01", "04",
+ "41", "80", "00", "00"};
+
+/* Cisco PcInitiate with the following objects:
+ * SRP, LSP, Endpoint, Inter-layer, Switch-layer, ERO
+ */
+uint16_t pcep_initiate_cisco_pcc_hexbyte_strs_length = 104;
+const char *pcep_initiate_cisco_pcc_hexbyte_strs[] = {
+ "20", "0c", "00", "68", "21", "10", "00", "14", "00", "00", "00", "00",
+ "00", "00", "00", "01", "00", "1c", "00", "04", "00", "00", "00", "01",
+ "20", "10", "00", "30", "00", "00", "00", "89", "00", "11", "00", "13",
+ "50", "4f", "4c", "31", "5f", "50", "43", "49", "4e", "49", "54", "41",
+ "54", "45", "5f", "54", "45", "53", "54", "00", "00", "07", "00", "0c",
+ "00", "00", "00", "09", "00", "03", "00", "04", "00", "00", "00", "01",
+ "04", "10", "00", "0c", "0a", "0a", "0a", "0a", "0a", "0a", "0a", "04",
+ "24", "10", "00", "08", "00", "00", "01", "4d", "25", "10", "00", "08",
+ "00", "00", "00", "64", "07", "10", "00", "04"};
+
+struct pcep_message *create_message(uint8_t msg_type, uint8_t obj1_class,
+ uint8_t obj2_class, uint8_t obj3_class,
+ uint8_t obj4_class);
+int convert_hexstrs_to_binary(char *filename, const char *hexbyte_strs[],
+ uint16_t hexbyte_strs_length);
+
+int pcep_tools_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ return 0;
+}
+
+int pcep_tools_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+void pcep_tools_test_setup(void)
+{
+}
+
+void pcep_tools_test_teardown(void)
+{
+}
+
+static const char BASE_TMPFILE[] = "/tmp/pceplib_XXXXXX";
+static int BASE_TMPFILE_SIZE = sizeof(BASE_TMPFILE);
+
+/* Reads an array of hexbyte strs, and writes them to a temporary file.
+ * The caller should close the returned file. */
+int convert_hexstrs_to_binary(char *filename, const char *hexbyte_strs[],
+ uint16_t hexbyte_strs_length)
+{
+ mode_t oldumask;
+ oldumask = umask(S_IXUSR | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
+ /* Set umask before anything for security */
+ umask(0027);
+
+ strlcpy(filename, BASE_TMPFILE, BASE_TMPFILE_SIZE);
+ int fd = mkstemp(filename);
+ umask(oldumask);
+
+ if (fd == -1)
+ return -1;
+
+ int i = 0;
+ for (; i < hexbyte_strs_length; i++) {
+ uint8_t byte = (uint8_t)strtol(hexbyte_strs[i], 0, 16);
+ if (write(fd, (char *)&byte, 1) < 0) {
+ return -1;
+ }
+ }
+
+ /* Go back to the beginning of the file */
+ lseek(fd, 0, SEEK_SET);
+ return fd;
+}
+
+static bool pcep_obj_has_tlv(struct pcep_object_header *obj_hdr)
+{
+ if (obj_hdr->tlv_list == NULL) {
+ return false;
+ }
+
+ return (obj_hdr->tlv_list->num_entries > 0);
+}
+
+void test_pcep_msg_read_pcep_initiate()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(filename, pcep_initiate_hexbyte_strs,
+ pcep_initiate_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 4);
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_INITIATE);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_initiate_hexbyte_strs_length);
+
+ /* Verify each of the object types */
+
+ /* SRP object */
+ double_linked_list_node *node = msg->obj_list->head;
+ struct pcep_object_header *obj_hdr =
+ (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_SRP);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_SRP);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length,
+ pcep_object_get_length_by_hdr(obj_hdr));
+ CU_ASSERT_FALSE(pcep_obj_has_tlv(obj_hdr));
+
+ /* LSP object and its TLV*/
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_LSP);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_LSP);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 20);
+ CU_ASSERT_EQUAL(((struct pcep_object_lsp *)obj_hdr)->plsp_id, 0);
+ CU_ASSERT_TRUE(((struct pcep_object_lsp *)obj_hdr)->flag_d);
+ CU_ASSERT_TRUE(((struct pcep_object_lsp *)obj_hdr)->flag_a);
+ CU_ASSERT_FALSE(((struct pcep_object_lsp *)obj_hdr)->flag_s);
+ CU_ASSERT_FALSE(((struct pcep_object_lsp *)obj_hdr)->flag_r);
+ CU_ASSERT_FALSE(((struct pcep_object_lsp *)obj_hdr)->flag_c);
+
+ /* LSP TLV */
+ CU_ASSERT_TRUE(pcep_obj_has_tlv(obj_hdr));
+ CU_ASSERT_EQUAL(obj_hdr->tlv_list->num_entries, 1);
+ struct pcep_object_tlv_header *tlv =
+ (struct pcep_object_tlv_header *)obj_hdr->tlv_list->head->data;
+ CU_ASSERT_EQUAL(tlv->type, PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME);
+ CU_ASSERT_EQUAL(tlv->encoded_tlv_length, 8);
+
+ /* Endpoints object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_ENDPOINTS);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_ENDPOINT_IPV4);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length,
+ pcep_object_get_length_by_hdr(obj_hdr));
+ CU_ASSERT_FALSE(pcep_obj_has_tlv(obj_hdr));
+
+ /* ERO object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_ERO);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_ERO);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 20);
+
+ /* ERO Subobjects */
+ double_linked_list *ero_subobj_list =
+ ((struct pcep_object_ro *)obj_hdr)->sub_objects;
+ CU_ASSERT_PTR_NOT_NULL(ero_subobj_list);
+ assert(ero_subobj_list != NULL);
+ CU_ASSERT_EQUAL(ero_subobj_list->num_entries, 2);
+ double_linked_list_node *subobj_node = ero_subobj_list->head;
+ struct pcep_object_ro_subobj *subobj_hdr =
+ (struct pcep_object_ro_subobj *)subobj_node->data;
+ CU_ASSERT_EQUAL(subobj_hdr->ro_subobj_type, RO_SUBOBJ_TYPE_IPV4);
+ struct in_addr ero_subobj_ip;
+ inet_pton(AF_INET, "10.0.1.1", &ero_subobj_ip);
+ CU_ASSERT_EQUAL(
+ ((struct pcep_ro_subobj_ipv4 *)subobj_hdr)->ip_addr.s_addr,
+ ero_subobj_ip.s_addr);
+ CU_ASSERT_EQUAL(
+ ((struct pcep_ro_subobj_ipv4 *)subobj_hdr)->prefix_length, 24);
+
+ subobj_hdr =
+ (struct pcep_object_ro_subobj *)subobj_node->next_node->data;
+ CU_ASSERT_EQUAL(subobj_hdr->ro_subobj_type, RO_SUBOBJ_TYPE_IPV4);
+ inet_pton(AF_INET, "10.0.7.4", &ero_subobj_ip);
+ CU_ASSERT_EQUAL(
+ ((struct pcep_ro_subobj_ipv4 *)subobj_hdr)->ip_addr.s_addr,
+ ero_subobj_ip.s_addr);
+ CU_ASSERT_EQUAL(
+ ((struct pcep_ro_subobj_ipv4 *)subobj_hdr)->prefix_length, 24);
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+
+void test_pcep_msg_read_pcep_initiate2()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd =
+ convert_hexstrs_to_binary(filename, pcep_initiate2_hexbyte_strs,
+ pcep_initiate2_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 4);
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_INITIATE);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_initiate2_hexbyte_strs_length);
+
+ /* Verify each of the object types */
+
+ /* SRP object */
+ double_linked_list_node *node = msg->obj_list->head;
+ struct pcep_object_header *obj_hdr =
+ (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_SRP);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_SRP);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 20);
+ CU_ASSERT_TRUE(pcep_obj_has_tlv(obj_hdr));
+ /* TODO test the TLVs */
+
+ /* LSP object and its TLV*/
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_LSP);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_LSP);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 20);
+
+ /* LSP TLV */
+ CU_ASSERT_TRUE(pcep_obj_has_tlv(obj_hdr));
+ CU_ASSERT_EQUAL(obj_hdr->tlv_list->num_entries, 1);
+ struct pcep_object_tlv_header *tlv =
+ (struct pcep_object_tlv_header *)obj_hdr->tlv_list->head->data;
+ CU_ASSERT_EQUAL(tlv->type, PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME);
+ CU_ASSERT_EQUAL(tlv->encoded_tlv_length, 8);
+
+ /* Endpoints object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_ENDPOINTS);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_ENDPOINT_IPV4);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length,
+ pcep_object_get_length_by_hdr(obj_hdr));
+ CU_ASSERT_FALSE(pcep_obj_has_tlv(obj_hdr));
+
+ /* ERO object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_ERO);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_ERO);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 16);
+
+ /* ERO Subobjects */
+ double_linked_list *ero_subobj_list =
+ ((struct pcep_object_ro *)obj_hdr)->sub_objects;
+ CU_ASSERT_PTR_NOT_NULL(ero_subobj_list);
+ assert(ero_subobj_list != NULL);
+ CU_ASSERT_EQUAL(ero_subobj_list->num_entries, 0);
+ double_linked_list_node *subobj_node = ero_subobj_list->head;
+ CU_ASSERT_PTR_NULL(subobj_node);
+ /* We no longer support draft07 SR sub-object type=5, and only support
+ type=36 struct pcep_object_ro_subobj *subobj_hdr = (struct
+ pcep_object_ro_subobj *) subobj_node->data;
+ CU_ASSERT_EQUAL(subobj_hdr->ro_subobj_type, RO_SUBOBJ_TYPE_SR);
+ struct pcep_ro_subobj_sr *subobj_sr = (struct pcep_ro_subobj_sr *)
+ subobj_hdr; CU_ASSERT_EQUAL(subobj_sr->nai_type,
+ PCEP_SR_SUBOBJ_NAI_IPV4_NODE); CU_ASSERT_TRUE(subobj_sr->flag_m);
+ CU_ASSERT_FALSE(subobj_sr->flag_c);
+ CU_ASSERT_FALSE(subobj_sr->flag_s);
+ CU_ASSERT_FALSE(subobj_sr->flag_f);
+ CU_ASSERT_EQUAL(subobj_sr->sid, 65576960);
+ CU_ASSERT_EQUAL(*((uint32_t *) subobj_sr->nai_list->head->data),
+ 0x01010101);
+ */
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_pcep_msg_read_pcep_open()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(filename, pcep_open_odl_hexbyte_strs,
+ pcep_open_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 1);
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_OPEN);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_open_hexbyte_strs_length);
+
+ /* Verify the Open message */
+ struct pcep_object_header *obj_hdr =
+ (struct pcep_object_header *)msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_OPEN);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 24);
+ CU_ASSERT_TRUE(pcep_obj_has_tlv(obj_hdr));
+
+ /* Open TLV: Stateful PCE Capability */
+ CU_ASSERT_EQUAL(obj_hdr->tlv_list->num_entries, 2);
+ double_linked_list_node *tlv_node = obj_hdr->tlv_list->head;
+ struct pcep_object_tlv_header *tlv =
+ (struct pcep_object_tlv_header *)tlv_node->data;
+ CU_ASSERT_EQUAL(tlv->type, PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY);
+ CU_ASSERT_EQUAL(tlv->encoded_tlv_length, 4);
+
+ /* Open TLV: SR PCE Capability */
+ tlv_node = tlv_node->next_node;
+ tlv = (struct pcep_object_tlv_header *)tlv_node->data;
+ CU_ASSERT_EQUAL(tlv->type, PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY);
+ CU_ASSERT_EQUAL(tlv->encoded_tlv_length, 4);
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_pcep_msg_read_pcep_update()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(filename, pcep_update_hexbyte_strs,
+ pcep_update_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 3);
+
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_UPDATE);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_update_hexbyte_strs_length);
+
+ /* Verify each of the object types */
+
+ double_linked_list_node *node = msg->obj_list->head;
+
+ /* SRP object */
+ struct pcep_object_header *obj_hdr =
+ (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_SRP);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_SRP);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 20);
+ CU_ASSERT_TRUE(pcep_obj_has_tlv(obj_hdr));
+
+ /* SRP TLV */
+ CU_ASSERT_EQUAL(obj_hdr->tlv_list->num_entries, 1);
+ struct pcep_object_tlv_header *tlv =
+ (struct pcep_object_tlv_header *)obj_hdr->tlv_list->head->data;
+ CU_ASSERT_EQUAL(tlv->type, PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE);
+ CU_ASSERT_EQUAL(tlv->encoded_tlv_length, 4);
+ /* TODO verify the path setup type */
+
+ /* LSP object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_LSP);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_LSP);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length,
+ pcep_object_get_length_by_hdr(obj_hdr));
+ CU_ASSERT_FALSE(pcep_obj_has_tlv(obj_hdr));
+
+ /* ERO object */
+ node = node->next_node;
+ obj_hdr = (struct pcep_object_header *)node->data;
+ CU_ASSERT_EQUAL(obj_hdr->object_class, PCEP_OBJ_CLASS_ERO);
+ CU_ASSERT_EQUAL(obj_hdr->object_type, PCEP_OBJ_TYPE_ERO);
+ CU_ASSERT_EQUAL(obj_hdr->encoded_object_length, 16);
+
+ /* ERO Subobjects */
+ double_linked_list *ero_subobj_list =
+ ((struct pcep_object_ro *)obj_hdr)->sub_objects;
+ CU_ASSERT_PTR_NOT_NULL(ero_subobj_list);
+ assert(ero_subobj_list != NULL);
+ CU_ASSERT_EQUAL(ero_subobj_list->num_entries, 0);
+ double_linked_list_node *subobj_node = ero_subobj_list->head;
+ CU_ASSERT_PTR_NULL(subobj_node);
+ /* We no longer support draft07 SR sub-object type=5, and only support
+ type=36 struct pcep_object_ro_subobj *subobj_hdr = (struct
+ pcep_object_ro_subobj *) subobj_node->data;
+ CU_ASSERT_EQUAL(subobj_hdr->ro_subobj_type, RO_SUBOBJ_TYPE_SR);
+ struct pcep_ro_subobj_sr *subobj_sr = (struct pcep_ro_subobj_sr *)
+ subobj_hdr; CU_ASSERT_EQUAL(subobj_sr->nai_type,
+ PCEP_SR_SUBOBJ_NAI_IPV4_NODE); CU_ASSERT_TRUE(subobj_sr->flag_m);
+ CU_ASSERT_FALSE(subobj_sr->flag_c);
+ CU_ASSERT_FALSE(subobj_sr->flag_s);
+ CU_ASSERT_FALSE(subobj_sr->flag_f);
+ CU_ASSERT_EQUAL(subobj_sr->sid, 65576960);
+ CU_ASSERT_EQUAL(*((uint32_t *) subobj_sr->nai_list->head->data),
+ 0x01010101);
+ */
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_pcep_msg_read_pcep_open_initiate()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(
+ filename, pcep_open_initiate_odl_hexbyte_strs,
+ pcep_open_initiate_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 2);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 1);
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_OPEN);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_open_hexbyte_strs_length);
+
+ msg = (struct pcep_message *)msg_list->head->next_node->data;
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 4);
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_INITIATE);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_initiate2_hexbyte_strs_length);
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_pcep_msg_read_pcep_open_cisco_pce()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(
+ filename, pcep_open_cisco_pce_hexbyte_strs,
+ pcep_open_cisco_pce_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_OPEN);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_open_hexbyte_strs_length);
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 1);
+
+ /* Open object */
+ struct pcep_object_open *open =
+ (struct pcep_object_open *)msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(open->header.object_class, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_EQUAL(open->header.object_type, PCEP_OBJ_TYPE_OPEN);
+ CU_ASSERT_EQUAL(open->header.encoded_object_length, 24);
+ CU_ASSERT_EQUAL(open->open_deadtimer, 120);
+ CU_ASSERT_EQUAL(open->open_keepalive, 60);
+ CU_ASSERT_EQUAL(open->open_sid, 0);
+ CU_ASSERT_EQUAL(open->open_version, 1);
+ CU_ASSERT_PTR_NOT_NULL(open->header.tlv_list);
+ assert(open->header.tlv_list != NULL);
+ CU_ASSERT_EQUAL(open->header.tlv_list->num_entries, 2);
+
+ /* Stateful PCE Capability TLV */
+ double_linked_list_node *tlv_node = open->header.tlv_list->head;
+ struct pcep_object_tlv_stateful_pce_capability *pce_cap_tlv =
+ (struct pcep_object_tlv_stateful_pce_capability *)
+ tlv_node->data;
+ CU_ASSERT_EQUAL(pce_cap_tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY);
+ CU_ASSERT_EQUAL(pce_cap_tlv->header.encoded_tlv_length, 4);
+ CU_ASSERT_TRUE(pce_cap_tlv->flag_u_lsp_update_capability);
+ CU_ASSERT_TRUE(pce_cap_tlv->flag_i_lsp_instantiation_capability);
+ CU_ASSERT_FALSE(pce_cap_tlv->flag_s_include_db_version);
+ CU_ASSERT_FALSE(pce_cap_tlv->flag_t_triggered_resync);
+ CU_ASSERT_FALSE(pce_cap_tlv->flag_d_delta_lsp_sync);
+ CU_ASSERT_FALSE(pce_cap_tlv->flag_f_triggered_initial_sync);
+
+ /* SR PCE Capability TLV */
+ tlv_node = tlv_node->next_node;
+ struct pcep_object_tlv_sr_pce_capability *sr_pce_cap_tlv =
+ (struct pcep_object_tlv_sr_pce_capability *)tlv_node->data;
+ CU_ASSERT_EQUAL(sr_pce_cap_tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY);
+ CU_ASSERT_EQUAL(sr_pce_cap_tlv->header.encoded_tlv_length, 4);
+ CU_ASSERT_FALSE(sr_pce_cap_tlv->flag_n);
+ CU_ASSERT_FALSE(sr_pce_cap_tlv->flag_x);
+ CU_ASSERT_EQUAL(sr_pce_cap_tlv->max_sid_depth, 10);
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_pcep_msg_read_pcep_update_cisco_pce()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(
+ filename, pcep_update_cisco_pce_hexbyte_strs,
+ pcep_update_cisco_pce_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_UPDATE);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_update_cisco_pce_hexbyte_strs_length);
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 4);
+
+ /* SRP object */
+ double_linked_list_node *obj_node = msg->obj_list->head;
+ struct pcep_object_srp *srp = (struct pcep_object_srp *)obj_node->data;
+ CU_ASSERT_EQUAL(srp->header.object_class, PCEP_OBJ_CLASS_SRP);
+ CU_ASSERT_EQUAL(srp->header.object_type, PCEP_OBJ_TYPE_SRP);
+ CU_ASSERT_EQUAL(srp->header.encoded_object_length, 20);
+ CU_ASSERT_PTR_NOT_NULL(srp->header.tlv_list);
+ assert(srp->header.tlv_list != NULL);
+ CU_ASSERT_EQUAL(srp->header.tlv_list->num_entries, 1);
+ CU_ASSERT_EQUAL(srp->srp_id_number, 1);
+ CU_ASSERT_FALSE(srp->flag_lsp_remove);
+
+ /* SRP Path Setup Type TLV */
+ double_linked_list_node *tlv_node = srp->header.tlv_list->head;
+ struct pcep_object_tlv_path_setup_type *pst_tlv =
+ (struct pcep_object_tlv_path_setup_type *)tlv_node->data;
+ CU_ASSERT_EQUAL(pst_tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE);
+ CU_ASSERT_EQUAL(pst_tlv->header.encoded_tlv_length, 4);
+ CU_ASSERT_EQUAL(pst_tlv->path_setup_type, 1);
+
+ /* LSP object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_lsp *lsp = (struct pcep_object_lsp *)obj_node->data;
+ CU_ASSERT_EQUAL(lsp->header.object_class, PCEP_OBJ_CLASS_LSP);
+ CU_ASSERT_EQUAL(lsp->header.object_type, PCEP_OBJ_TYPE_LSP);
+ CU_ASSERT_EQUAL(lsp->header.encoded_object_length, 24);
+ CU_ASSERT_PTR_NOT_NULL(lsp->header.tlv_list);
+ assert(lsp->header.tlv_list != NULL);
+ CU_ASSERT_EQUAL(lsp->header.tlv_list->num_entries, 1);
+ CU_ASSERT_EQUAL(lsp->plsp_id, 524303);
+ CU_ASSERT_EQUAL(lsp->operational_status, PCEP_LSP_OPERATIONAL_DOWN);
+ CU_ASSERT_TRUE(lsp->flag_a);
+ CU_ASSERT_TRUE(lsp->flag_c);
+ CU_ASSERT_TRUE(lsp->flag_d);
+ CU_ASSERT_FALSE(lsp->flag_r);
+ CU_ASSERT_FALSE(lsp->flag_s);
+
+ /* LSP Vendor Info TLV */
+ tlv_node = lsp->header.tlv_list->head;
+ struct pcep_object_tlv_vendor_info *vendor_tlv =
+ (struct pcep_object_tlv_vendor_info *)tlv_node->data;
+ CU_ASSERT_EQUAL(vendor_tlv->header.type, PCEP_OBJ_TLV_TYPE_VENDOR_INFO);
+ CU_ASSERT_EQUAL(vendor_tlv->header.encoded_tlv_length, 12);
+ CU_ASSERT_EQUAL(vendor_tlv->enterprise_number, 9);
+ CU_ASSERT_EQUAL(vendor_tlv->enterprise_specific_info, 0x00030004);
+
+ /* ERO object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_ro *ero = (struct pcep_object_ro *)obj_node->data;
+ CU_ASSERT_EQUAL(ero->header.object_class, PCEP_OBJ_CLASS_ERO);
+ CU_ASSERT_EQUAL(ero->header.object_type, PCEP_OBJ_TYPE_ERO);
+ CU_ASSERT_EQUAL(ero->header.encoded_object_length, 40);
+ CU_ASSERT_PTR_NULL(ero->header.tlv_list);
+ CU_ASSERT_PTR_NOT_NULL(ero->sub_objects);
+ assert(ero->sub_objects != NULL);
+ CU_ASSERT_EQUAL(ero->sub_objects->num_entries, 3);
+
+ /* ERO Subobjects */
+ double_linked_list_node *ero_subobj_node = ero->sub_objects->head;
+ struct pcep_ro_subobj_sr *sr_subobj_ipv4_node =
+ (struct pcep_ro_subobj_sr *)ero_subobj_node->data;
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->ro_subobj.ro_subobj_type,
+ RO_SUBOBJ_TYPE_SR);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->ro_subobj.flag_subobj_loose_hop);
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->nai_type,
+ PCEP_SR_SUBOBJ_NAI_IPV4_NODE);
+ CU_ASSERT_TRUE(sr_subobj_ipv4_node->flag_m);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_c);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_f);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_s);
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->sid, 73748480);
+ CU_ASSERT_EQUAL(
+ *((uint32_t *)sr_subobj_ipv4_node->nai_list->head->data),
+ htonl(0x0a0a0a05));
+
+ ero_subobj_node = ero_subobj_node->next_node;
+ sr_subobj_ipv4_node = (struct pcep_ro_subobj_sr *)ero_subobj_node->data;
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->ro_subobj.ro_subobj_type,
+ RO_SUBOBJ_TYPE_SR);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->ro_subobj.flag_subobj_loose_hop);
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->nai_type,
+ PCEP_SR_SUBOBJ_NAI_IPV4_NODE);
+ CU_ASSERT_TRUE(sr_subobj_ipv4_node->flag_m);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_c);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_f);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_s);
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->sid, 73736192);
+ CU_ASSERT_EQUAL(
+ *((uint32_t *)sr_subobj_ipv4_node->nai_list->head->data),
+ htonl(0x0a0a0a02));
+
+ ero_subobj_node = ero_subobj_node->next_node;
+ sr_subobj_ipv4_node = (struct pcep_ro_subobj_sr *)ero_subobj_node->data;
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->ro_subobj.ro_subobj_type,
+ RO_SUBOBJ_TYPE_SR);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->ro_subobj.flag_subobj_loose_hop);
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->nai_type,
+ PCEP_SR_SUBOBJ_NAI_IPV4_NODE);
+ CU_ASSERT_TRUE(sr_subobj_ipv4_node->flag_m);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_c);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_f);
+ CU_ASSERT_FALSE(sr_subobj_ipv4_node->flag_s);
+ CU_ASSERT_EQUAL(sr_subobj_ipv4_node->sid, 73732096);
+ CU_ASSERT_EQUAL(
+ *((uint32_t *)sr_subobj_ipv4_node->nai_list->head->data),
+ htonl(0x0a0a0a01));
+
+ /* Metric object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_metric *metric =
+ (struct pcep_object_metric *)obj_node->data;
+ CU_ASSERT_EQUAL(metric->header.object_class, PCEP_OBJ_CLASS_METRIC);
+ CU_ASSERT_EQUAL(metric->header.object_type, PCEP_OBJ_TYPE_METRIC);
+ CU_ASSERT_EQUAL(metric->header.encoded_object_length, 12);
+ CU_ASSERT_PTR_NULL(metric->header.tlv_list);
+ CU_ASSERT_FALSE(metric->flag_b);
+ CU_ASSERT_FALSE(metric->flag_c);
+ CU_ASSERT_EQUAL(metric->type, PCEP_METRIC_TE);
+ CU_ASSERT_EQUAL(metric->value, 30.0);
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_pcep_msg_read_pcep_report_cisco_pcc()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(
+ filename, pcep_report_cisco_pcc_hexbyte_strs,
+ pcep_report_cisco_pcc_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_REPORT);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_report_cisco_pcc_hexbyte_strs_length);
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 8);
+
+ /* SRP object */
+ double_linked_list_node *obj_node = msg->obj_list->head;
+ struct pcep_object_srp *srp = (struct pcep_object_srp *)obj_node->data;
+ CU_ASSERT_EQUAL(srp->header.object_class, PCEP_OBJ_CLASS_SRP);
+ CU_ASSERT_EQUAL(srp->header.object_type, PCEP_OBJ_TYPE_SRP);
+ CU_ASSERT_EQUAL(srp->header.encoded_object_length, 20);
+ CU_ASSERT_PTR_NOT_NULL(srp->header.tlv_list);
+ assert(srp->header.tlv_list != NULL);
+ CU_ASSERT_EQUAL(srp->header.tlv_list->num_entries, 1);
+ CU_ASSERT_EQUAL(srp->srp_id_number, 0);
+ CU_ASSERT_FALSE(srp->flag_lsp_remove);
+
+ /* SRP Path Setup Type TLV */
+ double_linked_list_node *tlv_node = srp->header.tlv_list->head;
+ struct pcep_object_tlv_path_setup_type *pst_tlv =
+ (struct pcep_object_tlv_path_setup_type *)tlv_node->data;
+ CU_ASSERT_EQUAL(pst_tlv->header.type,
+ PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE);
+ CU_ASSERT_EQUAL(pst_tlv->header.encoded_tlv_length, 4);
+ CU_ASSERT_EQUAL(pst_tlv->path_setup_type, 1);
+
+ /* LSP object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_lsp *lsp = (struct pcep_object_lsp *)obj_node->data;
+ CU_ASSERT_EQUAL(lsp->header.object_class, PCEP_OBJ_CLASS_LSP);
+ CU_ASSERT_EQUAL(lsp->header.object_type, PCEP_OBJ_TYPE_LSP);
+ CU_ASSERT_EQUAL(lsp->header.encoded_object_length, 60);
+ CU_ASSERT_PTR_NOT_NULL(lsp->header.tlv_list);
+ /* The TLV with ID 65505 is now recognized, and its in the list */
+ CU_ASSERT_EQUAL(lsp->header.tlv_list->num_entries, 3);
+ CU_ASSERT_EQUAL(lsp->plsp_id, 524303);
+ CU_ASSERT_EQUAL(lsp->operational_status, PCEP_LSP_OPERATIONAL_DOWN);
+ CU_ASSERT_TRUE(lsp->flag_a);
+ CU_ASSERT_TRUE(lsp->flag_d);
+ CU_ASSERT_FALSE(lsp->flag_c);
+ CU_ASSERT_FALSE(lsp->flag_r);
+ CU_ASSERT_FALSE(lsp->flag_s);
+
+ /* LSP IPv4 LSP Identifier TLV */
+ tlv_node = lsp->header.tlv_list->head;
+ struct pcep_object_tlv_ipv4_lsp_identifier *ipv4_lsp_id =
+ (struct pcep_object_tlv_ipv4_lsp_identifier *)tlv_node->data;
+ CU_ASSERT_EQUAL(ipv4_lsp_id->header.type,
+ PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS);
+ CU_ASSERT_EQUAL(ipv4_lsp_id->header.encoded_tlv_length, 16);
+ CU_ASSERT_EQUAL(ipv4_lsp_id->ipv4_tunnel_sender.s_addr,
+ htonl(0x0a0a0a06));
+ CU_ASSERT_EQUAL(ipv4_lsp_id->ipv4_tunnel_endpoint.s_addr,
+ htonl(0x0a0a0a01));
+ CU_ASSERT_EQUAL(ipv4_lsp_id->extended_tunnel_id.s_addr,
+ htonl(0x0a0a0a06));
+ CU_ASSERT_EQUAL(ipv4_lsp_id->tunnel_id, 15);
+ CU_ASSERT_EQUAL(ipv4_lsp_id->lsp_id, 2);
+
+ /* LSP Symbolic Path Name TLV */
+ tlv_node = tlv_node->next_node;
+ struct pcep_object_tlv_symbolic_path_name *sym_path_name =
+ (struct pcep_object_tlv_symbolic_path_name *)tlv_node->data;
+ CU_ASSERT_EQUAL(sym_path_name->header.type,
+ PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME);
+ CU_ASSERT_EQUAL(sym_path_name->header.encoded_tlv_length, 13);
+ CU_ASSERT_EQUAL(sym_path_name->symbolic_path_name_length, 13);
+ CU_ASSERT_EQUAL(
+ strncmp(sym_path_name->symbolic_path_name, "cfg_R6-to-R1", 13),
+ 0);
+
+ /* ERO object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_ro *ero = (struct pcep_object_ro *)obj_node->data;
+ CU_ASSERT_EQUAL(ero->header.object_class, PCEP_OBJ_CLASS_ERO);
+ CU_ASSERT_EQUAL(ero->header.object_type, PCEP_OBJ_TYPE_ERO);
+ CU_ASSERT_EQUAL(ero->header.encoded_object_length, 4);
+ CU_ASSERT_PTR_NULL(ero->header.tlv_list);
+ CU_ASSERT_PTR_NOT_NULL(ero->sub_objects);
+ assert(ero->sub_objects != NULL);
+ CU_ASSERT_EQUAL(ero->sub_objects->num_entries, 0);
+
+ /* LSPA object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_lspa *lspa =
+ (struct pcep_object_lspa *)obj_node->data;
+ CU_ASSERT_EQUAL(lspa->header.object_class, PCEP_OBJ_CLASS_LSPA);
+ CU_ASSERT_EQUAL(lspa->header.object_type, PCEP_OBJ_TYPE_LSPA);
+ CU_ASSERT_EQUAL(lspa->header.encoded_object_length, 20);
+ CU_ASSERT_PTR_NULL(lspa->header.tlv_list);
+ CU_ASSERT_TRUE(lspa->flag_local_protection);
+ CU_ASSERT_EQUAL(lspa->holding_priority, 7);
+ CU_ASSERT_EQUAL(lspa->setup_priority, 7);
+ CU_ASSERT_EQUAL(lspa->lspa_include_all, 0);
+ CU_ASSERT_EQUAL(lspa->lspa_include_any, 0);
+ CU_ASSERT_EQUAL(lspa->lspa_exclude_any, 0);
+
+ /* Bandwidth object 1 */
+ obj_node = obj_node->next_node;
+ struct pcep_object_bandwidth *bandwidth =
+ (struct pcep_object_bandwidth *)obj_node->data;
+ CU_ASSERT_EQUAL(bandwidth->header.object_class,
+ PCEP_OBJ_CLASS_BANDWIDTH);
+ CU_ASSERT_EQUAL(bandwidth->header.object_type,
+ PCEP_OBJ_TYPE_BANDWIDTH_REQ);
+ CU_ASSERT_EQUAL(bandwidth->header.encoded_object_length, 8);
+ CU_ASSERT_EQUAL(bandwidth->bandwidth, 0);
+
+ /* Bandwidth object 2 */
+ obj_node = obj_node->next_node;
+ bandwidth = (struct pcep_object_bandwidth *)obj_node->data;
+ CU_ASSERT_EQUAL(bandwidth->header.object_class,
+ PCEP_OBJ_CLASS_BANDWIDTH);
+ CU_ASSERT_EQUAL(bandwidth->header.object_type,
+ PCEP_OBJ_TYPE_BANDWIDTH_CISCO);
+ CU_ASSERT_EQUAL(bandwidth->header.encoded_object_length, 8);
+ CU_ASSERT_EQUAL(bandwidth->bandwidth, 0);
+
+ /* Metric object 1 */
+ obj_node = obj_node->next_node;
+ struct pcep_object_metric *metric =
+ (struct pcep_object_metric *)obj_node->data;
+ CU_ASSERT_EQUAL(metric->header.object_class, PCEP_OBJ_CLASS_METRIC);
+ CU_ASSERT_EQUAL(metric->header.object_type, PCEP_OBJ_TYPE_METRIC);
+ CU_ASSERT_EQUAL(metric->header.encoded_object_length, 12);
+ CU_ASSERT_PTR_NULL(metric->header.tlv_list);
+ CU_ASSERT_FALSE(metric->flag_b);
+ CU_ASSERT_FALSE(metric->flag_c);
+ CU_ASSERT_EQUAL(metric->type, PCEP_METRIC_TE);
+ CU_ASSERT_EQUAL(metric->value, 0);
+
+ /* Metric object 2 */
+ obj_node = obj_node->next_node;
+ metric = (struct pcep_object_metric *)obj_node->data;
+ CU_ASSERT_EQUAL(metric->header.object_class, PCEP_OBJ_CLASS_METRIC);
+ CU_ASSERT_EQUAL(metric->header.object_type, PCEP_OBJ_TYPE_METRIC);
+ CU_ASSERT_EQUAL(metric->header.encoded_object_length, 12);
+ CU_ASSERT_PTR_NULL(metric->header.tlv_list);
+ CU_ASSERT_TRUE(metric->flag_b);
+ CU_ASSERT_FALSE(metric->flag_c);
+ CU_ASSERT_EQUAL(metric->type, PCEP_METRIC_AGGREGATE_BW);
+ CU_ASSERT_EQUAL(metric->value, 16.0);
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_pcep_msg_read_pcep_initiate_cisco_pcc()
+{
+ char filename[BASE_TMPFILE_SIZE];
+
+ int fd = convert_hexstrs_to_binary(
+ filename, pcep_initiate_cisco_pcc_hexbyte_strs,
+ pcep_initiate_cisco_pcc_hexbyte_strs_length);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ double_linked_list *msg_list = pcep_msg_read(fd);
+ CU_ASSERT_PTR_NOT_NULL(msg_list);
+ assert(msg_list != NULL);
+ CU_ASSERT_EQUAL(msg_list->num_entries, 1);
+
+ struct pcep_message *msg = (struct pcep_message *)msg_list->head->data;
+ CU_ASSERT_EQUAL(msg->msg_header->type, PCEP_TYPE_INITIATE);
+ CU_ASSERT_EQUAL(msg->encoded_message_length,
+ pcep_initiate_cisco_pcc_hexbyte_strs_length);
+ CU_ASSERT_EQUAL(msg->obj_list->num_entries, 6);
+
+ /* SRP object */
+ double_linked_list_node *obj_node = msg->obj_list->head;
+ struct pcep_object_srp *srp = (struct pcep_object_srp *)obj_node->data;
+ CU_ASSERT_EQUAL(srp->header.object_class, PCEP_OBJ_CLASS_SRP);
+ CU_ASSERT_EQUAL(srp->header.object_type, PCEP_OBJ_TYPE_SRP);
+ CU_ASSERT_EQUAL(srp->header.encoded_object_length, 20);
+ CU_ASSERT_PTR_NOT_NULL(srp->header.tlv_list);
+ assert(srp->header.tlv_list != NULL);
+ CU_ASSERT_EQUAL(srp->header.tlv_list->num_entries, 1);
+ CU_ASSERT_EQUAL(srp->srp_id_number, 1);
+ CU_ASSERT_FALSE(srp->flag_lsp_remove);
+
+ /* LSP object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_lsp *lsp = (struct pcep_object_lsp *)obj_node->data;
+ CU_ASSERT_EQUAL(lsp->header.object_class, PCEP_OBJ_CLASS_LSP);
+ CU_ASSERT_EQUAL(lsp->header.object_type, PCEP_OBJ_TYPE_LSP);
+ CU_ASSERT_EQUAL(lsp->header.encoded_object_length, 48);
+ CU_ASSERT_PTR_NOT_NULL(lsp->header.tlv_list);
+ assert(lsp->header.tlv_list != NULL);
+ CU_ASSERT_EQUAL(lsp->header.tlv_list->num_entries, 2);
+ CU_ASSERT_EQUAL(lsp->plsp_id, 0);
+ CU_ASSERT_EQUAL(lsp->operational_status, PCEP_LSP_OPERATIONAL_DOWN);
+ CU_ASSERT_TRUE(lsp->flag_a);
+ CU_ASSERT_TRUE(lsp->flag_d);
+ CU_ASSERT_TRUE(lsp->flag_c);
+ CU_ASSERT_FALSE(lsp->flag_r);
+ CU_ASSERT_FALSE(lsp->flag_s);
+
+ /* Endpoint object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_endpoints_ipv4 *endpoint =
+ (struct pcep_object_endpoints_ipv4 *)obj_node->data;
+ CU_ASSERT_EQUAL(endpoint->header.object_class,
+ PCEP_OBJ_CLASS_ENDPOINTS);
+ CU_ASSERT_EQUAL(endpoint->header.object_type,
+ PCEP_OBJ_TYPE_ENDPOINT_IPV4);
+ CU_ASSERT_EQUAL(endpoint->header.encoded_object_length, 12);
+ CU_ASSERT_PTR_NULL(endpoint->header.tlv_list);
+ CU_ASSERT_EQUAL(endpoint->src_ipv4.s_addr, htonl(0x0a0a0a0a));
+ CU_ASSERT_EQUAL(endpoint->dst_ipv4.s_addr, htonl(0x0a0a0a04));
+
+ /* Inter-Layer object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_inter_layer *inter_layer =
+ (struct pcep_object_inter_layer *)obj_node->data;
+ CU_ASSERT_EQUAL(inter_layer->header.object_class,
+ PCEP_OBJ_CLASS_INTER_LAYER);
+ CU_ASSERT_EQUAL(inter_layer->header.object_type,
+ PCEP_OBJ_TYPE_INTER_LAYER);
+ CU_ASSERT_EQUAL(inter_layer->header.encoded_object_length, 8);
+ CU_ASSERT_PTR_NULL(inter_layer->header.tlv_list);
+ CU_ASSERT_TRUE(inter_layer->flag_i);
+ CU_ASSERT_FALSE(inter_layer->flag_m);
+ CU_ASSERT_TRUE(inter_layer->flag_t);
+
+ /* Switch-Layer object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_switch_layer *switch_layer =
+ (struct pcep_object_switch_layer *)obj_node->data;
+ CU_ASSERT_EQUAL(switch_layer->header.object_class,
+ PCEP_OBJ_CLASS_SWITCH_LAYER);
+ CU_ASSERT_EQUAL(switch_layer->header.object_type,
+ PCEP_OBJ_TYPE_SWITCH_LAYER);
+ CU_ASSERT_EQUAL(switch_layer->header.encoded_object_length, 8);
+ CU_ASSERT_PTR_NULL(switch_layer->header.tlv_list);
+ assert(switch_layer->header.tlv_list == NULL);
+ CU_ASSERT_PTR_NOT_NULL(switch_layer->switch_layer_rows);
+ assert(switch_layer->switch_layer_rows != NULL);
+ CU_ASSERT_EQUAL(switch_layer->switch_layer_rows->num_entries, 1);
+ struct pcep_object_switch_layer_row *switch_layer_row =
+ (struct pcep_object_switch_layer_row *)
+ switch_layer->switch_layer_rows->head->data;
+ CU_ASSERT_EQUAL(switch_layer_row->lsp_encoding_type, 0);
+ CU_ASSERT_EQUAL(switch_layer_row->switching_type, 0);
+ CU_ASSERT_FALSE(switch_layer_row->flag_i);
+
+ /* ERO object */
+ obj_node = obj_node->next_node;
+ struct pcep_object_ro *ero = (struct pcep_object_ro *)obj_node->data;
+ CU_ASSERT_EQUAL(ero->header.object_class, PCEP_OBJ_CLASS_ERO);
+ CU_ASSERT_EQUAL(ero->header.object_type, PCEP_OBJ_TYPE_ERO);
+ CU_ASSERT_EQUAL(ero->header.encoded_object_length, 4);
+ CU_ASSERT_PTR_NULL(ero->header.tlv_list);
+
+ pcep_msg_free_message_list(msg_list);
+ close(fd);
+ unlink(filename);
+}
+
+void test_validate_message_header()
+{
+ uint8_t pcep_message_invalid_version[] = {0x40, 0x01, 0x04, 0x00};
+ uint8_t pcep_message_invalid_flags[] = {0x22, 0x01, 0x04, 0x00};
+ uint8_t pcep_message_invalid_length[] = {0x20, 0x01, 0x00, 0x00};
+ uint8_t pcep_message_invalid_type[] = {0x20, 0xff, 0x04, 0x00};
+ uint8_t pcep_message_valid[] = {0x20, 0x01, 0x00, 0x04};
+
+ /* Verify invalid message header version */
+ CU_ASSERT_TRUE(
+ pcep_decode_validate_msg_header(pcep_message_invalid_version)
+ < 0);
+
+ /* Verify invalid message header flags */
+ CU_ASSERT_TRUE(
+ pcep_decode_validate_msg_header(pcep_message_invalid_flags)
+ < 0);
+
+ /* Verify invalid message header lengths */
+ CU_ASSERT_TRUE(
+ pcep_decode_validate_msg_header(pcep_message_invalid_length)
+ < 0);
+ pcep_message_invalid_length[3] = 0x05;
+ CU_ASSERT_TRUE(
+ pcep_decode_validate_msg_header(pcep_message_invalid_length)
+ < 0);
+
+ /* Verify invalid message header types */
+ CU_ASSERT_TRUE(
+ pcep_decode_validate_msg_header(pcep_message_invalid_type) < 0);
+ pcep_message_invalid_type[1] = 0x00;
+ CU_ASSERT_TRUE(
+ pcep_decode_validate_msg_header(pcep_message_invalid_type) < 0);
+
+ /* Verify a valid message header */
+ CU_ASSERT_EQUAL(pcep_decode_validate_msg_header(pcep_message_valid), 4);
+}
+
+/* Internal util function */
+struct pcep_message *create_message(uint8_t msg_type, uint8_t obj1_class,
+ uint8_t obj2_class, uint8_t obj3_class,
+ uint8_t obj4_class)
+{
+ struct pcep_message *msg =
+ pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct pcep_message));
+ msg->obj_list = dll_initialize();
+ msg->msg_header = pceplib_malloc(PCEPLIB_MESSAGES,
+ sizeof(struct pcep_message_header));
+ msg->msg_header->type = msg_type;
+ msg->encoded_message = NULL;
+
+ if (obj1_class > 0) {
+ struct pcep_object_header *obj_hdr = pceplib_malloc(
+ PCEPLIB_MESSAGES, sizeof(struct pcep_object_header));
+ obj_hdr->object_class = obj1_class;
+ obj_hdr->tlv_list = NULL;
+ dll_append(msg->obj_list, obj_hdr);
+ }
+
+ if (obj2_class > 0) {
+ struct pcep_object_header *obj_hdr = pceplib_malloc(
+ PCEPLIB_MESSAGES, sizeof(struct pcep_object_header));
+ obj_hdr->object_class = obj2_class;
+ obj_hdr->tlv_list = NULL;
+ dll_append(msg->obj_list, obj_hdr);
+ }
+
+ if (obj3_class > 0) {
+ struct pcep_object_header *obj_hdr = pceplib_malloc(
+ PCEPLIB_MESSAGES, sizeof(struct pcep_object_header));
+ obj_hdr->object_class = obj3_class;
+ obj_hdr->tlv_list = NULL;
+ dll_append(msg->obj_list, obj_hdr);
+ }
+
+ if (obj4_class > 0) {
+ struct pcep_object_header *obj_hdr = pceplib_malloc(
+ PCEPLIB_MESSAGES, sizeof(struct pcep_object_header));
+ obj_hdr->object_class = obj4_class;
+ obj_hdr->tlv_list = NULL;
+ dll_append(msg->obj_list, obj_hdr);
+ }
+
+ return msg;
+}
+
+void test_validate_message_objects()
+{
+ /* Valid Open message */
+ struct pcep_message *msg =
+ create_message(PCEP_TYPE_OPEN, PCEP_OBJ_CLASS_OPEN, 0, 0, 0);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid KeepAlive message */
+ msg = create_message(PCEP_TYPE_KEEPALIVE, 0, 0, 0, 0);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid PcReq message */
+ /* Using object_class=255 to verify it can take any object */
+ msg = create_message(PCEP_TYPE_PCREQ, PCEP_OBJ_CLASS_RP,
+ PCEP_OBJ_CLASS_ENDPOINTS, any_obj_class, 0);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid PcRep message */
+ msg = create_message(PCEP_TYPE_PCREP, PCEP_OBJ_CLASS_RP, any_obj_class,
+ 0, 0);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid Notify message */
+ msg = create_message(PCEP_TYPE_PCNOTF, PCEP_OBJ_CLASS_NOTF,
+ any_obj_class, 0, 0);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid Error message */
+ msg = create_message(PCEP_TYPE_ERROR, PCEP_OBJ_CLASS_ERROR,
+ any_obj_class, 0, 0);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid Close message */
+ msg = create_message(PCEP_TYPE_CLOSE, PCEP_OBJ_CLASS_CLOSE, 0, 0, 0);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid Report message */
+ msg = create_message(PCEP_TYPE_REPORT, PCEP_OBJ_CLASS_SRP,
+ PCEP_OBJ_CLASS_LSP, any_obj_class, any_obj_class);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid Update message */
+ msg = create_message(PCEP_TYPE_UPDATE, PCEP_OBJ_CLASS_SRP,
+ PCEP_OBJ_CLASS_LSP, any_obj_class, any_obj_class);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Valid Initiate message */
+ msg = create_message(PCEP_TYPE_INITIATE, PCEP_OBJ_CLASS_SRP,
+ PCEP_OBJ_CLASS_LSP, any_obj_class, any_obj_class);
+ CU_ASSERT_TRUE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+}
+
+void test_validate_message_objects_invalid()
+{
+ /* unsupported message ID = 0
+ * {NO_OBJECT, NO_OBJECT, NO_OBJECT, NO_OBJECT} */
+ struct pcep_message *msg = create_message(0, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Open message
+ * {PCEP_OBJ_CLASS_OPEN, NO_OBJECT, NO_OBJECT, NO_OBJECT} */
+ msg = create_message(PCEP_TYPE_OPEN, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_OPEN, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_OPEN, PCEP_OBJ_CLASS_OPEN, any_obj_class,
+ 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* KeepAlive message
+ * {NO_OBJECT, NO_OBJECT, NO_OBJECT, NO_OBJECT} */
+ msg = create_message(PCEP_TYPE_KEEPALIVE, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* PcReq message
+ * {PCEP_OBJ_CLASS_RP, PCEP_OBJ_CLASS_ENDPOINTS, ANY_OBJECT, ANY_OBJECT}
+ */
+ msg = create_message(PCEP_TYPE_PCREQ, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_PCREQ, PCEP_OBJ_CLASS_RP, any_obj_class,
+ 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* PcRep message
+ * {PCEP_OBJ_CLASS_RP, ANY_OBJECT, ANY_OBJECT, ANY_OBJECT} */
+ msg = create_message(PCEP_TYPE_PCREP, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_PCREP, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Notify message
+ * {PCEP_OBJ_CLASS_NOTF, ANY_OBJECT, ANY_OBJECT, ANY_OBJECT} */
+ msg = create_message(PCEP_TYPE_PCNOTF, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_PCNOTF, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Error message
+ * {PCEP_OBJ_CLASS_ERROR, ANY_OBJECT, ANY_OBJECT, ANY_OBJECT} */
+ msg = create_message(PCEP_TYPE_ERROR, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_ERROR, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Close message
+ * {PCEP_OBJ_CLASS_CLOSE, NO_OBJECT, NO_OBJECT, NO_OBJECT} */
+ msg = create_message(PCEP_TYPE_CLOSE, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_CLOSE, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* unsupported message ID = 8
+ * {NO_OBJECT, NO_OBJECT, NO_OBJECT, NO_OBJECT} */
+ msg = create_message(8, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* unsupported message ID = 9
+ * {NO_OBJECT, NO_OBJECT, NO_OBJECT, NO_OBJECT} */
+ msg = create_message(9, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Report message
+ * {PCEP_OBJ_CLASS_SRP, PCEP_OBJ_CLASS_LSP, ANY_OBJECT, ANY_OBJECT} */
+ msg = create_message(PCEP_TYPE_REPORT, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_REPORT, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_REPORT, PCEP_OBJ_CLASS_SRP, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_REPORT, PCEP_OBJ_CLASS_SRP,
+ any_obj_class, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Update message
+ * {PCEP_OBJ_CLASS_SRP, PCEP_OBJ_CLASS_LSP, ANY_OBJECT, ANY_OBJECT} */
+ msg = create_message(PCEP_TYPE_UPDATE, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_UPDATE, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_UPDATE, PCEP_OBJ_CLASS_SRP, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_UPDATE, PCEP_OBJ_CLASS_SRP,
+ any_obj_class, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ /* Initiate message
+ * {PCEP_OBJ_CLASS_SRP, PCEP_OBJ_CLASS_LSP, ANY_OBJECT, ANY_OBJECT} */
+ msg = create_message(PCEP_TYPE_INITIATE, 0, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_INITIATE, any_obj_class, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_INITIATE, PCEP_OBJ_CLASS_SRP, 0, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+
+ msg = create_message(PCEP_TYPE_INITIATE, PCEP_OBJ_CLASS_SRP,
+ any_obj_class, 0, 0);
+ CU_ASSERT_FALSE(validate_message_objects(msg));
+ pcep_msg_free_message(msg);
+}
diff --git a/pceplib/test/pcep_msg_tools_test.h b/pceplib/test/pcep_msg_tools_test.h
new file mode 100644
index 0000000..dc66390
--- /dev/null
+++ b/pceplib/test/pcep_msg_tools_test.h
@@ -0,0 +1,48 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_MSG_TOOLS_TEST_H_
+#define PCEP_MSG_TOOLS_TEST_H_
+
+
+int pcep_tools_test_suite_setup(void);
+int pcep_tools_test_suite_teardown(void);
+void pcep_tools_test_setup(void);
+void pcep_tools_test_teardown(void);
+void test_pcep_msg_read_pcep_initiate(void);
+void test_pcep_msg_read_pcep_initiate2(void);
+void test_pcep_msg_read_pcep_update(void);
+void test_pcep_msg_read_pcep_open(void);
+void test_pcep_msg_read_pcep_open_initiate(void);
+void test_validate_message_header(void);
+void test_validate_message_objects(void);
+void test_validate_message_objects_invalid(void);
+void test_pcep_msg_read_pcep_open_cisco_pce(void);
+void test_pcep_msg_read_pcep_update_cisco_pce(void);
+void test_pcep_msg_read_pcep_report_cisco_pcc(void);
+void test_pcep_msg_read_pcep_initiate_cisco_pcc(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
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);
+}
diff --git a/pceplib/test/pcep_pcc_api_test.h b/pceplib/test/pcep_pcc_api_test.h
new file mode 100644
index 0000000..d3db96e
--- /dev/null
+++ b/pceplib/test/pcep_pcc_api_test.h
@@ -0,0 +1,43 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_PCC_API_TEST_
+#define PCEP_PCC_API_TEST_
+
+int pcep_pcc_api_test_suite_setup(void);
+int pcep_pcc_api_test_suite_teardown(void);
+void pcep_pcc_api_test_setup(void);
+void pcep_pcc_api_test_teardown(void);
+void test_initialize_pcc(void);
+void test_connect_pce(void);
+void test_connect_pce_ipv6(void);
+void test_connect_pce_with_src_ip(void);
+void test_disconnect_pce(void);
+void test_send_message(void);
+void test_event_queue(void);
+void test_get_event_type_str(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_pcc_api_tests.c b/pceplib/test/pcep_pcc_api_tests.c
new file mode 100644
index 0000000..5d9e92c
--- /dev/null
+++ b/pceplib/test/pcep_pcc_api_tests.c
@@ -0,0 +1,92 @@
+/*
+ * 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 <CUnit/Basic.h>
+#include <CUnit/CUnit.h>
+#include <CUnit/TestDB.h>
+
+#include "pcep_pcc_api_test.h"
+
+int main(int argc, char **argv)
+{
+ /* Unused parameters cause compilation warnings */
+ (void)argc;
+ (void)argv;
+
+ CU_initialize_registry();
+
+ /*
+ * Tests defined in pcep_socket_comm_test.c
+ */
+ CU_pSuite test_pcc_api_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP PCC API Test Suite",
+ pcep_pcc_api_test_suite_setup, // suite setup and cleanup
+ // function pointers
+ pcep_pcc_api_test_suite_teardown,
+ pcep_pcc_api_test_setup, // test case setup function pointer
+ pcep_pcc_api_test_teardown); // test case teardown function
+ // pointer
+
+ CU_add_test(test_pcc_api_suite, "test_initialize_pcc",
+ test_initialize_pcc);
+ CU_add_test(test_pcc_api_suite, "test_connect_pce", test_connect_pce);
+ CU_add_test(test_pcc_api_suite, "test_connect_pce_ipv6",
+ test_connect_pce_ipv6);
+ CU_add_test(test_pcc_api_suite, "test_connect_pce_with_src_ip",
+ test_connect_pce_with_src_ip);
+ CU_add_test(test_pcc_api_suite, "test_disconnect_pce",
+ test_disconnect_pce);
+ CU_add_test(test_pcc_api_suite, "test_send_message", test_send_message);
+ CU_add_test(test_pcc_api_suite, "test_event_queue", test_event_queue);
+ CU_add_test(test_pcc_api_suite, "test_get_event_type_str",
+ test_get_event_type_str);
+
+ /*
+ * Run the tests and cleanup.
+ */
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ CU_FailureRecord *failure_record = CU_get_failure_list();
+ if (failure_record != NULL) {
+ printf("\nFailed tests:\n\t [Suite] [Test] [File:line-number]\n");
+ do {
+ printf("\t [%s] [%s] [%s:%d]\n",
+ failure_record->pSuite->pName,
+ failure_record->pTest->pName,
+ failure_record->strFileName,
+ failure_record->uiLineNumber);
+ failure_record = failure_record->pNext;
+
+ } while (failure_record != NULL);
+ }
+
+ CU_pRunSummary run_summary = CU_get_run_summary();
+ int result = run_summary->nTestsFailed;
+ CU_cleanup_registry();
+
+ return result;
+}
diff --git a/pceplib/test/pcep_pcc_api_tests_valgrind.sh b/pceplib/test/pcep_pcc_api_tests_valgrind.sh
new file mode 100755
index 0000000..74494b7
--- /dev/null
+++ b/pceplib/test/pcep_pcc_api_tests_valgrind.sh
@@ -0,0 +1,2 @@
+source pceplib/test/pcep_tests_valgrind.sh
+valgrind_test pceplib/test/pcep_pcc_api_tests
diff --git a/pceplib/test/pcep_session_logic_loop_test.c b/pceplib/test/pcep_session_logic_loop_test.c
new file mode 100644
index 0000000..7a42715
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_loop_test.c
@@ -0,0 +1,245 @@
+/*
+ * 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 <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_msg_encoding.h"
+#include "pcep_session_logic.h"
+#include "pcep_session_logic_internals.h"
+#include "pcep_timers.h"
+#include "pcep_utils_ordered_list.h"
+#include "pcep_utils_memory.h"
+#include "pcep_session_logic_loop_test.h"
+
+
+extern pcep_session_logic_handle *session_logic_handle_;
+extern pcep_event_queue *session_logic_event_queue_;
+
+/*
+ * Test suite setup and teardown called before AND after the test suite.
+ */
+
+int pcep_session_logic_loop_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ return 0;
+}
+
+int pcep_session_logic_loop_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+
+/*
+ * Test case setup and teardown called before AND after each test.
+ */
+
+void pcep_session_logic_loop_test_setup()
+{
+ /* We need to setup the session_logic_handle_ without starting the
+ * thread */
+ session_logic_handle_ = pceplib_malloc(
+ PCEPLIB_INFRA, sizeof(pcep_session_logic_handle));
+ memset(session_logic_handle_, 0, sizeof(pcep_session_logic_handle));
+ session_logic_handle_->active = true;
+ session_logic_handle_->session_list =
+ ordered_list_initialize(pointer_compare_function);
+ session_logic_handle_->session_event_queue = queue_initialize();
+ pthread_cond_init(&(session_logic_handle_->session_logic_cond_var),
+ NULL);
+ pthread_mutex_init(&(session_logic_handle_->session_logic_mutex), NULL);
+ pthread_mutex_init(&(session_logic_handle_->session_list_mutex), NULL);
+
+ pthread_mutex_lock(&(session_logic_handle_->session_logic_mutex));
+ session_logic_handle_->session_logic_condition = true;
+ pthread_cond_signal(&(session_logic_handle_->session_logic_cond_var));
+ pthread_mutex_unlock(&(session_logic_handle_->session_logic_mutex));
+
+ session_logic_event_queue_ =
+ pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_event_queue));
+ memset(session_logic_event_queue_, 0, sizeof(pcep_event_queue));
+ session_logic_event_queue_->event_queue = queue_initialize();
+}
+
+
+void pcep_session_logic_loop_test_teardown()
+{
+ ordered_list_destroy(session_logic_handle_->session_list);
+ queue_destroy(session_logic_handle_->session_event_queue);
+ pthread_mutex_unlock(&(session_logic_handle_->session_logic_mutex));
+ pthread_mutex_destroy(&(session_logic_handle_->session_logic_mutex));
+ pthread_mutex_destroy(&(session_logic_handle_->session_list_mutex));
+ pceplib_free(PCEPLIB_INFRA, session_logic_handle_);
+ session_logic_handle_ = NULL;
+
+ queue_destroy(session_logic_event_queue_->event_queue);
+ pceplib_free(PCEPLIB_INFRA, session_logic_event_queue_);
+ session_logic_event_queue_ = NULL;
+}
+
+
+/*
+ * Test cases
+ */
+
+void test_session_logic_loop_null_data()
+{
+ /* Just testing that it does not core dump */
+ session_logic_loop(NULL);
+}
+
+
+void test_session_logic_loop_inactive()
+{
+ session_logic_handle_->active = false;
+
+ session_logic_loop(session_logic_handle_);
+}
+
+
+void test_session_logic_msg_ready_handler()
+{
+ /* Just testing that it does not core dump */
+ CU_ASSERT_EQUAL(session_logic_msg_ready_handler(NULL, 0), -1);
+
+ /* Read from an empty file should return 0, thus
+ * session_logic_msg_ready_handler returns -1 */
+ mode_t oldumask;
+ oldumask = umask(S_IXUSR | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
+ /* Set umask before anything for security */
+ umask(0027);
+ char tmpfile[] = "/tmp/pceplib_XXXXXX";
+ int fd = mkstemp(tmpfile);
+ umask(oldumask);
+ if (fd == -1) {
+ CU_ASSERT_TRUE(fd >= 0);
+ return;
+ }
+ pcep_session session;
+ memset(&session, 0, sizeof(pcep_session));
+ session.session_id = 100;
+ CU_ASSERT_EQUAL(session_logic_msg_ready_handler(&session, fd), 0);
+ CU_ASSERT_EQUAL(session_logic_handle_->session_event_queue->num_entries,
+ 1);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCE_CLOSED_SOCKET, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ pcep_session_event *socket_event = (pcep_session_event *)queue_dequeue(
+ session_logic_handle_->session_event_queue);
+ CU_ASSERT_PTR_NOT_NULL(socket_event);
+ assert(socket_event != NULL);
+ CU_ASSERT_TRUE(socket_event->socket_closed);
+ pceplib_free(PCEPLIB_INFRA, socket_event);
+
+ /* A pcep_session_event should be created */
+ struct pcep_versioning *versioning = create_default_pcep_versioning();
+ struct pcep_message *keep_alive_msg = pcep_msg_create_keepalive();
+ pcep_encode_message(keep_alive_msg, versioning);
+ int retval = write(fd, (char *)keep_alive_msg->encoded_message,
+ keep_alive_msg->encoded_message_length);
+ CU_ASSERT_TRUE(retval > 0);
+ lseek(fd, 0, SEEK_SET);
+ CU_ASSERT_EQUAL(session_logic_msg_ready_handler(&session, fd),
+ keep_alive_msg->encoded_message_length);
+ CU_ASSERT_EQUAL(session_logic_handle_->session_event_queue->num_entries,
+ 1);
+ socket_event = (pcep_session_event *)queue_dequeue(
+ session_logic_handle_->session_event_queue);
+ CU_ASSERT_PTR_NOT_NULL(socket_event);
+ assert(socket_event != NULL);
+ CU_ASSERT_FALSE(socket_event->socket_closed);
+ CU_ASSERT_PTR_EQUAL(socket_event->session, &session);
+ CU_ASSERT_EQUAL(socket_event->expired_timer_id, TIMER_ID_NOT_SET);
+ CU_ASSERT_PTR_NOT_NULL(socket_event->received_msg_list);
+ pcep_msg_free_message_list(socket_event->received_msg_list);
+ pcep_msg_free_message(keep_alive_msg);
+ destroy_pcep_versioning(versioning);
+ pceplib_free(PCEPLIB_INFRA, socket_event);
+ close(fd);
+ unlink(tmpfile);
+}
+
+
+void test_session_logic_conn_except_notifier()
+{
+ /* Just testing that it does not core dump */
+ session_logic_conn_except_notifier(NULL, 1);
+
+ /* A pcep_session_event should be created */
+ pcep_session session;
+ memset(&session, 0, sizeof(pcep_session));
+ session.session_id = 100;
+ session_logic_conn_except_notifier(&session, 10);
+ CU_ASSERT_EQUAL(session_logic_handle_->session_event_queue->num_entries,
+ 1);
+ pcep_session_event *socket_event = (pcep_session_event *)queue_dequeue(
+ session_logic_handle_->session_event_queue);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(socket_event);
+ assert(socket_event != NULL);
+ CU_ASSERT_TRUE(socket_event->socket_closed);
+ CU_ASSERT_PTR_EQUAL(socket_event->session, &session);
+ CU_ASSERT_EQUAL(socket_event->expired_timer_id, TIMER_ID_NOT_SET);
+ CU_ASSERT_PTR_NULL(socket_event->received_msg_list);
+
+ pceplib_free(PCEPLIB_INFRA, socket_event);
+}
+
+
+void test_session_logic_timer_expire_handler()
+{
+ /* Just testing that it does not core dump */
+ session_logic_timer_expire_handler(NULL, 42);
+
+ /* A pcep_session_event should be created */
+ pcep_session session;
+ memset(&session, 0, sizeof(pcep_session));
+ session.session_id = 100;
+ session_logic_timer_expire_handler(&session, 42);
+ CU_ASSERT_EQUAL(session_logic_handle_->session_event_queue->num_entries,
+ 1);
+ pcep_session_event *socket_event = (pcep_session_event *)queue_dequeue(
+ session_logic_handle_->session_event_queue);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(socket_event);
+ assert(socket_event != NULL);
+ CU_ASSERT_FALSE(socket_event->socket_closed);
+ CU_ASSERT_PTR_EQUAL(socket_event->session, &session);
+ CU_ASSERT_EQUAL(socket_event->expired_timer_id, 42);
+ CU_ASSERT_PTR_NULL(socket_event->received_msg_list);
+
+ pceplib_free(PCEPLIB_INFRA, socket_event);
+}
diff --git a/pceplib/test/pcep_session_logic_loop_test.h b/pceplib/test/pcep_session_logic_loop_test.h
new file mode 100644
index 0000000..ae3c3e3
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_loop_test.h
@@ -0,0 +1,40 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_SESSION_LOGIC_LOOP_TEST_H_
+#define PCEP_SESSION_LOGIC_LOOP_TEST_H_
+
+int pcep_session_logic_loop_test_suite_setup(void);
+int pcep_session_logic_loop_test_suite_teardown(void);
+void pcep_session_logic_loop_test_setup(void);
+void pcep_session_logic_loop_test_teardown(void);
+void test_session_logic_loop_null_data(void);
+void test_session_logic_loop_inactive(void);
+void test_session_logic_msg_ready_handler(void);
+void test_session_logic_conn_except_notifier(void);
+void test_session_logic_timer_expire_handler(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_session_logic_states_test.c b/pceplib/test/pcep_session_logic_states_test.c
new file mode 100644
index 0000000..17ddae6
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_states_test.c
@@ -0,0 +1,933 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_socket_comm_mock.h"
+#include "pcep_session_logic.h"
+#include "pcep_session_logic_internals.h"
+#include "pcep_timers.h"
+#include "pcep_utils_ordered_list.h"
+#include "pcep_utils_double_linked_list.h"
+#include "pcep_utils_memory.h"
+#include "pcep_msg_objects.h"
+#include "pcep_msg_tools.h"
+#include "pcep_session_logic_states_test.h"
+
+/* Functions being tested */
+extern pcep_session_logic_handle *session_logic_handle_;
+extern pcep_event_queue *session_logic_event_queue_;
+
+static pcep_session_event event;
+static pcep_session session;
+/* A message list is a dll of struct pcep_messages_list_node items */
+static double_linked_list *msg_list;
+struct pcep_message *message;
+static bool free_msg_list;
+static bool msg_enqueued;
+/* Forward declaration */
+void destroy_message_for_test(void);
+void create_message_for_test(uint8_t msg_type, bool free_msg_list_at_teardown,
+ bool was_msg_enqueued);
+void test_handle_timer_event_open_keep_alive(void);
+
+/*
+ * Test suite setup and teardown called before AND after the test suite.
+ */
+
+int pcep_session_logic_states_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ return 0;
+}
+
+int pcep_session_logic_states_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+/*
+ * Test case setup and teardown called before AND after each test.
+ */
+
+void pcep_session_logic_states_test_setup()
+{
+ session_logic_handle_ = pceplib_malloc(
+ PCEPLIB_INFRA, sizeof(pcep_session_logic_handle));
+ memset(session_logic_handle_, 0, sizeof(pcep_session_logic_handle));
+
+ session_logic_event_queue_ =
+ pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_event_queue));
+ memset(session_logic_event_queue_, 0, sizeof(pcep_event_queue));
+ session_logic_event_queue_->event_queue = queue_initialize();
+
+ memset(&session, 0, sizeof(pcep_session));
+ session.pcc_config.keep_alive_seconds = 5;
+ session.pcc_config.keep_alive_pce_negotiated_timer_seconds = 5;
+ session.pcc_config.min_keep_alive_seconds = 1;
+ session.pcc_config.max_keep_alive_seconds = 10;
+ session.pcc_config.dead_timer_seconds = 5;
+ session.pcc_config.dead_timer_pce_negotiated_seconds = 5;
+ session.pcc_config.min_dead_timer_seconds = 1;
+ session.pcc_config.max_dead_timer_seconds = 10;
+ session.pcc_config.max_unknown_messages = 2;
+ memcpy(&session.pce_config, &session.pcc_config,
+ sizeof(pcep_configuration));
+ session.num_unknown_messages_time_queue = queue_initialize();
+
+ memset(&event, 0, sizeof(pcep_session_event));
+ event.socket_closed = false;
+ event.session = &session;
+
+ setup_mock_socket_comm_info();
+ free_msg_list = false;
+ msg_enqueued = false;
+}
+
+
+void pcep_session_logic_states_test_teardown()
+{
+ destroy_message_for_test();
+ pceplib_free(PCEPLIB_INFRA, session_logic_handle_);
+ queue_destroy(session_logic_event_queue_->event_queue);
+ pceplib_free(PCEPLIB_INFRA, session_logic_event_queue_);
+ session_logic_handle_ = NULL;
+ session_logic_event_queue_ = NULL;
+ queue_destroy_with_data(session.num_unknown_messages_time_queue);
+ teardown_mock_socket_comm_info();
+}
+
+void create_message_for_test(uint8_t msg_type, bool free_msg_list_at_teardown,
+ bool was_msg_enqueued)
+{
+ /* See the comments in destroy_message_for_test() about these 2
+ * variables */
+ free_msg_list = free_msg_list_at_teardown;
+ msg_enqueued = was_msg_enqueued;
+
+ message = pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct pcep_message));
+ memset(message, 0, sizeof(struct pcep_message));
+
+ message->msg_header = pceplib_malloc(
+ PCEPLIB_MESSAGES, sizeof(struct pcep_message_header));
+ memset(message->msg_header, 0, sizeof(struct pcep_message_header));
+ message->obj_list = dll_initialize();
+ message->msg_header->type = msg_type;
+
+ msg_list = dll_initialize();
+ dll_append(msg_list, message);
+ event.received_msg_list = msg_list;
+}
+
+void destroy_message_for_test()
+{
+ /* Some test cases internally free the message list, so we dont
+ * want to double free it */
+ if (free_msg_list == true) {
+ /* This will destroy both the msg_list and the obj_list */
+ pcep_msg_free_message_list(msg_list);
+ }
+
+ /* Some tests cause the message to be enqueued and dont delete it,
+ * so we have to delete it here */
+ if (msg_enqueued == true) {
+ pcep_msg_free_message(message);
+ }
+}
+
+/*
+ * Test cases
+ */
+
+void test_handle_timer_event_dead_timer()
+{
+ /* Dead Timer expired */
+ event.expired_timer_id = session.timer_id_dead_timer = 100;
+
+ handle_timer_event(&event);
+
+ CU_ASSERT_EQUAL(session.timer_id_dead_timer, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_INITIALIZED);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCE_DEAD_TIMER_EXPIRED, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+
+ /* verify_socket_comm_times_called(
+ * initialized, teardown, connect, send_message, close_after_write,
+ * close, destroy); */
+ verify_socket_comm_times_called(0, 0, 0, 1, 1, 0, 0);
+}
+
+
+void test_handle_timer_event_keep_alive()
+{
+ /* Keep Alive timer expired */
+ event.expired_timer_id = session.timer_id_keep_alive = 200;
+
+ handle_timer_event(&event);
+
+ CU_ASSERT_EQUAL(session.timer_id_keep_alive, TIMER_ID_NOT_SET);
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+}
+
+
+void test_handle_timer_event_open_keep_wait()
+{
+ /* Open Keep Wait timer expired */
+ event.expired_timer_id = session.timer_id_open_keep_wait = 300;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ handle_timer_event(&event);
+
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_wait, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_INITIALIZED);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ verify_socket_comm_times_called(0, 0, 0, 0, 1, 0, 0);
+
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCE_OPEN_KEEP_WAIT_TIMER_EXPIRED, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+
+ /* If the state is not SESSION_STATE_PCEP_CONNECTED, then nothing should
+ * happen */
+ reset_mock_socket_comm_info();
+ session.session_state = SESSION_STATE_UNKNOWN;
+ event.expired_timer_id = session.timer_id_open_keep_wait = 300;
+ handle_timer_event(&event);
+
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_wait, 300);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_UNKNOWN);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+}
+
+
+void test_handle_timer_event_open_keep_alive()
+{
+ /* Open Keep Alive timer expired, but the Keep Alive should not be sent
+ * since the PCE Open has not been received yet */
+ event.expired_timer_id = session.timer_id_open_keep_alive = 300;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ session.pce_open_keep_alive_sent = false;
+ session.pce_open_received = false;
+ handle_timer_event(&event);
+
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_alive, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ CU_ASSERT_FALSE(session.pce_open_keep_alive_sent);
+
+ /* Open Keep Alive timer expired, the Keep Alive should be sent,
+ * but the session should not be connected, since the PCC Open
+ * has not been accepted yet */
+ event.expired_timer_id = session.timer_id_open_keep_alive = 300;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ session.pce_open_keep_alive_sent = false;
+ session.pce_open_received = true;
+ session.pce_open_rejected = false;
+ session.pcc_open_accepted = false;
+ handle_timer_event(&event);
+
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_alive, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ CU_ASSERT_TRUE(session.pce_open_keep_alive_sent);
+
+ /* Open Keep Alive timer expired, the Keep Alive should be sent,
+ * and the session is connected */
+ event.expired_timer_id = session.timer_id_open_keep_alive = 300;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ session.pce_open_keep_alive_sent = false;
+ session.pce_open_received = true;
+ session.pce_open_rejected = false;
+ session.pcc_open_accepted = true;
+ handle_timer_event(&event);
+
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_alive, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTED);
+ CU_ASSERT_FALSE(session.pce_open_keep_alive_sent);
+}
+
+
+void test_handle_socket_comm_event_null_params()
+{
+ /* Verify it doesn't core dump */
+ handle_socket_comm_event(NULL);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ reset_mock_socket_comm_info();
+
+ event.received_msg_list = NULL;
+ handle_socket_comm_event(&event);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+}
+
+
+void test_handle_socket_comm_event_close()
+{
+ event.socket_closed = true;
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_INITIALIZED);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 1, 0);
+
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCE_CLOSED_SOCKET, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
+
+
+void test_handle_socket_comm_event_open()
+{
+ /*
+ * Test when a PCE Open is received, but the PCC Open has not been
+ * accepted yet
+ */
+ create_message_for_test(PCEP_TYPE_OPEN, false, true);
+ struct pcep_object_open *open_object =
+ pcep_obj_create_open(1, 1, 1, NULL);
+ dll_append(message->obj_list, open_object);
+ session.pcc_open_accepted = false;
+ session.pce_open_received = false;
+ session.pce_open_accepted = false;
+ session.timer_id_open_keep_alive = 100;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pce_open_received);
+ CU_ASSERT_TRUE(session.pce_open_accepted);
+ CU_ASSERT_FALSE(session.pce_open_rejected);
+ CU_ASSERT_FALSE(session.pce_open_keep_alive_sent);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ CU_ASSERT_NOT_EQUAL(session.timer_id_open_keep_alive, 100);
+ /* A keep alive response should NOT be sent yet */
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_OPEN, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ destroy_message_for_test();
+
+ /*
+ * Test when a PCE Open is received, and the PCC Open has been accepted
+ */
+ create_message_for_test(PCEP_TYPE_OPEN, false, true);
+ reset_mock_socket_comm_info();
+ open_object = pcep_obj_create_open(1, 1, 1, NULL);
+ dll_append(message->obj_list, open_object);
+ session.pcc_open_accepted = true;
+ session.pce_open_received = false;
+ session.pce_open_accepted = false;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pce_open_received);
+ CU_ASSERT_TRUE(session.pce_open_accepted);
+ CU_ASSERT_FALSE(session.pce_open_rejected);
+ CU_ASSERT_TRUE(session.pce_open_keep_alive_sent);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTED);
+ /* A keep alive response should be sent, accepting the Open */
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 2);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_OPEN, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_CONNECTED_TO_PCE, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ destroy_message_for_test();
+
+ /*
+ * Send a 2nd Open, an error should be sent
+ */
+ create_message_for_test(PCEP_TYPE_OPEN, false, false);
+ reset_mock_socket_comm_info();
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 0);
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ /* 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 *msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(msg);
+ assert(msg != NULL);
+ CU_ASSERT_EQUAL(PCEP_TYPE_ERROR, msg->msg_header->type);
+ /* Verify the error object */
+ CU_ASSERT_EQUAL(1, msg->obj_list->num_entries);
+ struct pcep_object_error *error_obj = msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(PCEP_OBJ_CLASS_ERROR, error_obj->header.object_class);
+ CU_ASSERT_EQUAL(PCEP_OBJ_TYPE_ERROR, error_obj->header.object_type);
+ CU_ASSERT_EQUAL(PCEP_ERRT_ATTEMPT_TO_ESTABLISH_2ND_PCEP_SESSION,
+ error_obj->error_type);
+ CU_ASSERT_EQUAL(PCEP_ERRV_RECVD_INVALID_OPEN_MSG,
+ error_obj->error_value);
+ pcep_msg_free_message(msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+}
+
+
+void test_handle_socket_comm_event_open_error()
+{
+ /* Test when the PCE rejects the PCC Open with an Error
+ * that a "corrected" Open message is sent. */
+
+ create_message_for_test(PCEP_TYPE_ERROR, false, true);
+ struct pcep_object_error *error_object = pcep_obj_create_error(
+ PCEP_ERRT_SESSION_FAILURE, PCEP_ERRV_UNACCEPTABLE_OPEN_MSG_NEG);
+ struct pcep_object_open *error_open_object =
+ pcep_obj_create_open(1, 1, 1, NULL);
+ /* The configured [Keep-alive, Dead-timer] values are [5, 5],
+ * this error open object will request they be changed to [10, 10] */
+ error_open_object->open_keepalive = 10;
+ error_open_object->open_deadtimer = 10;
+ dll_append(message->obj_list, error_object);
+ dll_append(message->obj_list, error_open_object);
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pcc_open_rejected);
+ CU_ASSERT_FALSE(session.pce_open_keep_alive_sent);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ /* Another Open should be sent */
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 2);
+
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_SENT_INVALID_OPEN, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_ERROR, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+
+ /* Check the Corrected Open Message */
+
+ /* 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);
+ assert(encoded_msg != NULL);
+ struct pcep_message *open_msg_corrected =
+ pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(open_msg_corrected);
+ struct pcep_object_open *open_object_corrected =
+ (struct pcep_object_open *)pcep_obj_get(
+ open_msg_corrected->obj_list, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_PTR_NOT_NULL(open_object_corrected);
+ assert(open_object_corrected != NULL);
+ /* Verify the Keep-alive and Dead timers have been negotiated */
+ CU_ASSERT_EQUAL(error_open_object->open_keepalive,
+ open_object_corrected->open_keepalive);
+ CU_ASSERT_EQUAL(error_open_object->open_deadtimer,
+ open_object_corrected->open_deadtimer);
+ CU_ASSERT_EQUAL(session.pcc_config.dead_timer_pce_negotiated_seconds,
+ open_object_corrected->open_deadtimer);
+ CU_ASSERT_EQUAL(
+ session.pcc_config.keep_alive_pce_negotiated_timer_seconds,
+ open_object_corrected->open_keepalive);
+ CU_ASSERT_NOT_EQUAL(
+ session.pcc_config.dead_timer_pce_negotiated_seconds,
+ session.pcc_config.dead_timer_seconds);
+ CU_ASSERT_NOT_EQUAL(
+ session.pcc_config.keep_alive_pce_negotiated_timer_seconds,
+ session.pcc_config.keep_alive_seconds);
+
+ pcep_msg_free_message(open_msg_corrected);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+}
+
+
+void test_handle_socket_comm_event_keep_alive()
+{
+ /* Test when a Keep Alive is received, but the PCE Open has not been
+ * received yet */
+ create_message_for_test(PCEP_TYPE_KEEPALIVE, false, false);
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ session.timer_id_dead_timer = 100;
+ session.timer_id_open_keep_wait = 200;
+ session.pce_open_accepted = false;
+ session.pce_open_received = false;
+ session.pcc_open_accepted = false;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pcc_open_accepted);
+ CU_ASSERT_FALSE(session.pce_open_keep_alive_sent);
+ CU_ASSERT_FALSE(session.pcc_open_rejected);
+ CU_ASSERT_FALSE(session.pce_open_accepted);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_wait, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.timer_id_dead_timer, 100);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 0);
+
+ /* Test when a Keep Alive is received, and the PCE Open has been
+ * received and accepted */
+ create_message_for_test(PCEP_TYPE_KEEPALIVE, false, false);
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ session.timer_id_dead_timer = 100;
+ session.timer_id_open_keep_wait = 200;
+ session.pce_open_received = true;
+ session.pce_open_accepted = true;
+ session.pcc_open_accepted = false;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pcc_open_accepted);
+ CU_ASSERT_TRUE(session.pce_open_keep_alive_sent);
+ CU_ASSERT_FALSE(session.pcc_open_rejected);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTED);
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_wait, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.timer_id_dead_timer, 100);
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+
+ /* Test when a Keep Alive is received, and the PCE Open has been
+ * received and rejected */
+ create_message_for_test(PCEP_TYPE_KEEPALIVE, false, false);
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+ session.timer_id_dead_timer = 100;
+ session.timer_id_open_keep_wait = 200;
+ session.pce_open_received = true;
+ session.pce_open_accepted = false;
+ session.pce_open_rejected = true;
+ session.pce_open_keep_alive_sent = false;
+ session.pcc_open_accepted = true;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pcc_open_accepted);
+ CU_ASSERT_FALSE(session.pce_open_keep_alive_sent);
+ CU_ASSERT_FALSE(session.pcc_open_rejected);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ CU_ASSERT_EQUAL(session.timer_id_open_keep_wait, TIMER_ID_NOT_SET);
+ CU_ASSERT_EQUAL(session.timer_id_dead_timer, 100);
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+
+ /* The session is considered connected, when both the
+ * PCE and PCC Open messages have been accepted */
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_CONNECTED_TO_PCE, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
+
+
+void test_handle_socket_comm_event_pcrep()
+{
+ create_message_for_test(PCEP_TYPE_PCREP, false, true);
+ struct pcep_object_rp *rp =
+ pcep_obj_create_rp(1, true, true, true, true, 1, NULL);
+ dll_append(message->obj_list, rp);
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
+
+
+void test_handle_socket_comm_event_pcreq()
+{
+ create_message_for_test(PCEP_TYPE_PCREQ, false, false);
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ /* The PCC does not support receiving PcReq messages, so an error should
+ * be sent */
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 0);
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ uint8_t *encoded_msg =
+ dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ struct pcep_message *error_msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(error_msg);
+ assert(error_msg != NULL);
+ CU_ASSERT_EQUAL(PCEP_TYPE_ERROR, error_msg->msg_header->type);
+ /* Verify the error object */
+ CU_ASSERT_EQUAL(1, error_msg->obj_list->num_entries);
+ struct pcep_object_error *obj = error_msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(PCEP_OBJ_CLASS_ERROR, obj->header.object_class);
+ CU_ASSERT_EQUAL(PCEP_OBJ_TYPE_ERROR, obj->header.object_type);
+ CU_ASSERT_EQUAL(PCEP_ERRT_CAPABILITY_NOT_SUPPORTED, obj->error_type);
+ CU_ASSERT_EQUAL(PCEP_ERRV_UNASSIGNED, obj->error_value);
+ pcep_msg_free_message(error_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+}
+
+
+void test_handle_socket_comm_event_report()
+{
+ create_message_for_test(PCEP_TYPE_REPORT, false, false);
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ /* The PCC does not support receiving Report messages, so an error
+ * should be sent */
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 0);
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ uint8_t *encoded_msg =
+ dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ struct pcep_message *error_msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(error_msg);
+ assert(error_msg != NULL);
+ CU_ASSERT_EQUAL(PCEP_TYPE_ERROR, error_msg->msg_header->type);
+ /* Verify the error object */
+ CU_ASSERT_EQUAL(1, error_msg->obj_list->num_entries);
+ struct pcep_object_error *obj = error_msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(PCEP_OBJ_CLASS_ERROR, obj->header.object_class);
+ CU_ASSERT_EQUAL(PCEP_OBJ_TYPE_ERROR, obj->header.object_type);
+ CU_ASSERT_EQUAL(PCEP_ERRT_CAPABILITY_NOT_SUPPORTED, obj->error_type);
+ CU_ASSERT_EQUAL(PCEP_ERRV_UNASSIGNED, obj->error_value);
+ pcep_msg_free_message(error_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+}
+
+
+void test_handle_socket_comm_event_update()
+{
+ create_message_for_test(PCEP_TYPE_UPDATE, false, true);
+ struct pcep_object_srp *srp = pcep_obj_create_srp(false, 100, NULL);
+ struct pcep_object_lsp *lsp =
+ pcep_obj_create_lsp(100, PCEP_LSP_OPERATIONAL_UP, true, true,
+ true, true, true, NULL);
+ double_linked_list *ero_subobj_list = dll_initialize();
+ dll_append(ero_subobj_list, pcep_obj_create_ro_subobj_asn(0x0102));
+ struct pcep_object_ro *ero = pcep_obj_create_ero(ero_subobj_list);
+ struct pcep_object_metric *metric =
+ pcep_obj_create_metric(PCEP_METRIC_TE, false, true, 16.0);
+ dll_append(message->obj_list, srp);
+ dll_append(message->obj_list, lsp);
+ dll_append(message->obj_list, ero);
+ dll_append(message->obj_list, metric);
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_UPDATE, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
+
+
+void test_handle_socket_comm_event_initiate()
+{
+ create_message_for_test(PCEP_TYPE_INITIATE, false, true);
+ struct pcep_object_srp *srp = pcep_obj_create_srp(false, 100, NULL);
+ struct pcep_object_lsp *lsp =
+ pcep_obj_create_lsp(100, PCEP_LSP_OPERATIONAL_UP, true, true,
+ true, true, true, NULL);
+ dll_append(message->obj_list, srp);
+ dll_append(message->obj_list, lsp);
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_INITIATE, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
+
+
+void test_handle_socket_comm_event_notify()
+{
+ create_message_for_test(PCEP_TYPE_PCNOTF, false, true);
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_PCNOTF, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
+
+
+void test_handle_socket_comm_event_error()
+{
+ create_message_for_test(PCEP_TYPE_ERROR, false, true);
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 0, 0);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_ERROR, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
+
+
+void test_handle_socket_comm_event_unknown_msg()
+{
+ create_message_for_test(13, false, false);
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ /* Sending an unsupported message type, so an error should be sent,
+ * but the connection should remain open, since max_unknown_messages = 2
+ */
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 0);
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ 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(PCEP_TYPE_ERROR, msg->msg_header->type);
+ /* Verify the error object */
+ CU_ASSERT_EQUAL(1, msg->obj_list->num_entries);
+ struct pcep_object_error *error_obj = msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(PCEP_OBJ_CLASS_ERROR, error_obj->header.object_class);
+ CU_ASSERT_EQUAL(PCEP_OBJ_TYPE_ERROR, error_obj->header.object_type);
+ CU_ASSERT_EQUAL(PCEP_ERRT_CAPABILITY_NOT_SUPPORTED,
+ error_obj->error_type);
+ CU_ASSERT_EQUAL(PCEP_ERRV_UNASSIGNED, error_obj->error_value);
+ pcep_msg_free_message(msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+ destroy_message_for_test();
+
+ /* Send another unsupported message type, an error should be sent and
+ * the connection should be closed, since max_unknown_messages = 2 */
+ create_message_for_test(13, false, false);
+ reset_mock_socket_comm_info();
+ mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+
+ handle_socket_comm_event(&event);
+
+ verify_socket_comm_times_called(0, 0, 0, 2, 1, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_RCVD_MAX_UNKOWN_MSGS, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+
+ /* Verify the error message */
+ encoded_msg = dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ assert(encoded_msg != NULL);
+ msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(msg);
+ CU_ASSERT_EQUAL(PCEP_TYPE_ERROR, msg->msg_header->type);
+ /* Verify the error object */
+ CU_ASSERT_EQUAL(1, msg->obj_list->num_entries);
+ error_obj = msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(PCEP_OBJ_CLASS_ERROR, error_obj->header.object_class);
+ CU_ASSERT_EQUAL(PCEP_OBJ_TYPE_ERROR, error_obj->header.object_type);
+ CU_ASSERT_EQUAL(PCEP_ERRT_CAPABILITY_NOT_SUPPORTED,
+ error_obj->error_type);
+ CU_ASSERT_EQUAL(PCEP_ERRV_UNASSIGNED, error_obj->error_value);
+ pcep_msg_free_message(msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+
+ /* Verify the Close message */
+ encoded_msg = dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ assert(encoded_msg != NULL);
+ msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(msg);
+ assert(msg != NULL);
+ CU_ASSERT_EQUAL(PCEP_TYPE_CLOSE, msg->msg_header->type);
+ /* Verify the error object */
+ CU_ASSERT_EQUAL(1, msg->obj_list->num_entries);
+ struct pcep_object_close *close_obj = msg->obj_list->head->data;
+ CU_ASSERT_EQUAL(PCEP_OBJ_CLASS_CLOSE, close_obj->header.object_class);
+ CU_ASSERT_EQUAL(PCEP_OBJ_TYPE_CLOSE, close_obj->header.object_type);
+ CU_ASSERT_EQUAL(PCEP_CLOSE_REASON_UNREC_MSG, close_obj->reason);
+ pcep_msg_free_message(msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+}
+
+
+void test_connection_failure(void)
+{
+ /*
+ * Test when 2 invalid Open messages are received that a
+ * PCC_CONNECTION_FAILURE event is generated.
+ */
+ create_message_for_test(PCEP_TYPE_OPEN, false, false);
+ reset_mock_socket_comm_info();
+ struct pcep_object_open *open_object =
+ pcep_obj_create_open(1, 1, 1, NULL);
+ /* Make the Open message invalid */
+ open_object->open_deadtimer =
+ session.pcc_config.max_dead_timer_seconds + 1;
+ dll_append(message->obj_list, open_object);
+ session.pce_open_received = false;
+ session.pce_open_accepted = false;
+ session.pce_open_rejected = false;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pce_open_received);
+ CU_ASSERT_TRUE(session.pce_open_rejected);
+ CU_ASSERT_FALSE(session.pce_open_accepted);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ /* An error response should be sent, rejecting the Open */
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 1);
+ pcep_event *e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_RCVD_INVALID_OPEN, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ destroy_message_for_test();
+
+ /* Send the same erroneous Open again */
+ create_message_for_test(PCEP_TYPE_OPEN, false, false);
+ reset_mock_socket_comm_info();
+ open_object = pcep_obj_create_open(1, 1, 1, NULL);
+ /* Make the Open message invalid */
+ open_object->open_deadtimer =
+ session.pcc_config.max_dead_timer_seconds + 1;
+ dll_append(message->obj_list, open_object);
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pce_open_received);
+ CU_ASSERT_TRUE(session.pce_open_rejected);
+ CU_ASSERT_FALSE(session.pce_open_accepted);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_INITIALIZED);
+ /* An error response should be sent, rejecting the Open */
+ verify_socket_comm_times_called(0, 0, 0, 1, 1, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 2);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_RCVD_INVALID_OPEN, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_CONNECTION_FAILURE, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+
+ destroy_message_for_test();
+
+ /*
+ * Test when 2 invalid Open messages are sent that a
+ * PCC_CONNECTION_FAILURE event is generated.
+ */
+ create_message_for_test(PCEP_TYPE_ERROR, false, false);
+ reset_mock_socket_comm_info();
+ struct pcep_object_error *error_object = pcep_obj_create_error(
+ PCEP_ERRT_SESSION_FAILURE, PCEP_ERRV_UNACCEPTABLE_OPEN_MSG_NEG);
+ dll_append(message->obj_list, error_object);
+ session.pcc_open_accepted = false;
+ session.pcc_open_rejected = false;
+ session.session_state = SESSION_STATE_PCEP_CONNECTING;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pcc_open_rejected);
+ CU_ASSERT_FALSE(session.pcc_open_accepted);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_PCEP_CONNECTING);
+ /* Another Open should be sent */
+ verify_socket_comm_times_called(0, 0, 0, 1, 0, 0, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 2);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_SENT_INVALID_OPEN, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(MESSAGE_RECEIVED, e->event_type);
+ CU_ASSERT_EQUAL(PCEP_TYPE_ERROR, e->message->msg_header->type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ destroy_message_for_test();
+
+ /* Send a socket close while connecting, which should
+ * generate a PCC_CONNECTION_FAILURE event */
+ reset_mock_socket_comm_info();
+ event.socket_closed = true;
+ event.received_msg_list = NULL;
+
+ handle_socket_comm_event(&event);
+
+ CU_ASSERT_TRUE(session.pcc_open_rejected);
+ CU_ASSERT_FALSE(session.pcc_open_accepted);
+ CU_ASSERT_EQUAL(session.session_state, SESSION_STATE_INITIALIZED);
+ verify_socket_comm_times_called(0, 0, 0, 0, 0, 1, 0);
+ CU_ASSERT_EQUAL(session_logic_event_queue_->event_queue->num_entries,
+ 2);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCE_CLOSED_SOCKET, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+ e = queue_dequeue(session_logic_event_queue_->event_queue);
+ CU_ASSERT_EQUAL(PCC_CONNECTION_FAILURE, e->event_type);
+ pceplib_free(PCEPLIB_INFRA, e);
+}
diff --git a/pceplib/test/pcep_session_logic_states_test.h b/pceplib/test/pcep_session_logic_states_test.h
new file mode 100644
index 0000000..e42b501
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_states_test.h
@@ -0,0 +1,52 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_SESSION_LOGIC_STATES_TEST_H
+#define PCEP_SESSION_LOGIC_STATES_TEST_H
+
+int pcep_session_logic_states_test_suite_setup(void);
+int pcep_session_logic_states_test_suite_teardown(void);
+void pcep_session_logic_states_test_setup(void);
+void pcep_session_logic_states_test_teardown(void);
+void test_handle_timer_event_dead_timer(void);
+void test_handle_timer_event_keep_alive(void);
+void test_handle_timer_event_open_keep_wait(void);
+void test_handle_socket_comm_event_null_params(void);
+void test_handle_socket_comm_event_close(void);
+void test_handle_socket_comm_event_open(void);
+void test_handle_socket_comm_event_open_error(void);
+void test_handle_socket_comm_event_keep_alive(void);
+void test_handle_socket_comm_event_pcrep(void);
+void test_handle_socket_comm_event_pcreq(void);
+void test_handle_socket_comm_event_report(void);
+void test_handle_socket_comm_event_update(void);
+void test_handle_socket_comm_event_initiate(void);
+void test_handle_socket_comm_event_notify(void);
+void test_handle_socket_comm_event_error(void);
+void test_handle_socket_comm_event_unknown_msg(void);
+void test_connection_failure(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_session_logic_test.c b/pceplib/test/pcep_session_logic_test.c
new file mode 100644
index 0000000..8339a7a
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_test.c
@@ -0,0 +1,381 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_socket_comm_mock.h"
+#include "pcep_session_logic.h"
+#include "pcep_session_logic_test.h"
+
+/*
+ * Test suite setup and teardown called before AND after the test suite.
+ */
+
+int pcep_session_logic_test_suite_setup(void)
+{
+ pceplib_memory_reset();
+ return 0;
+}
+
+int pcep_session_logic_test_suite_teardown(void)
+{
+ printf("\n");
+ pceplib_memory_dump();
+ return 0;
+}
+
+/*
+ * Test case setup and teardown called before AND after each test.
+ */
+
+void pcep_session_logic_test_setup()
+{
+ setup_mock_socket_comm_info();
+}
+
+
+void pcep_session_logic_test_teardown()
+{
+ stop_session_logic();
+ teardown_mock_socket_comm_info();
+}
+
+
+/*
+ * Test cases
+ */
+
+void test_run_stop_session_logic()
+{
+ CU_ASSERT_TRUE(run_session_logic());
+ CU_ASSERT_TRUE(stop_session_logic());
+}
+
+
+void test_run_session_logic_twice()
+{
+ CU_ASSERT_TRUE(run_session_logic());
+ CU_ASSERT_FALSE(run_session_logic());
+}
+
+
+void test_session_logic_without_run()
+{
+ /* Verify the functions that depend on run_session_logic() being called
+ */
+ CU_ASSERT_FALSE(stop_session_logic());
+}
+
+
+void test_create_pcep_session_null_params()
+{
+ pcep_configuration config;
+ struct in_addr pce_ip;
+
+ CU_ASSERT_PTR_NULL(create_pcep_session(NULL, NULL));
+ CU_ASSERT_PTR_NULL(create_pcep_session(NULL, &pce_ip));
+ CU_ASSERT_PTR_NULL(create_pcep_session(&config, NULL));
+}
+
+
+void test_create_destroy_pcep_session()
+{
+ pcep_session *session;
+ pcep_configuration config;
+ struct in_addr pce_ip;
+
+ run_session_logic();
+
+ memset(&config, 0, sizeof(pcep_configuration));
+ config.keep_alive_seconds = 5;
+ config.dead_timer_seconds = 5;
+ config.request_time_seconds = 5;
+ config.max_unknown_messages = 5;
+ config.max_unknown_requests = 5;
+ inet_pton(AF_INET, "127.0.0.1", &(pce_ip));
+
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+ session = create_pcep_session(&config, &pce_ip);
+ CU_ASSERT_PTR_NOT_NULL(session);
+ /* 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);
+ /* Should be an Open, with no TLVs: length = 12 */
+ CU_ASSERT_EQUAL(open_msg->msg_header->type, PCEP_TYPE_OPEN);
+ CU_ASSERT_EQUAL(open_msg->encoded_message_length, 12);
+ destroy_pcep_session(session);
+ pcep_msg_free_message(open_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+
+ stop_session_logic();
+}
+
+
+void test_create_destroy_pcep_session_ipv6()
+{
+ pcep_session *session;
+ pcep_configuration config;
+ struct in6_addr pce_ip;
+
+ run_session_logic();
+
+ memset(&config, 0, sizeof(pcep_configuration));
+ config.keep_alive_seconds = 5;
+ config.dead_timer_seconds = 5;
+ config.request_time_seconds = 5;
+ config.max_unknown_messages = 5;
+ config.max_unknown_requests = 5;
+ config.is_src_ipv6 = true;
+ inet_pton(AF_INET6, "::1", &pce_ip);
+
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+ session = create_pcep_session_ipv6(&config, &pce_ip);
+ CU_ASSERT_PTR_NOT_NULL(session);
+ assert(session != NULL);
+ CU_ASSERT_TRUE(session->socket_comm_session->is_ipv6);
+ /* 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);
+ /* Should be an Open, with no TLVs: length = 12 */
+ CU_ASSERT_EQUAL(open_msg->msg_header->type, PCEP_TYPE_OPEN);
+ CU_ASSERT_EQUAL(open_msg->encoded_message_length, 12);
+ destroy_pcep_session(session);
+ pcep_msg_free_message(open_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+
+ stop_session_logic();
+}
+
+
+void test_create_pcep_session_open_tlvs()
+{
+ pcep_session *session;
+ struct in_addr pce_ip;
+ struct pcep_message *open_msg;
+ struct pcep_object_header *open_obj;
+ pcep_configuration config;
+ memset(&config, 0, sizeof(pcep_configuration));
+ config.pcep_msg_versioning = create_default_pcep_versioning();
+ inet_pton(AF_INET, "127.0.0.1", &(pce_ip));
+
+ run_session_logic();
+
+ /* Verify the created Open message only has 1 TLV:
+ * pcep_tlv_create_stateful_pce_capability() */
+ mock_socket_comm_info *mock_info = get_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+ config.support_stateful_pce_lsp_update = true;
+ config.pcep_msg_versioning->draft_ietf_pce_segment_routing_07 = false;
+ config.support_sr_te_pst = false;
+
+ session = create_pcep_session(&config, &pce_ip);
+ CU_ASSERT_PTR_NOT_NULL(session);
+ /* Get and verify the Open Message */
+ uint8_t *encoded_msg =
+ dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ open_msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(open_msg);
+ assert(open_msg != NULL);
+ /* Get and verify the Open Message objects */
+ CU_ASSERT_PTR_NOT_NULL(open_msg->obj_list);
+ assert(open_msg->obj_list != NULL);
+ CU_ASSERT_TRUE(open_msg->obj_list->num_entries > 0);
+ /* Get and verify the Open object */
+ open_obj = pcep_obj_get(open_msg->obj_list, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_PTR_NOT_NULL(open_obj);
+ /* Get and verify the Open object TLVs */
+ CU_ASSERT_PTR_NOT_NULL(open_obj->tlv_list);
+ assert(open_obj->tlv_list != NULL);
+ CU_ASSERT_EQUAL(open_obj->tlv_list->num_entries, 1);
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)
+ open_obj->tlv_list->head->data)
+ ->type,
+ PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY);
+
+ destroy_pcep_session(session);
+ pcep_msg_free_message(open_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+
+ /* Verify the created Open message only has 2 TLVs:
+ * pcep_tlv_create_stateful_pce_capability()
+ * pcep_tlv_create_lsp_db_version() */
+ reset_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+ config.support_include_db_version = true;
+ config.lsp_db_version = 100;
+
+ session = create_pcep_session(&config, &pce_ip);
+ CU_ASSERT_PTR_NOT_NULL(session);
+ /* Get and verify the Open Message */
+ encoded_msg = dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ open_msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(open_msg);
+ /* Get and verify the Open Message objects */
+ CU_ASSERT_PTR_NOT_NULL(open_msg->obj_list);
+ assert(open_msg != NULL);
+ CU_ASSERT_TRUE(open_msg->obj_list->num_entries > 0);
+ /* Get and verify the Open object */
+ open_obj = pcep_obj_get(open_msg->obj_list, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_PTR_NOT_NULL(open_obj);
+ /* Get and verify the Open object TLVs */
+ CU_ASSERT_PTR_NOT_NULL(open_obj->tlv_list);
+ assert(open_obj->tlv_list != NULL);
+ CU_ASSERT_EQUAL(open_obj->tlv_list->num_entries, 2);
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)
+ open_obj->tlv_list->head->data)
+ ->type,
+ PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY);
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)
+ open_obj->tlv_list->head->next_node->data)
+ ->type,
+ PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION);
+
+ destroy_pcep_session(session);
+ pcep_msg_free_message(open_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+
+
+ /* Verify the created Open message only has 4 TLVs:
+ * pcep_tlv_create_stateful_pce_capability()
+ * pcep_tlv_create_lsp_db_version()
+ * pcep_tlv_create_sr_pce_capability()
+ * pcep_tlv_create_path_setup_type_capability() */
+ reset_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+ config.support_sr_te_pst = true;
+
+ session = create_pcep_session(&config, &pce_ip);
+ CU_ASSERT_PTR_NOT_NULL(session);
+ /* Get and verify the Open Message */
+ encoded_msg = dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ open_msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(open_msg);
+ assert(open_msg != NULL);
+ /* Get and verify the Open Message objects */
+ CU_ASSERT_PTR_NOT_NULL(open_msg->obj_list);
+ assert(open_msg->obj_list != NULL);
+ CU_ASSERT_TRUE(open_msg->obj_list->num_entries > 0);
+ /* Get and verify the Open object */
+ open_obj = pcep_obj_get(open_msg->obj_list, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_PTR_NOT_NULL(open_obj);
+ /* Get and verify the Open object TLVs */
+ CU_ASSERT_PTR_NOT_NULL(open_obj->tlv_list);
+ assert(open_obj->tlv_list != NULL);
+ CU_ASSERT_EQUAL(open_obj->tlv_list->num_entries, 3);
+ double_linked_list_node *tlv_node = open_obj->tlv_list->head;
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)tlv_node->data)->type,
+ PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY);
+ tlv_node = tlv_node->next_node;
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)tlv_node->data)->type,
+ PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION);
+ tlv_node = tlv_node->next_node;
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)tlv_node->data)->type,
+ PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY);
+
+ destroy_pcep_session(session);
+ pcep_msg_free_message(open_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+
+ /* Verify the created Open message only has 4 TLVs:
+ * pcep_tlv_create_stateful_pce_capability()
+ * pcep_tlv_create_lsp_db_version()
+ * pcep_tlv_create_sr_pce_capability()
+ * pcep_tlv_create_path_setup_type_capability() */
+ reset_mock_socket_comm_info();
+ mock_info->send_message_save_message = true;
+ config.pcep_msg_versioning->draft_ietf_pce_segment_routing_07 = true;
+
+ session = create_pcep_session(&config, &pce_ip);
+ CU_ASSERT_PTR_NOT_NULL(session);
+ /* Get and verify the Open Message */
+ encoded_msg = dll_delete_first_node(mock_info->sent_message_list);
+ CU_ASSERT_PTR_NOT_NULL(encoded_msg);
+ assert(encoded_msg != NULL);
+ open_msg = pcep_decode_message(encoded_msg);
+ CU_ASSERT_PTR_NOT_NULL(open_msg);
+ assert(open_msg != NULL);
+ /* Get and verify the Open Message objects */
+ CU_ASSERT_PTR_NOT_NULL(open_msg->obj_list);
+ assert(open_msg->obj_list != NULL);
+ CU_ASSERT_TRUE(open_msg->obj_list->num_entries > 0);
+ /* Get and verify the Open object */
+ open_obj = pcep_obj_get(open_msg->obj_list, PCEP_OBJ_CLASS_OPEN);
+ CU_ASSERT_PTR_NOT_NULL(open_obj);
+ assert(open_obj != NULL);
+ /* Get and verify the Open object TLVs */
+ CU_ASSERT_PTR_NOT_NULL(open_obj->tlv_list);
+ assert(open_obj->tlv_list != NULL);
+ CU_ASSERT_EQUAL(open_obj->tlv_list->num_entries, 4);
+ tlv_node = open_obj->tlv_list->head;
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)tlv_node->data)->type,
+ PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY);
+ tlv_node = tlv_node->next_node;
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)tlv_node->data)->type,
+ PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION);
+ tlv_node = tlv_node->next_node;
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)tlv_node->data)->type,
+ PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY);
+ tlv_node = tlv_node->next_node;
+ CU_ASSERT_EQUAL(((struct pcep_object_tlv_header *)tlv_node->data)->type,
+ PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY);
+
+ destroy_pcep_versioning(config.pcep_msg_versioning);
+ destroy_pcep_session(session);
+ pcep_msg_free_message(open_msg);
+ pceplib_free(PCEPLIB_MESSAGES, encoded_msg);
+
+ stop_session_logic();
+}
+
+
+void test_destroy_pcep_session_null_session()
+{
+ /* Just testing that it does not core dump */
+ destroy_pcep_session(NULL);
+}
diff --git a/pceplib/test/pcep_session_logic_test.h b/pceplib/test/pcep_session_logic_test.h
new file mode 100644
index 0000000..6cc1963
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_test.h
@@ -0,0 +1,43 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_SESSION_LOGIC_TEST_H_
+#define PCEP_SESSION_LOGIC_TEST_H_
+
+int pcep_session_logic_test_suite_setup(void);
+int pcep_session_logic_test_suite_teardown(void);
+void pcep_session_logic_test_setup(void);
+void pcep_session_logic_test_teardown(void);
+void test_run_stop_session_logic(void);
+void test_run_session_logic_twice(void);
+void test_session_logic_without_run(void);
+void test_create_pcep_session_null_params(void);
+void test_create_destroy_pcep_session(void);
+void test_create_destroy_pcep_session_ipv6(void);
+void test_create_pcep_session_open_tlvs(void);
+void test_destroy_pcep_session_null_session(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_session_logic_tests.c b/pceplib/test/pcep_session_logic_tests.c
new file mode 100644
index 0000000..9a15390
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_tests.c
@@ -0,0 +1,205 @@
+/*
+ * 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 <CUnit/Basic.h>
+#include <CUnit/CUnit.h>
+#include <CUnit/TestDB.h>
+
+#include "pcep_session_logic_loop_test.h"
+#include "pcep_session_logic_states_test.h"
+#include "pcep_session_logic_test.h"
+
+
+int main(int argc, char **argv)
+{
+ /* Unused parameters cause compilation warnings */
+ (void)argc;
+ (void)argv;
+
+ CU_initialize_registry();
+
+ /*
+ * Tests defined in pcep_socket_comm_test.c
+ */
+ CU_pSuite test_session_logic_suite =
+ CU_add_suite_with_setup_and_teardown(
+ "PCEP Session Logic Test Suite",
+ pcep_session_logic_test_suite_setup, // suite setup and
+ // cleanup function
+ // pointers
+ pcep_session_logic_test_suite_teardown,
+ pcep_session_logic_test_setup, // test case setup
+ // function pointer
+ pcep_session_logic_test_teardown); // test case teardown
+ // function pointer
+
+ CU_add_test(test_session_logic_suite, "test_run_stop_session_logic",
+ test_run_stop_session_logic);
+ CU_add_test(test_session_logic_suite, "test_run_session_logic_twice",
+ test_run_session_logic_twice);
+ CU_add_test(test_session_logic_suite, "test_session_logic_without_run",
+ test_session_logic_without_run);
+ CU_add_test(test_session_logic_suite,
+ "test_create_pcep_session_null_params",
+ test_create_pcep_session_null_params);
+ CU_add_test(test_session_logic_suite,
+ "test_create_destroy_pcep_session",
+ test_create_destroy_pcep_session);
+ CU_add_test(test_session_logic_suite,
+ "test_create_destroy_pcep_session_ipv6",
+ test_create_destroy_pcep_session_ipv6);
+ CU_add_test(test_session_logic_suite,
+ "test_create_pcep_session_open_tlvs",
+ test_create_pcep_session_open_tlvs);
+ CU_add_test(test_session_logic_suite,
+ "test_destroy_pcep_session_null_session",
+ test_destroy_pcep_session_null_session);
+
+ CU_pSuite test_session_logic_loop_suite =
+ CU_add_suite_with_setup_and_teardown(
+ "PCEP Session Logic Loop Test Suite",
+ pcep_session_logic_loop_test_suite_setup, // suite setup
+ // and cleanup
+ // function
+ // pointers
+ pcep_session_logic_loop_test_suite_teardown,
+ pcep_session_logic_loop_test_setup, // test case setup
+ // function pointer
+ pcep_session_logic_loop_test_teardown); // test case
+ // teardown
+ // function
+ // pointer
+
+ CU_add_test(test_session_logic_loop_suite,
+ "test_session_logic_loop_null_data",
+ test_session_logic_loop_null_data);
+ CU_add_test(test_session_logic_loop_suite,
+ "test_session_logic_loop_inactive",
+ test_session_logic_loop_inactive);
+ CU_add_test(test_session_logic_loop_suite,
+ "test_session_logic_msg_ready_handler",
+ test_session_logic_msg_ready_handler);
+ CU_add_test(test_session_logic_loop_suite,
+ "test_session_logic_conn_except_notifier",
+ test_session_logic_conn_except_notifier);
+ CU_add_test(test_session_logic_loop_suite,
+ "test_session_logic_timer_expire_handler",
+ test_session_logic_timer_expire_handler);
+
+ CU_pSuite test_session_logic_states_suite =
+ CU_add_suite_with_setup_and_teardown(
+ "PCEP Session Logic States Test Suite",
+ pcep_session_logic_states_test_suite_setup, // suite
+ // setup and
+ // cleanup
+ // function
+ // pointers
+ pcep_session_logic_states_test_suite_teardown,
+ pcep_session_logic_states_test_setup, // test case setup
+ // function
+ // pointer
+ pcep_session_logic_states_test_teardown); // test case
+ // teardown
+ // function
+ // pointer
+
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_timer_event_dead_timer",
+ test_handle_timer_event_dead_timer);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_timer_event_keep_alive",
+ test_handle_timer_event_keep_alive);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_timer_event_open_keep_wait",
+ test_handle_timer_event_open_keep_wait);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_null_params",
+ test_handle_socket_comm_event_null_params);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_close",
+ test_handle_socket_comm_event_close);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_open",
+ test_handle_socket_comm_event_open);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_open_error",
+ test_handle_socket_comm_event_open_error);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_keep_alive",
+ test_handle_socket_comm_event_keep_alive);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_pcrep",
+ test_handle_socket_comm_event_pcrep);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_pcreq",
+ test_handle_socket_comm_event_pcreq);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_report",
+ test_handle_socket_comm_event_report);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_update",
+ test_handle_socket_comm_event_update);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_initiate",
+ test_handle_socket_comm_event_initiate);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_notify",
+ test_handle_socket_comm_event_notify);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_error",
+ test_handle_socket_comm_event_error);
+ CU_add_test(test_session_logic_states_suite,
+ "test_handle_socket_comm_event_unknown_msg",
+ test_handle_socket_comm_event_unknown_msg);
+ CU_add_test(test_session_logic_states_suite, "test_connection_failure",
+ test_connection_failure);
+
+ /*
+ * Run the tests and cleanup.
+ */
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ CU_FailureRecord *failure_record = CU_get_failure_list();
+ if (failure_record != NULL) {
+ printf("\nFailed tests:\n\t [Suite] [Test] [File:line-number]\n");
+ do {
+ printf("\t [%s] [%s] [%s:%d]\n",
+ failure_record->pSuite->pName,
+ failure_record->pTest->pName,
+ failure_record->strFileName,
+ failure_record->uiLineNumber);
+ failure_record = failure_record->pNext;
+
+ } while (failure_record != NULL);
+ }
+
+ CU_pRunSummary run_summary = CU_get_run_summary();
+ int result = run_summary->nTestsFailed;
+ CU_cleanup_registry();
+
+ return result;
+}
diff --git a/pceplib/test/pcep_session_logic_tests_valgrind.sh b/pceplib/test/pcep_session_logic_tests_valgrind.sh
new file mode 100755
index 0000000..435bb3d
--- /dev/null
+++ b/pceplib/test/pcep_session_logic_tests_valgrind.sh
@@ -0,0 +1,2 @@
+source pceplib/test/pcep_tests_valgrind.sh
+valgrind_test pceplib/test/pcep_session_logic_tests
diff --git a/pceplib/test/pcep_socket_comm_loop_test.c b/pceplib/test/pcep_socket_comm_loop_test.c
new file mode 100644
index 0000000..748cf43
--- /dev/null
+++ b/pceplib/test/pcep_socket_comm_loop_test.c
@@ -0,0 +1,198 @@
+/*
+ * 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 <pthread.h>
+#include <stdlib.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_socket_comm_internals.h"
+#include "pcep_socket_comm_loop.h"
+#include "pcep_socket_comm_loop_test.h"
+#include "pcep_socket_comm.h"
+#include "pcep_utils_memory.h"
+
+void test_loop_conn_except_notifier(void *session_data, int socket_fd);
+
+/*
+ * Functions to be tested, implemented in pcep_socket_comm_loop.c
+ */
+
+typedef struct ready_to_read_handler_info_ {
+ bool handler_called;
+ bool except_handler_called;
+ void *data;
+ int socket_fd;
+ int bytes_read;
+
+} ready_to_read_handler_info;
+
+static ready_to_read_handler_info read_handler_info;
+static pcep_socket_comm_session *test_comm_session;
+static pcep_socket_comm_handle *test_socket_comm_handle = NULL;
+
+static int test_loop_message_ready_to_read_handler(void *session_data,
+ int socket_fd)
+{
+ read_handler_info.handler_called = true;
+ read_handler_info.data = session_data;
+ read_handler_info.socket_fd = socket_fd;
+
+ return read_handler_info.bytes_read;
+}
+
+
+void test_loop_conn_except_notifier(void *session_data, int socket_fd)
+{
+ (void)session_data;
+ (void)socket_fd;
+ read_handler_info.except_handler_called = true;
+}
+
+
+/*
+ * Test case setup and teardown called before AND after each test.
+ */
+void pcep_socket_comm_loop_test_setup()
+{
+ test_socket_comm_handle =
+ pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_socket_comm_handle));
+ memset(test_socket_comm_handle, 0, sizeof(pcep_socket_comm_handle));
+ test_socket_comm_handle->active = false;
+ test_socket_comm_handle->read_list =
+ ordered_list_initialize(socket_fd_node_compare);
+ test_socket_comm_handle->write_list =
+ ordered_list_initialize(socket_fd_node_compare);
+ test_socket_comm_handle->session_list =
+ ordered_list_initialize(pointer_compare_function);
+ pthread_mutex_init(&test_socket_comm_handle->socket_comm_mutex, NULL);
+ test_socket_comm_handle->num_active_sessions = 0;
+
+ test_comm_session =
+ pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_socket_comm_session));
+ memset(test_comm_session, 0, sizeof(pcep_socket_comm_session));
+ test_comm_session->message_ready_to_read_handler =
+ test_loop_message_ready_to_read_handler;
+ ordered_list_add_node(test_socket_comm_handle->session_list,
+ test_comm_session);
+
+ read_handler_info.handler_called = false;
+ read_handler_info.except_handler_called = false;
+ read_handler_info.data = NULL;
+ read_handler_info.socket_fd = -1;
+ read_handler_info.bytes_read = 0;
+}
+
+
+void pcep_socket_comm_loop_test_teardown()
+{
+ pthread_mutex_destroy(&test_socket_comm_handle->socket_comm_mutex);
+ ordered_list_destroy(test_socket_comm_handle->read_list);
+ ordered_list_destroy(test_socket_comm_handle->write_list);
+ ordered_list_destroy(test_socket_comm_handle->session_list);
+ pceplib_free(PCEPLIB_INFRA, test_socket_comm_handle);
+ test_socket_comm_handle = NULL;
+
+ if (test_comm_session != NULL) {
+ pceplib_free(PCEPLIB_INFRA, test_comm_session);
+ test_comm_session = NULL;
+ }
+}
+
+
+/*
+ * Test cases
+ */
+
+void test_socket_comm_loop_null_handle()
+{
+ /* Verify that socket_comm_loop() correctly handles a NULL
+ * timers_context */
+ socket_comm_loop(NULL);
+}
+
+
+void test_socket_comm_loop_not_active()
+{
+ /* Verify that event_loop() correctly handles an inactive flag */
+ pcep_socket_comm_handle handle;
+ handle.active = false;
+ socket_comm_loop(&handle);
+}
+
+
+void test_handle_reads_no_read()
+{
+ CU_ASSERT_PTR_NULL(test_socket_comm_handle->read_list->head);
+
+ handle_reads(test_socket_comm_handle);
+
+ CU_ASSERT_FALSE(read_handler_info.handler_called);
+ CU_ASSERT_FALSE(read_handler_info.except_handler_called);
+ CU_ASSERT_PTR_NULL(test_socket_comm_handle->read_list->head);
+}
+
+
+void test_handle_reads_read_message()
+{
+ /* Setup the comm session so that it can read.
+ * It should read 100 bytes, which simulates a successful read */
+ test_comm_session->socket_fd = 10;
+ read_handler_info.bytes_read = 100;
+ FD_SET(test_comm_session->socket_fd,
+ &test_socket_comm_handle->read_master_set);
+ ordered_list_add_node(test_socket_comm_handle->read_list,
+ test_comm_session);
+
+ handle_reads(test_socket_comm_handle);
+
+ CU_ASSERT_TRUE(read_handler_info.handler_called);
+ CU_ASSERT_FALSE(read_handler_info.except_handler_called);
+ CU_ASSERT_EQUAL(test_comm_session->received_bytes,
+ read_handler_info.bytes_read);
+}
+
+
+void test_handle_reads_read_message_close()
+{
+ /* Setup the comm session so that it can read.
+ * It should read 0 bytes, which simulates that the socket closed */
+ test_comm_session->socket_fd = 11;
+ read_handler_info.bytes_read = 0;
+ FD_SET(test_comm_session->socket_fd,
+ &test_socket_comm_handle->read_master_set);
+ ordered_list_add_node(test_socket_comm_handle->read_list,
+ test_comm_session);
+
+ handle_reads(test_socket_comm_handle);
+
+ CU_ASSERT_TRUE(read_handler_info.handler_called);
+ CU_ASSERT_FALSE(read_handler_info.except_handler_called);
+ CU_ASSERT_EQUAL(test_comm_session->received_bytes,
+ read_handler_info.bytes_read);
+ CU_ASSERT_PTR_NULL(test_socket_comm_handle->read_list->head);
+}
diff --git a/pceplib/test/pcep_socket_comm_loop_test.h b/pceplib/test/pcep_socket_comm_loop_test.h
new file mode 100644
index 0000000..d2e3f21
--- /dev/null
+++ b/pceplib/test/pcep_socket_comm_loop_test.h
@@ -0,0 +1,38 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_SOCKET_COMM_LOOP_TEST_H_
+#define PCEP_SOCKET_COMM_LOOP_TEST_H_
+
+void pcep_socket_comm_loop_test_setup(void);
+void pcep_socket_comm_loop_test_teardown(void);
+void test_socket_comm_loop_null_handle(void);
+void test_socket_comm_loop_not_active(void);
+void test_handle_reads_no_read(void);
+void test_handle_reads_read_message(void);
+void test_handle_reads_read_message_close(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_socket_comm_test.c b/pceplib/test/pcep_socket_comm_test.c
new file mode 100644
index 0000000..116531f
--- /dev/null
+++ b/pceplib/test/pcep_socket_comm_test.c
@@ -0,0 +1,325 @@
+/*
+ * 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 <netinet/in.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_socket_comm.h"
+#include "pcep_socket_comm_internals.h"
+#include "pcep_socket_comm_test.h"
+
+extern pcep_socket_comm_handle *socket_comm_handle_;
+
+static pcep_socket_comm_session *test_session = NULL;
+static struct in_addr test_host_ip;
+static struct in_addr test_src_ip;
+static struct in6_addr test_host_ipv6;
+static struct in6_addr test_src_ipv6;
+static short test_port = 4789;
+static short test_src_port = 4999;
+static uint32_t connect_timeout_millis = 500;
+
+/*
+ * Unit Test Basic pcep_socket_comm API usage.
+ * Testing sending messages, etc via sockets should be done
+ * with integration tests, not unit tests.
+ */
+
+/*
+ * Different socket_comm handler test implementations
+ */
+static void test_message_received_handler(void *session_data,
+ const char *message_data,
+ unsigned int message_length)
+{
+ (void)session_data;
+ (void)message_data;
+ (void)message_length;
+}
+
+static int test_message_ready_to_read_handler(void *session_data, int socket_fd)
+{
+ (void)session_data;
+ (void)socket_fd;
+ return 1;
+}
+
+static void test_message_sent_handler(void *session_data, int socket_fd)
+{
+ (void)session_data;
+ (void)socket_fd;
+ return;
+}
+
+static void test_connection_except_notifier(void *session_data, int socket_fd)
+{
+ (void)session_data;
+ (void)socket_fd;
+}
+
+
+/*
+ * Test case setup and teardown called before AND after each test.
+ */
+void pcep_socket_comm_test_setup()
+{
+ inet_pton(AF_INET, "127.0.0.1", &(test_host_ip));
+ inet_pton(AF_INET, "127.0.0.1", &(test_src_ip));
+ inet_pton(AF_INET6, "::1", &(test_host_ipv6));
+ inet_pton(AF_INET6, "::1", &(test_src_ipv6));
+}
+
+void pcep_socket_comm_test_teardown()
+{
+ socket_comm_session_teardown(test_session);
+ test_session = NULL;
+}
+
+
+/*
+ * Test cases
+ */
+
+void test_pcep_socket_comm_initialize()
+{
+ test_session = socket_comm_session_initialize(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_host_ip, test_port,
+ connect_timeout_millis, NULL, false, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_FALSE(test_session->is_ipv6);
+}
+
+
+void test_pcep_socket_comm_initialize_ipv6()
+{
+ test_session = socket_comm_session_initialize_ipv6(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_host_ipv6, test_port,
+ connect_timeout_millis, NULL, false, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_TRUE(test_session->is_ipv6);
+}
+
+
+void test_pcep_socket_comm_initialize_with_src()
+{
+ /* Test that INADDR_ANY will be used when src_ip is NULL */
+ test_session = socket_comm_session_initialize_with_src(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, NULL, 0, &test_host_ip,
+ test_port, connect_timeout_millis, NULL, false, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(
+ test_session->src_sock_addr.src_sock_addr_ipv4.sin_addr.s_addr,
+ INADDR_ANY);
+ CU_ASSERT_FALSE(test_session->is_ipv6);
+
+ socket_comm_session_teardown(test_session);
+ test_session = socket_comm_session_initialize_with_src(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_src_ip, test_src_port,
+ &test_host_ip, test_port, connect_timeout_millis, NULL, false,
+ NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(
+ test_session->src_sock_addr.src_sock_addr_ipv4.sin_addr.s_addr,
+ test_src_ip.s_addr);
+ CU_ASSERT_EQUAL(test_session->src_sock_addr.src_sock_addr_ipv4.sin_port,
+ ntohs(test_src_port));
+ CU_ASSERT_FALSE(test_session->is_ipv6);
+}
+
+
+void test_pcep_socket_comm_initialize_with_src_ipv6()
+{
+ /* Test that INADDR6_ANY will be used when src_ip is NULL */
+ test_session = socket_comm_session_initialize_with_src_ipv6(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, NULL, 0, &test_host_ipv6,
+ test_port, connect_timeout_millis, NULL, false, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(memcmp(&test_session->src_sock_addr.src_sock_addr_ipv6
+ .sin6_addr,
+ &in6addr_any, sizeof(struct in6_addr)),
+ 0);
+ CU_ASSERT_TRUE(test_session->is_ipv6);
+
+ socket_comm_session_teardown(test_session);
+ test_session = socket_comm_session_initialize_with_src_ipv6(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_src_ipv6, test_src_port,
+ &test_host_ipv6, test_port, connect_timeout_millis, NULL, false,
+ NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(memcmp(&test_session->src_sock_addr.src_sock_addr_ipv6
+ .sin6_addr,
+ &test_src_ipv6, sizeof(struct in6_addr)),
+ 0);
+ CU_ASSERT_EQUAL(
+ test_session->src_sock_addr.src_sock_addr_ipv6.sin6_port,
+ ntohs(test_src_port));
+ CU_ASSERT_TRUE(test_session->is_ipv6);
+}
+
+
+void test_pcep_socket_comm_initialize_tcpmd5()
+{
+ char tcp_md5_str[] = "hello";
+ int tcp_md5_strlen = strlen(tcp_md5_str);
+
+ test_session = socket_comm_session_initialize(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_host_ip, test_port, 1,
+ tcp_md5_str, true, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(0, strncmp(tcp_md5_str,
+ test_session->tcp_authentication_str,
+ tcp_md5_strlen));
+ CU_ASSERT_TRUE(test_session->is_tcp_auth_md5);
+ CU_ASSERT_FALSE(socket_comm_session_connect_tcp(test_session));
+ /* This call does not work, it returns errno=92, Protocol not available
+ getsockopt(test_session->socket_fd, SOL_SOCKET, TCP_MD5SIG, &sig,
+ &siglen);*/
+
+ socket_comm_session_teardown(test_session);
+ test_session = socket_comm_session_initialize(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_host_ip, test_port, 1,
+ tcp_md5_str, false, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(0, strncmp(tcp_md5_str,
+ test_session->tcp_authentication_str,
+ tcp_md5_strlen));
+ CU_ASSERT_FALSE(test_session->is_tcp_auth_md5);
+ CU_ASSERT_FALSE(socket_comm_session_connect_tcp(test_session));
+}
+
+
+void test_pcep_socket_comm_initialize_ipv6_tcpmd5()
+{
+ char tcp_md5_str[] = "hello";
+ int tcp_md5_strlen = strlen(tcp_md5_str);
+
+ test_session = socket_comm_session_initialize_ipv6(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_host_ipv6, test_port, 1,
+ tcp_md5_str, true, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(0, strncmp(tcp_md5_str,
+ test_session->tcp_authentication_str,
+ tcp_md5_strlen));
+ CU_ASSERT_TRUE(test_session->is_tcp_auth_md5);
+ CU_ASSERT_FALSE(socket_comm_session_connect_tcp(test_session));
+ /* This call does not work, it returns errno=92, Protocol not available
+ getsockopt(test_session->socket_fd, SOL_SOCKET, TCP_MD5SIG, &sig,
+ &siglen);*/
+
+ socket_comm_session_teardown(test_session);
+ test_session = socket_comm_session_initialize_ipv6(
+ test_message_received_handler, NULL, NULL,
+ test_connection_except_notifier, &test_host_ipv6, test_port, 1,
+ tcp_md5_str, false, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_EQUAL(0, strncmp(tcp_md5_str,
+ test_session->tcp_authentication_str,
+ tcp_md5_strlen));
+ CU_ASSERT_FALSE(test_session->is_tcp_auth_md5);
+ CU_ASSERT_FALSE(socket_comm_session_connect_tcp(test_session));
+}
+
+
+void test_pcep_socket_comm_initialize_handlers()
+{
+ /* Verify incorrect handler usage is correctly handled */
+
+ /* Both receive handlers cannot be NULL */
+ test_session = socket_comm_session_initialize(
+ NULL, NULL, NULL, test_connection_except_notifier,
+ &test_host_ip, test_port, connect_timeout_millis, NULL, false,
+ NULL);
+ CU_ASSERT_PTR_NULL(test_session);
+
+ /* Both receive handlers cannot be set */
+ test_session = socket_comm_session_initialize(
+ test_message_received_handler,
+ test_message_ready_to_read_handler, test_message_sent_handler,
+ test_connection_except_notifier, &test_host_ip, test_port,
+ connect_timeout_millis, NULL, false, NULL);
+ CU_ASSERT_PTR_NULL(test_session);
+
+ /* Only one receive handler can be set */
+ test_session = socket_comm_session_initialize(
+ NULL, test_message_ready_to_read_handler,
+ test_message_sent_handler, test_connection_except_notifier,
+ &test_host_ip, test_port, connect_timeout_millis, NULL, false,
+ NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+}
+
+
+void test_pcep_socket_comm_session_not_initialized()
+{
+ CU_ASSERT_FALSE(socket_comm_session_connect_tcp(NULL));
+ CU_ASSERT_FALSE(socket_comm_session_close_tcp(NULL));
+ CU_ASSERT_FALSE(socket_comm_session_close_tcp_after_write(NULL));
+ socket_comm_session_send_message(NULL, NULL, 0, true);
+ CU_ASSERT_FALSE(socket_comm_session_teardown(NULL));
+}
+
+
+void test_pcep_socket_comm_session_destroy()
+{
+ test_session = socket_comm_session_initialize(
+ test_message_received_handler, NULL, test_message_sent_handler,
+ test_connection_except_notifier, &test_host_ip, test_port,
+ connect_timeout_millis, NULL, false, NULL);
+ CU_ASSERT_PTR_NOT_NULL(test_session);
+ assert(test_session != NULL);
+ CU_ASSERT_PTR_NOT_NULL(socket_comm_handle_);
+ assert(socket_comm_handle_ != NULL);
+ CU_ASSERT_EQUAL(socket_comm_handle_->num_active_sessions, 1);
+
+ CU_ASSERT_TRUE(socket_comm_session_teardown(test_session));
+ test_session = NULL;
+ CU_ASSERT_PTR_NOT_NULL(socket_comm_handle_);
+
+ CU_ASSERT_TRUE(destroy_socket_comm_loop());
+ CU_ASSERT_PTR_NULL(socket_comm_handle_);
+}
diff --git a/pceplib/test/pcep_socket_comm_test.h b/pceplib/test/pcep_socket_comm_test.h
new file mode 100644
index 0000000..f857af0
--- /dev/null
+++ b/pceplib/test/pcep_socket_comm_test.h
@@ -0,0 +1,42 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_SOCKET_COMM_TEST_H_
+#define PCEP_SOCKET_COMM_TEST_H_
+
+void pcep_socket_comm_test_teardown(void);
+void pcep_socket_comm_test_setup(void);
+void test_pcep_socket_comm_initialize(void);
+void test_pcep_socket_comm_initialize_ipv6(void);
+void test_pcep_socket_comm_initialize_with_src(void);
+void test_pcep_socket_comm_initialize_with_src_ipv6(void);
+void test_pcep_socket_comm_initialize_tcpmd5(void);
+void test_pcep_socket_comm_initialize_ipv6_tcpmd5(void);
+void test_pcep_socket_comm_initialize_handlers(void);
+void test_pcep_socket_comm_session_not_initialized(void);
+void test_pcep_socket_comm_session_destroy(void);
+
+#endif
diff --git a/pceplib/test/pcep_socket_comm_tests.c b/pceplib/test/pcep_socket_comm_tests.c
new file mode 100644
index 0000000..6a5839d
--- /dev/null
+++ b/pceplib/test/pcep_socket_comm_tests.c
@@ -0,0 +1,132 @@
+/*
+ * 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 <CUnit/Basic.h>
+#include <CUnit/CUnit.h>
+#include <CUnit/TestDB.h>
+
+#include "pcep_socket_comm_loop_test.h"
+#include "pcep_socket_comm_test.h"
+
+
+int main(int argc, char **argv)
+{
+ /* Unused parameters cause compilation warnings */
+ (void)argc;
+ (void)argv;
+
+ CU_initialize_registry();
+
+ /*
+ * Tests defined in pcep_socket_comm_test.c
+ */
+ CU_pSuite test_socket_comm_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP Socket Comm Test Suite", NULL,
+ NULL, // suite setup and cleanup function pointers
+ pcep_socket_comm_test_setup, // test case setup function pointer
+ pcep_socket_comm_test_teardown); // test case teardown function
+ // pointer
+
+ CU_add_test(test_socket_comm_suite, "test_pcep_socket_comm_initialize",
+ test_pcep_socket_comm_initialize);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_initialize_ipv6",
+ test_pcep_socket_comm_initialize_ipv6);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_initialize_with_src",
+ test_pcep_socket_comm_initialize_with_src);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_initialize_with_src_ipv6",
+ test_pcep_socket_comm_initialize_with_src_ipv6);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_initialize_tcpmd5",
+ test_pcep_socket_comm_initialize_tcpmd5);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_initialize_ipv6_tcpmd5",
+ test_pcep_socket_comm_initialize_ipv6_tcpmd5);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_initialize_handlers",
+ test_pcep_socket_comm_initialize_handlers);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_session_not_initialized",
+ test_pcep_socket_comm_session_not_initialized);
+ CU_add_test(test_socket_comm_suite,
+ "test_pcep_socket_comm_session_destroy",
+ test_pcep_socket_comm_session_destroy);
+
+ /*
+ * Tests defined in pcep_socket_comm_loop_test.c
+ */
+ CU_pSuite test_socket_comm_loop_suite =
+ CU_add_suite_with_setup_and_teardown(
+ "PCEP Socket Comm Loop Test Suite", NULL, NULL,
+ pcep_socket_comm_loop_test_setup, // suite setup
+ // function pointer
+ pcep_socket_comm_loop_test_teardown); // suite cleanup
+ // function
+ // pointer
+
+ CU_add_test(test_socket_comm_loop_suite,
+ "test_socket_comm_loop_null_handle",
+ test_socket_comm_loop_null_handle);
+ CU_add_test(test_socket_comm_loop_suite,
+ "test_socket_comm_loop_not_active",
+ test_socket_comm_loop_not_active);
+ CU_add_test(test_socket_comm_loop_suite, "test_handle_reads_no_read",
+ test_handle_reads_no_read);
+ CU_add_test(test_socket_comm_loop_suite,
+ "test_handle_reads_read_message",
+ test_handle_reads_read_message);
+ CU_add_test(test_socket_comm_loop_suite,
+ "test_handle_reads_read_message_close",
+ test_handle_reads_read_message_close);
+
+ /*
+ * Run the tests and cleanup.
+ */
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ CU_FailureRecord *failure_record = CU_get_failure_list();
+ if (failure_record != NULL) {
+ printf("\nFailed tests:\n\t [Suite] [Test] [File:line-number]\n");
+ do {
+ printf("\t [%s] [%s] [%s:%d]\n",
+ failure_record->pSuite->pName,
+ failure_record->pTest->pName,
+ failure_record->strFileName,
+ failure_record->uiLineNumber);
+ failure_record = failure_record->pNext;
+
+ } while (failure_record != NULL);
+ }
+
+ CU_pRunSummary run_summary = CU_get_run_summary();
+ int result = run_summary->nTestsFailed;
+ CU_cleanup_registry();
+
+ return result;
+}
diff --git a/pceplib/test/pcep_socket_comm_tests_valgrind.sh b/pceplib/test/pcep_socket_comm_tests_valgrind.sh
new file mode 100755
index 0000000..d9e95e4
--- /dev/null
+++ b/pceplib/test/pcep_socket_comm_tests_valgrind.sh
@@ -0,0 +1,2 @@
+source pceplib/test/pcep_tests_valgrind.sh
+valgrind_test pceplib/test/pcep_socket_comm_tests
diff --git a/pceplib/test/pcep_tests_valgrind.sh b/pceplib/test/pcep_tests_valgrind.sh
new file mode 100755
index 0000000..ca4772c
--- /dev/null
+++ b/pceplib/test/pcep_tests_valgrind.sh
@@ -0,0 +1,15 @@
+#
+# Common function definition for PCEPlib valgrind tests
+#
+
+function valgrind_test()
+{
+ local test_suite=$1
+ [[ -z ${test_suite} ]] && { echo "${FUNCNAME}(): test_suite not specified."; exit 1; }
+ [[ ! -x "${test_suite}" ]] && { echo "${test_suite} is not an executable file."; exit 1; }
+
+ G_SLICE=always-malloc
+ G_DEBUG=gc-friendly
+ VALGRIND="valgrind -v --tool=memcheck --leak-check=full --num-callers=40 --error-exitcode=1"
+ ${VALGRIND} --log-file=${test_suite}.val.log ./${test_suite} || ({ echo "Valgrind memory check error"; exit 1; })
+}
diff --git a/pceplib/test/pcep_timers_event_loop_test.c b/pceplib/test/pcep_timers_event_loop_test.c
new file mode 100644
index 0000000..79ed84b
--- /dev/null
+++ b/pceplib/test/pcep_timers_event_loop_test.c
@@ -0,0 +1,166 @@
+/*
+ * 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 <stdlib.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_timers.h"
+#include "pcep_utils_memory.h"
+#include "pcep_timers_event_loop.h"
+#include "pcep_timers_event_loop_test.h"
+
+
+typedef struct timer_expire_handler_info_ {
+ bool handler_called;
+ void *data;
+ int timerId;
+
+} timer_expire_handler_info;
+
+static pcep_timers_context *test_timers_context = NULL;
+static timer_expire_handler_info expire_handler_info;
+#define TEST_EVENT_LOOP_TIMER_ID 500
+
+
+/* Called when a timer expires */
+static void test_timer_expire_handler(void *data, int timerId)
+{
+ expire_handler_info.handler_called = true;
+ expire_handler_info.data = data;
+ expire_handler_info.timerId = timerId;
+}
+
+
+/* Test case setup called before each test.
+ * Declared in pcep_timers_tests.c */
+void pcep_timers_event_loop_test_setup()
+{
+ test_timers_context =
+ pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_timers_context));
+ memset(test_timers_context, 0, sizeof(pcep_timers_context));
+ if (pthread_mutex_init(&(test_timers_context->timer_list_lock), NULL)
+ != 0) {
+ fprintf(stderr,
+ "ERROR initializing timers, cannot initialize the mutex\n");
+ }
+ test_timers_context->active = false;
+ test_timers_context->expire_handler = test_timer_expire_handler;
+ test_timers_context->timer_list =
+ ordered_list_initialize(timer_list_node_timer_id_compare);
+
+ expire_handler_info.handler_called = false;
+ expire_handler_info.data = NULL;
+ expire_handler_info.timerId = -1;
+}
+
+
+/* Test case teardown called after each test.
+ * Declared in pcep_timers_tests.c */
+void pcep_timers_event_loop_test_teardown()
+{
+ pthread_mutex_unlock(&test_timers_context->timer_list_lock);
+ pthread_mutex_destroy(&(test_timers_context->timer_list_lock));
+ ordered_list_destroy(test_timers_context->timer_list);
+ pceplib_free(PCEPLIB_INFRA, test_timers_context);
+ test_timers_context = NULL;
+}
+
+
+/*
+ * Test functions
+ */
+
+void test_walk_and_process_timers_no_timers()
+{
+ CU_ASSERT_EQUAL(test_timers_context->timer_list->num_entries, 0);
+ CU_ASSERT_PTR_NULL(test_timers_context->timer_list->head);
+
+ walk_and_process_timers(test_timers_context);
+
+ CU_ASSERT_FALSE(expire_handler_info.handler_called);
+ CU_ASSERT_EQUAL(test_timers_context->timer_list->num_entries, 0);
+ CU_ASSERT_PTR_NULL(test_timers_context->timer_list->head);
+}
+
+
+void test_walk_and_process_timers_timer_not_expired()
+{
+ pcep_timer timer;
+ timer.data = &timer;
+ // Set the timer to expire 100 seconds from now
+ timer.expire_time = time(NULL) + 100;
+ timer.timer_id = TEST_EVENT_LOOP_TIMER_ID;
+ ordered_list_add_node(test_timers_context->timer_list, &timer);
+
+ walk_and_process_timers(test_timers_context);
+
+ /* The timer should still be in the list, since it hasnt expired yet */
+ CU_ASSERT_FALSE(expire_handler_info.handler_called);
+ CU_ASSERT_EQUAL(test_timers_context->timer_list->num_entries, 1);
+ CU_ASSERT_PTR_NOT_NULL(test_timers_context->timer_list->head);
+}
+
+
+void test_walk_and_process_timers_timer_expired()
+{
+ /* We need to alloc it, since it will be free'd in
+ * walk_and_process_timers */
+ pcep_timer *timer = pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_timer));
+ timer->data = timer;
+ // Set the timer to expire 10 seconds ago
+ timer->expire_time = time(NULL) - 10;
+ pthread_mutex_lock(&test_timers_context->timer_list_lock);
+ timer->timer_id = TEST_EVENT_LOOP_TIMER_ID;
+ pthread_mutex_unlock(&test_timers_context->timer_list_lock);
+ ordered_list_add_node(test_timers_context->timer_list, timer);
+
+ walk_and_process_timers(test_timers_context);
+
+ /* Since the timer expired, the expire_handler should have been called
+ * and the timer should have been removed from the timer list */
+ CU_ASSERT_TRUE(expire_handler_info.handler_called);
+ CU_ASSERT_PTR_EQUAL(expire_handler_info.data, timer);
+ CU_ASSERT_EQUAL(expire_handler_info.timerId, TEST_EVENT_LOOP_TIMER_ID);
+ CU_ASSERT_EQUAL(test_timers_context->timer_list->num_entries, 0);
+ CU_ASSERT_PTR_NULL(test_timers_context->timer_list->head);
+}
+
+void test_event_loop_null_handle()
+{
+ /* Verify that event_loop() correctly handles a NULL timers_context */
+ event_loop(NULL);
+}
+
+
+void test_event_loop_not_active()
+{
+ /* Verify that event_loop() correctly handles an inactive timers_context
+ * flag */
+ test_timers_context->active = false;
+ event_loop(test_timers_context);
+}
diff --git a/pceplib/test/pcep_timers_event_loop_test.h b/pceplib/test/pcep_timers_event_loop_test.h
new file mode 100644
index 0000000..19fd264
--- /dev/null
+++ b/pceplib/test/pcep_timers_event_loop_test.h
@@ -0,0 +1,38 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_TIMERS_EVENT_LOOP_TEST_H_
+#define PCEP_TIMERS_EVENT_LOOP_TEST_H_
+
+void pcep_timers_event_loop_test_setup(void);
+void pcep_timers_event_loop_test_teardown(void);
+void test_walk_and_process_timers_no_timers(void);
+void test_walk_and_process_timers_timer_not_expired(void);
+void test_walk_and_process_timers_timer_expired(void);
+void test_event_loop_null_handle(void);
+void test_event_loop_not_active(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_timers_test.c b/pceplib/test/pcep_timers_test.c
new file mode 100644
index 0000000..e5be90a
--- /dev/null
+++ b/pceplib/test/pcep_timers_test.c
@@ -0,0 +1,113 @@
+/*
+ * 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 <stdbool.h>
+#include <CUnit/CUnit.h>
+
+#include "pcep_timers.h"
+#include "pcep_timers_test.h"
+
+/* Test case teardown called after each test.
+ * Declared in pcep_timers_tests.c */
+void pcep_timers_test_teardown()
+{
+ teardown_timers();
+}
+
+static void test_timer_expire_handler(void *data, int timerId)
+{
+ (void)data;
+ (void)timerId;
+}
+
+
+void test_double_initialization(void)
+{
+ CU_ASSERT_EQUAL(initialize_timers(test_timer_expire_handler), true);
+ CU_ASSERT_EQUAL(initialize_timers(test_timer_expire_handler), false);
+}
+
+
+void test_initialization_null_callback(void)
+{
+ CU_ASSERT_EQUAL(initialize_timers(NULL), false);
+}
+
+
+void test_not_initialized(void)
+{
+ /* All of these should fail if initialize_timers() hasnt been called */
+ CU_ASSERT_EQUAL(create_timer(5, NULL), -1);
+ CU_ASSERT_EQUAL(cancel_timer(7), false);
+ CU_ASSERT_EQUAL(reset_timer(7), false);
+ CU_ASSERT_EQUAL(teardown_timers(), false);
+}
+
+
+void test_create_timer(void)
+{
+ CU_ASSERT_EQUAL(initialize_timers(test_timer_expire_handler), true);
+
+ int timer_id = create_timer(0, NULL);
+ CU_ASSERT_TRUE(timer_id > -1);
+}
+
+
+void test_cancel_timer(void)
+{
+ CU_ASSERT_EQUAL(initialize_timers(test_timer_expire_handler), true);
+
+ int timer_id = create_timer(10, NULL);
+ CU_ASSERT_TRUE(timer_id > -1);
+
+ CU_ASSERT_EQUAL(cancel_timer(timer_id), true);
+}
+
+
+void test_cancel_timer_invalid(void)
+{
+ CU_ASSERT_EQUAL(initialize_timers(test_timer_expire_handler), true);
+ CU_ASSERT_EQUAL(cancel_timer(1), false);
+}
+
+
+void test_reset_timer(void)
+{
+ CU_ASSERT_EQUAL(initialize_timers(test_timer_expire_handler), true);
+
+ int timer_id = create_timer(10, NULL);
+ CU_ASSERT_TRUE(timer_id > -1);
+
+ CU_ASSERT_EQUAL(reset_timer(timer_id), true);
+}
+
+
+void test_reset_timer_invalid(void)
+{
+ CU_ASSERT_EQUAL(initialize_timers(test_timer_expire_handler), true);
+ CU_ASSERT_EQUAL(reset_timer(1), false);
+}
diff --git a/pceplib/test/pcep_timers_test.h b/pceplib/test/pcep_timers_test.h
new file mode 100644
index 0000000..6ac9a90
--- /dev/null
+++ b/pceplib/test/pcep_timers_test.h
@@ -0,0 +1,40 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_TIMERS_TEST_H_
+#define PCEP_TIMERS_TEST_H_
+
+void pcep_timers_test_teardown(void);
+void test_double_initialization(void);
+void test_initialization_null_callback(void);
+void test_not_initialized(void);
+void test_create_timer(void);
+void test_cancel_timer(void);
+void test_cancel_timer_invalid(void);
+void test_reset_timer(void);
+void test_reset_timer_invalid(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_timers_tests.c b/pceplib/test/pcep_timers_tests.c
new file mode 100644
index 0000000..f3aa830
--- /dev/null
+++ b/pceplib/test/pcep_timers_tests.c
@@ -0,0 +1,117 @@
+/*
+ * 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 <CUnit/Basic.h>
+#include <CUnit/CUnit.h>
+#include <CUnit/TestDB.h>
+
+#include "pcep_timers_test.h"
+#include "pcep_timers_event_loop_test.h"
+
+
+int main(int argc, char **argv)
+{
+ /* Unused parameters cause compilation warnings */
+ (void)argc;
+ (void)argv;
+
+ CU_initialize_registry();
+
+ /*
+ * Tests defined in pcep_timers_test.c
+ */
+ CU_pSuite test_timers_suite = CU_add_suite_with_setup_and_teardown(
+ "PCEP Timers Test Suite", NULL,
+ NULL, // suite setup and cleanup function pointers
+ NULL, pcep_timers_test_teardown); // test case setup and
+ // teardown function pointers
+ CU_add_test(test_timers_suite, "test_double_initialization",
+ test_double_initialization);
+ CU_add_test(test_timers_suite, "test_initialization_null_callback",
+ test_initialization_null_callback);
+ CU_add_test(test_timers_suite, "test_not_initialized",
+ test_not_initialized);
+ CU_add_test(test_timers_suite, "test_create_timer", test_create_timer);
+ CU_add_test(test_timers_suite, "test_cancel_timer", test_cancel_timer);
+ CU_add_test(test_timers_suite, "test_cancel_timer_invalid",
+ test_cancel_timer_invalid);
+ CU_add_test(test_timers_suite, "test_reset_timer", test_reset_timer);
+ CU_add_test(test_timers_suite, "test_reset_timer_invalid",
+ test_reset_timer_invalid);
+
+ /*
+ * Tests defined in pcep_timers_event_loop_test.c
+ */
+ CU_pSuite test_timers_event_loop_suite =
+ CU_add_suite_with_setup_and_teardown(
+ "PCEP Timers Event Loop Test Suite", NULL,
+ NULL, // suite setup and cleanup function pointers
+ pcep_timers_event_loop_test_setup, // test case setup
+ // function pointer
+ pcep_timers_event_loop_test_teardown); // test case
+ // teardown
+ // function
+ // pointer
+ CU_add_test(test_timers_event_loop_suite,
+ "test_walk_and_process_timers_no_timers",
+ test_walk_and_process_timers_no_timers);
+ CU_add_test(test_timers_event_loop_suite,
+ "test_walk_and_process_timers_timer_not_expired",
+ test_walk_and_process_timers_timer_not_expired);
+ CU_add_test(test_timers_event_loop_suite,
+ "test_walk_and_process_timers_timer_expired",
+ test_walk_and_process_timers_timer_expired);
+ CU_add_test(test_timers_event_loop_suite, "test_event_loop_null_handle",
+ test_event_loop_null_handle);
+ CU_add_test(test_timers_event_loop_suite, "test_event_loop_not_active",
+ test_event_loop_not_active);
+
+ /*
+ * Run the tests and cleanup.
+ */
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ CU_FailureRecord *failure_record = CU_get_failure_list();
+ if (failure_record != NULL) {
+ printf("\nFailed tests:\n\t [Suite] [Test] [File:line-number]\n");
+ do {
+ printf("\t [%s] [%s] [%s:%d]\n",
+ failure_record->pSuite->pName,
+ failure_record->pTest->pName,
+ failure_record->strFileName,
+ failure_record->uiLineNumber);
+ failure_record = failure_record->pNext;
+
+ } while (failure_record != NULL);
+ }
+
+ CU_pRunSummary run_summary = CU_get_run_summary();
+ int result = run_summary->nTestsFailed;
+ CU_cleanup_registry();
+
+ return result;
+}
diff --git a/pceplib/test/pcep_timers_tests_valgrind.sh b/pceplib/test/pcep_timers_tests_valgrind.sh
new file mode 100755
index 0000000..f9bff3b
--- /dev/null
+++ b/pceplib/test/pcep_timers_tests_valgrind.sh
@@ -0,0 +1,2 @@
+source pceplib/test/pcep_tests_valgrind.sh
+valgrind_test pceplib/test/pcep_timers_tests
diff --git a/pceplib/test/pcep_utils_counters_test.c b/pceplib/test/pcep_utils_counters_test.c
new file mode 100644
index 0000000..b31715f
--- /dev/null
+++ b/pceplib/test/pcep_utils_counters_test.c
@@ -0,0 +1,261 @@
+/*
+ * 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 <stdlib.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_utils_counters.h"
+#include "pcep_utils_counters_test.h"
+
+
+void test_create_counters_group()
+{
+ const char group_name[] = "group";
+ uint16_t num_subgroups = 10;
+
+ struct counters_group *group =
+ create_counters_group(NULL, num_subgroups);
+ CU_ASSERT_PTR_NULL(group);
+
+ group = create_counters_group(group_name, MAX_COUNTER_GROUPS + 1);
+ CU_ASSERT_PTR_NULL(group);
+
+ group = create_counters_group(group_name, num_subgroups);
+ CU_ASSERT_PTR_NOT_NULL(group);
+ assert(group != NULL);
+
+ CU_ASSERT_EQUAL(group->num_subgroups, 0);
+ CU_ASSERT_EQUAL(group->max_subgroups, num_subgroups);
+ CU_ASSERT_EQUAL(strcmp(group->counters_group_name, group_name), 0);
+
+ delete_counters_group(group);
+}
+
+void test_create_counters_subgroup()
+{
+ const char subgroup_name[] = "subgroup";
+ uint16_t subgroup_id = 10;
+ uint16_t num_counters = 20;
+
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup(NULL, subgroup_id, num_counters);
+ CU_ASSERT_PTR_NULL(subgroup);
+
+ subgroup = create_counters_subgroup(
+ subgroup_name, MAX_COUNTER_GROUPS + 1, num_counters);
+ CU_ASSERT_PTR_NULL(subgroup);
+
+ subgroup = create_counters_subgroup(subgroup_name, subgroup_id,
+ MAX_COUNTERS + 1);
+ CU_ASSERT_PTR_NULL(subgroup);
+
+ subgroup = create_counters_subgroup(subgroup_name, subgroup_id,
+ num_counters);
+ CU_ASSERT_PTR_NOT_NULL(subgroup);
+ assert(subgroup != NULL);
+
+ CU_ASSERT_EQUAL(subgroup->subgroup_id, subgroup_id);
+ CU_ASSERT_EQUAL(subgroup->num_counters, 0);
+ CU_ASSERT_EQUAL(subgroup->max_counters, num_counters);
+ CU_ASSERT_EQUAL(strcmp(subgroup->counters_subgroup_name, subgroup_name),
+ 0);
+
+ delete_counters_subgroup(subgroup);
+}
+
+void test_add_counters_subgroup()
+{
+ struct counters_group *group = create_counters_group("group", 1);
+ struct counters_subgroup *subgroup1 =
+ create_counters_subgroup("subgroup", 0, 5);
+ struct counters_subgroup *subgroup2 =
+ create_counters_subgroup("subgroup", 1, 5);
+
+ CU_ASSERT_FALSE(add_counters_subgroup(NULL, NULL));
+ CU_ASSERT_FALSE(add_counters_subgroup(NULL, subgroup1));
+ CU_ASSERT_FALSE(add_counters_subgroup(group, NULL));
+
+ CU_ASSERT_EQUAL(group->num_subgroups, 0);
+ CU_ASSERT_TRUE(add_counters_subgroup(group, subgroup1));
+ CU_ASSERT_EQUAL(group->num_subgroups, 1);
+ /* Cant add more than num_subgroups to the group */
+ CU_ASSERT_FALSE(add_counters_subgroup(group, subgroup2));
+
+ CU_ASSERT_PTR_NOT_NULL(find_subgroup(group, 0));
+ CU_ASSERT_PTR_NULL(find_subgroup(group, 1));
+
+ delete_counters_group(group);
+ delete_counters_subgroup(subgroup2);
+}
+
+void test_create_subgroup_counter()
+{
+ uint16_t counter_id = 1;
+ char counter_name[] = "my counter";
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", 1, 2);
+
+ CU_ASSERT_FALSE(
+ create_subgroup_counter(NULL, counter_id, counter_name));
+ CU_ASSERT_FALSE(create_subgroup_counter(subgroup, counter_id + 1,
+ counter_name));
+ CU_ASSERT_FALSE(create_subgroup_counter(subgroup, counter_id, NULL));
+ CU_ASSERT_EQUAL(subgroup->num_counters, 0);
+ CU_ASSERT_TRUE(
+ create_subgroup_counter(subgroup, counter_id, counter_name));
+ CU_ASSERT_EQUAL(subgroup->num_counters, 1);
+
+ delete_counters_subgroup(subgroup);
+}
+
+void test_delete_counters_group()
+{
+ struct counters_group *group = create_counters_group("group", 1);
+
+ CU_ASSERT_FALSE(delete_counters_group(NULL));
+ CU_ASSERT_TRUE(delete_counters_group(group));
+}
+
+void test_delete_counters_subgroup()
+{
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", 1, 1);
+
+ CU_ASSERT_FALSE(delete_counters_subgroup(NULL));
+ CU_ASSERT_TRUE(delete_counters_subgroup(subgroup));
+}
+
+void test_reset_group_counters()
+{
+ uint16_t subgroup_id = 1;
+ uint16_t counter_id = 1;
+ struct counters_group *group = create_counters_group("group", 10);
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", subgroup_id, 10);
+ create_subgroup_counter(subgroup, counter_id, "counter");
+ add_counters_subgroup(group, subgroup);
+
+ struct counter *counter = subgroup->counters[counter_id];
+ counter->counter_value = 100;
+
+ CU_ASSERT_FALSE(reset_group_counters(NULL));
+ CU_ASSERT_TRUE(reset_group_counters(group));
+ CU_ASSERT_EQUAL(counter->counter_value, 0);
+
+ delete_counters_group(group);
+}
+
+void test_reset_subgroup_counters()
+{
+ uint16_t counter_id = 1;
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", 1, 10);
+ create_subgroup_counter(subgroup, counter_id, "counter");
+
+ struct counter *counter = subgroup->counters[counter_id];
+ counter->counter_value = 100;
+
+ CU_ASSERT_FALSE(reset_subgroup_counters(NULL));
+ CU_ASSERT_TRUE(reset_subgroup_counters(subgroup));
+ CU_ASSERT_EQUAL(counter->counter_value, 0);
+
+ delete_counters_subgroup(subgroup);
+}
+
+void test_increment_counter()
+{
+ uint16_t subgroup_id = 1;
+ uint16_t counter_id = 1;
+ struct counters_group *group = create_counters_group("group", 10);
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", subgroup_id, 10);
+ create_subgroup_counter(subgroup, counter_id, "counter");
+ add_counters_subgroup(group, subgroup);
+
+ struct counter *counter = subgroup->counters[counter_id];
+ counter->counter_value = 100;
+
+ CU_ASSERT_FALSE(increment_counter(NULL, subgroup_id, counter_id));
+ CU_ASSERT_FALSE(increment_counter(group, 100, counter_id));
+ CU_ASSERT_FALSE(increment_counter(group, subgroup_id, 123));
+ CU_ASSERT_TRUE(increment_counter(group, subgroup_id, counter_id));
+ CU_ASSERT_EQUAL(counter->counter_value, 101);
+ CU_ASSERT_EQUAL(subgroup_counters_total(subgroup), 101);
+
+ delete_counters_group(group);
+}
+
+void test_increment_subgroup_counter()
+{
+ int counter_id = 1;
+ uint32_t counter_value = 100;
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", 1, 10);
+ create_subgroup_counter(subgroup, counter_id, "counter");
+
+ struct counter *counter = subgroup->counters[counter_id];
+ counter->counter_value = counter_value;
+
+ CU_ASSERT_FALSE(increment_subgroup_counter(NULL, counter_id));
+ CU_ASSERT_FALSE(increment_subgroup_counter(subgroup, counter_id + 1));
+ CU_ASSERT_TRUE(increment_subgroup_counter(subgroup, counter_id));
+ CU_ASSERT_EQUAL(counter->counter_value, counter_value + 1);
+
+ delete_counters_subgroup(subgroup);
+}
+
+void test_dump_counters_group_to_log()
+{
+ uint16_t subgroup_id = 1;
+ uint16_t counter_id = 1;
+ struct counters_group *group = create_counters_group("group", 10);
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", subgroup_id, 10);
+ create_subgroup_counter(subgroup, counter_id, "counter");
+ add_counters_subgroup(group, subgroup);
+
+ CU_ASSERT_FALSE(dump_counters_group_to_log(NULL));
+ CU_ASSERT_TRUE(dump_counters_group_to_log(group));
+
+ delete_counters_group(group);
+}
+
+void test_dump_counters_subgroup_to_log()
+{
+ uint16_t subgroup_id = 1;
+ uint16_t counter_id = 1;
+ struct counters_subgroup *subgroup =
+ create_counters_subgroup("subgroup", subgroup_id, 10);
+ create_subgroup_counter(subgroup, counter_id, "counter");
+
+ CU_ASSERT_FALSE(dump_counters_subgroup_to_log(NULL));
+ CU_ASSERT_TRUE(dump_counters_subgroup_to_log(subgroup));
+
+ delete_counters_subgroup(subgroup);
+}
diff --git a/pceplib/test/pcep_utils_counters_test.h b/pceplib/test/pcep_utils_counters_test.h
new file mode 100644
index 0000000..07236dc
--- /dev/null
+++ b/pceplib/test/pcep_utils_counters_test.h
@@ -0,0 +1,43 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_UTILS_COUNTERS_TEST_H_
+#define PCEP_UTILS_COUNTERS_TEST_H_
+
+void test_create_counters_group(void);
+void test_create_counters_subgroup(void);
+void test_add_counters_subgroup(void);
+void test_create_subgroup_counter(void);
+void test_delete_counters_group(void);
+void test_delete_counters_subgroup(void);
+void test_reset_group_counters(void);
+void test_reset_subgroup_counters(void);
+void test_increment_counter(void);
+void test_increment_subgroup_counter(void);
+void test_dump_counters_group_to_log(void);
+void test_dump_counters_subgroup_to_log(void);
+
+#endif
diff --git a/pceplib/test/pcep_utils_double_linked_list_test.c b/pceplib/test/pcep_utils_double_linked_list_test.c
new file mode 100644
index 0000000..181cbec
--- /dev/null
+++ b/pceplib/test/pcep_utils_double_linked_list_test.c
@@ -0,0 +1,315 @@
+/*
+ * 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 <CUnit/CUnit.h>
+
+#include "pcep_utils_double_linked_list.h"
+#include "pcep_utils_double_linked_list_test.h"
+
+typedef struct dll_node_data_ {
+ int int_data;
+
+} dll_node_data;
+
+void test_empty_dl_list()
+{
+ double_linked_list *handle = dll_initialize();
+
+ CU_ASSERT_PTR_NULL(dll_delete_first_node(handle));
+ CU_ASSERT_PTR_NULL(dll_delete_last_node(handle));
+ CU_ASSERT_PTR_NULL(dll_delete_node(handle, NULL));
+
+ dll_destroy(handle);
+}
+
+void test_null_dl_list_handle()
+{
+ dll_destroy(NULL);
+ CU_ASSERT_PTR_NULL(dll_prepend(NULL, NULL));
+ CU_ASSERT_PTR_NULL(dll_append(NULL, NULL));
+ CU_ASSERT_PTR_NULL(dll_delete_first_node(NULL));
+ CU_ASSERT_PTR_NULL(dll_delete_last_node(NULL));
+ CU_ASSERT_PTR_NULL(dll_delete_node(NULL, NULL));
+}
+
+void test_dll_prepend_data()
+{
+ dll_node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ double_linked_list *handle = dll_initialize();
+
+ CU_ASSERT_PTR_NOT_NULL(dll_prepend(handle, &data3));
+ CU_ASSERT_PTR_NOT_NULL(dll_prepend(handle, &data2));
+ CU_ASSERT_PTR_NOT_NULL(dll_prepend(handle, &data1));
+
+ CU_ASSERT_EQUAL(handle->num_entries, 3);
+
+ double_linked_list_node *node = handle->head;
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data1);
+ CU_ASSERT_PTR_NULL(node->prev_node);
+ CU_ASSERT_PTR_NOT_NULL(node->next_node);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data2);
+ CU_ASSERT_PTR_NOT_NULL(node->prev_node);
+ CU_ASSERT_PTR_NOT_NULL(node->next_node);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data3);
+ CU_ASSERT_PTR_NOT_NULL(node->prev_node);
+ CU_ASSERT_PTR_NULL(node->next_node);
+ CU_ASSERT_PTR_EQUAL(handle->tail, node);
+
+ dll_destroy(handle);
+}
+
+
+void test_dll_append_data()
+{
+ dll_node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ double_linked_list *handle = dll_initialize();
+
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data1));
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data2));
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data3));
+
+ CU_ASSERT_EQUAL(handle->num_entries, 3);
+
+ double_linked_list_node *node = handle->head;
+ CU_ASSERT_PTR_EQUAL(node->data, &data1);
+ CU_ASSERT_PTR_NULL(node->prev_node);
+ CU_ASSERT_PTR_NOT_NULL(node->next_node);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data2);
+ CU_ASSERT_PTR_NOT_NULL(node->prev_node);
+ CU_ASSERT_PTR_NOT_NULL(node->next_node);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data3);
+ CU_ASSERT_PTR_NOT_NULL(node->prev_node);
+ CU_ASSERT_PTR_NULL(node->next_node);
+ CU_ASSERT_PTR_EQUAL(handle->tail, node);
+
+ dll_destroy(handle);
+}
+
+
+void test_dll_delete_first_node()
+{
+ dll_node_data data1, data2;
+ data1.int_data = 1;
+ data2.int_data = 2;
+
+ double_linked_list *handle = dll_initialize();
+
+ /* Test deleting with just 1 node in the list */
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data1));
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+
+ void *deleted_data = dll_delete_first_node(handle);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data1, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+ CU_ASSERT_PTR_NULL(handle->head);
+ CU_ASSERT_PTR_NULL(handle->tail);
+
+ /* Test deleting with 2 nodes in the list */
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data1));
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data2));
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ deleted_data = dll_delete_first_node(handle);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data1, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+ CU_ASSERT_PTR_EQUAL(handle->head->data, &data2);
+ CU_ASSERT_PTR_EQUAL(handle->head, handle->tail);
+ CU_ASSERT_PTR_NULL(handle->head->prev_node);
+ CU_ASSERT_PTR_NULL(handle->head->next_node);
+
+ dll_destroy(handle);
+}
+
+
+void test_dll_delete_last_node()
+{
+ dll_node_data data1, data2;
+ data1.int_data = 1;
+ data2.int_data = 2;
+
+ double_linked_list *handle = dll_initialize();
+
+ /* Test deleting with just 1 node in the list */
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data1));
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+
+ void *deleted_data = dll_delete_last_node(handle);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data1, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+ CU_ASSERT_PTR_NULL(handle->head);
+ CU_ASSERT_PTR_NULL(handle->tail);
+
+ /* Test deleting with 2 nodes in the list */
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data1));
+ CU_ASSERT_PTR_NOT_NULL(dll_append(handle, &data2));
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ deleted_data = dll_delete_last_node(handle);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data2, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+ CU_ASSERT_PTR_EQUAL(handle->head->data, &data1);
+ CU_ASSERT_PTR_EQUAL(handle->head, handle->tail);
+ CU_ASSERT_PTR_NULL(handle->head->prev_node);
+ CU_ASSERT_PTR_NULL(handle->head->next_node);
+
+ dll_destroy(handle);
+}
+
+
+void test_dll_delete_node()
+{
+ dll_node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+ double_linked_list_node *node1, *node2, *node3;
+ double_linked_list *handle;
+
+ /* Test deleting with just 1 node in the list */
+ handle = dll_initialize();
+ node1 = dll_append(handle, &data1);
+ CU_ASSERT_PTR_NOT_NULL(node1);
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+
+ void *deleted_data = dll_delete_node(handle, node1);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data1, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+ CU_ASSERT_PTR_NULL(handle->head);
+ CU_ASSERT_PTR_NULL(handle->tail);
+
+ /*
+ * Test deleting the head with 2 nodes in the list
+ */
+ node1 = dll_append(handle, &data1);
+ node2 = dll_append(handle, &data2);
+ CU_ASSERT_PTR_NOT_NULL(node1);
+ CU_ASSERT_PTR_NOT_NULL(node2);
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ /* Delete the head entry */
+ deleted_data = dll_delete_node(handle, node1);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data1, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+ CU_ASSERT_PTR_EQUAL(handle->head->data, &data2);
+ CU_ASSERT_PTR_EQUAL(handle->head, handle->tail);
+ CU_ASSERT_PTR_NULL(handle->head->prev_node);
+ CU_ASSERT_PTR_NULL(handle->head->next_node);
+ dll_destroy(handle);
+
+ /*
+ * Test deleting the tail with 2 nodes in the list
+ */
+ handle = dll_initialize();
+ node1 = dll_append(handle, &data1);
+ node2 = dll_append(handle, &data2);
+ CU_ASSERT_PTR_NOT_NULL(node1);
+ CU_ASSERT_PTR_NOT_NULL(node2);
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ /* Delete the tail entry */
+ deleted_data = dll_delete_node(handle, node2);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data2, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+ CU_ASSERT_PTR_EQUAL(handle->head->data, &data1);
+ CU_ASSERT_PTR_EQUAL(handle->head, handle->tail);
+ CU_ASSERT_PTR_NULL(handle->head->prev_node);
+ CU_ASSERT_PTR_NULL(handle->head->next_node);
+ dll_destroy(handle);
+
+ /*
+ * Test deleting in the middle with 3 nodes in the list
+ */
+ handle = dll_initialize();
+ node1 = dll_append(handle, &data1);
+ node2 = dll_append(handle, &data2);
+ node3 = dll_append(handle, &data3);
+ CU_ASSERT_PTR_NOT_NULL(node1);
+ assert(node1 != NULL);
+ CU_ASSERT_PTR_NOT_NULL(node2);
+ assert(node2 != NULL);
+ CU_ASSERT_PTR_NOT_NULL(node3);
+ assert(node3 != NULL);
+ CU_ASSERT_EQUAL(handle->num_entries, 3);
+
+ /* Delete the middle entry */
+ deleted_data = dll_delete_node(handle, node2);
+ CU_ASSERT_PTR_NOT_NULL(deleted_data);
+ CU_ASSERT_PTR_EQUAL(&data2, deleted_data);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+ CU_ASSERT_PTR_EQUAL(handle->head, node1);
+ CU_ASSERT_PTR_EQUAL(handle->tail, node3);
+ CU_ASSERT_PTR_EQUAL(node1->data, &data1);
+ CU_ASSERT_PTR_EQUAL(node3->data, &data3);
+ CU_ASSERT_PTR_EQUAL(node1->next_node, node3);
+ CU_ASSERT_PTR_EQUAL(node3->prev_node, node1);
+ CU_ASSERT_PTR_NULL(node1->prev_node);
+ CU_ASSERT_PTR_NULL(node3->next_node);
+
+ dll_destroy(handle);
+}
diff --git a/pceplib/test/pcep_utils_double_linked_list_test.h b/pceplib/test/pcep_utils_double_linked_list_test.h
new file mode 100644
index 0000000..ddb6467
--- /dev/null
+++ b/pceplib/test/pcep_utils_double_linked_list_test.h
@@ -0,0 +1,38 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_UTILS_DOUBLE_LINKED_LIST_TEST_H_
+#define PCEP_UTILS_DOUBLE_LINKED_LIST_TEST_H_
+
+void test_empty_dl_list(void);
+void test_null_dl_list_handle(void);
+void test_dll_prepend_data(void);
+void test_dll_append_data(void);
+void test_dll_delete_first_node(void);
+void test_dll_delete_last_node(void);
+void test_dll_delete_node(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_utils_memory_test.c b/pceplib/test/pcep_utils_memory_test.c
new file mode 100644
index 0000000..0958626
--- /dev/null
+++ b/pceplib/test/pcep_utils_memory_test.c
@@ -0,0 +1,245 @@
+/*
+ * 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 <stdlib.h>
+#include <stdint.h>
+
+#include <CUnit/CUnit.h>
+
+#include "pcep_utils_memory.h"
+#include "pcep_utils_memory_test.h"
+
+void *test_pceplib_malloc(void *mem_type, size_t size);
+void *test_pceplib_calloc(void *mem_type, size_t size);
+void *test_pceplib_realloc(void *mem_type, void *ptr, size_t size);
+void *test_pceplib_strdup(void *mem_type, const char *str);
+void test_pceplib_free(void *mem_type, void *ptr);
+void verify_memory_type(struct pceplib_memory_type *mt, uint32_t num_alloc,
+ uint32_t alloc_bytes, uint32_t num_free,
+ uint32_t free_bytes);
+void verify_ext_memory_type(void *mt, int num_malloc_calls,
+ int num_calloc_calls, int num_realloc_calls,
+ int num_strdup_calls, int num_free_calls);
+
+struct test_memory_type {
+ int num_malloc_calls;
+ int num_calloc_calls;
+ int num_realloc_calls;
+ int num_strdup_calls;
+ int num_free_calls;
+};
+
+void *test_pceplib_malloc(void *mem_type, size_t size)
+{
+ ((struct test_memory_type *)mem_type)->num_malloc_calls++;
+ return malloc(size);
+}
+
+void *test_pceplib_calloc(void *mem_type, size_t size)
+{
+ ((struct test_memory_type *)mem_type)->num_calloc_calls++;
+ return calloc(1, size);
+}
+
+void *test_pceplib_realloc(void *mem_type, void *ptr, size_t size)
+{
+ ((struct test_memory_type *)mem_type)->num_realloc_calls++;
+ return realloc(ptr, size);
+}
+
+void *test_pceplib_strdup(void *mem_type, const char *str)
+{
+ ((struct test_memory_type *)mem_type)->num_strdup_calls++;
+ return strdup(str);
+}
+
+void test_pceplib_free(void *mem_type, void *ptr)
+{
+ ((struct test_memory_type *)mem_type)->num_free_calls++;
+ free(ptr);
+}
+
+void verify_memory_type(struct pceplib_memory_type *mt, uint32_t num_alloc,
+ uint32_t alloc_bytes, uint32_t num_free,
+ uint32_t free_bytes)
+{
+ CU_ASSERT_EQUAL(num_alloc, mt->num_allocates);
+ CU_ASSERT_EQUAL(alloc_bytes, mt->total_bytes_allocated);
+ CU_ASSERT_EQUAL(num_free, mt->num_frees);
+ CU_ASSERT_EQUAL(free_bytes, mt->total_bytes_freed);
+}
+
+void verify_ext_memory_type(void *mt, int num_malloc_calls,
+ int num_calloc_calls, int num_realloc_calls,
+ int num_strdup_calls, int num_free_calls)
+{
+ struct test_memory_type *mt_ptr = (struct test_memory_type *)mt;
+ CU_ASSERT_EQUAL(num_malloc_calls, mt_ptr->num_malloc_calls);
+ CU_ASSERT_EQUAL(num_calloc_calls, mt_ptr->num_calloc_calls);
+ CU_ASSERT_EQUAL(num_realloc_calls, mt_ptr->num_realloc_calls);
+ CU_ASSERT_EQUAL(num_strdup_calls, mt_ptr->num_strdup_calls);
+ CU_ASSERT_EQUAL(num_free_calls, mt_ptr->num_free_calls);
+}
+
+void test_memory_internal_impl()
+{
+ int alloc_size = 100;
+ struct pceplib_memory_type *pceplib_infra_ptr =
+ (struct pceplib_memory_type *)PCEPLIB_INFRA;
+ struct pceplib_memory_type *pceplib_messages_ptr =
+ (struct pceplib_memory_type *)PCEPLIB_MESSAGES;
+ int alloc_counter = 1;
+ int free_counter = 1;
+
+ /* reset the memory type counters for easier testing */
+ pceplib_infra_ptr->num_allocates =
+ pceplib_infra_ptr->total_bytes_allocated =
+ pceplib_infra_ptr->num_frees =
+ pceplib_infra_ptr->total_bytes_freed = 0;
+ pceplib_messages_ptr->num_allocates =
+ pceplib_messages_ptr->total_bytes_allocated =
+ pceplib_messages_ptr->num_frees =
+ pceplib_messages_ptr->total_bytes_freed = 0;
+
+ /* Make sure nothing crashes when all these are set NULL, since the
+ * internal default values should still be used. */
+ pceplib_memory_initialize(NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ /* Test malloc() */
+ void *ptr = pceplib_malloc(PCEPLIB_INFRA, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_INFRA, ptr);
+ verify_memory_type(pceplib_infra_ptr, alloc_counter, alloc_size,
+ free_counter++, 0);
+
+ /* Test calloc() */
+ ptr = pceplib_calloc(PCEPLIB_INFRA, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_INFRA, ptr);
+ alloc_counter++;
+ verify_memory_type(pceplib_infra_ptr, alloc_counter,
+ alloc_size * alloc_counter, free_counter++, 0);
+
+ /* Test realloc() */
+ ptr = pceplib_malloc(PCEPLIB_INFRA, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ ptr = pceplib_realloc(PCEPLIB_INFRA, ptr, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_INFRA, ptr);
+ alloc_counter += 2;
+ verify_memory_type(pceplib_infra_ptr, alloc_counter,
+ alloc_size * alloc_counter, free_counter++, 0);
+
+ /* Test strdup() */
+ ptr = pceplib_malloc(PCEPLIB_INFRA, alloc_size);
+ /* Make strdup duplicate (alloc_size - 1) bytes */
+ memset(ptr, 'a', alloc_size);
+ ((char *)ptr)[alloc_size - 1] = '\0';
+ char *str = pceplib_strdup(PCEPLIB_INFRA, (char *)ptr);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_INFRA, ptr);
+ pceplib_free(PCEPLIB_INFRA, str);
+ alloc_counter += 2;
+ free_counter++;
+ verify_memory_type(pceplib_infra_ptr, alloc_counter,
+ (alloc_size * alloc_counter) - 1, free_counter, 0);
+
+ /* Make sure only the pceplib_infra_ptr memory counters are incremented
+ */
+ verify_memory_type(pceplib_messages_ptr, 0, 0, 0, 0);
+}
+
+void test_memory_external_impl()
+{
+ int alloc_size = 100;
+ struct pceplib_memory_type *pceplib_infra_ptr =
+ (struct pceplib_memory_type *)PCEPLIB_INFRA;
+ struct pceplib_memory_type *pceplib_messages_ptr =
+ (struct pceplib_memory_type *)PCEPLIB_MESSAGES;
+
+ /* reset the internal memory type counters to later verify they are NOT
+ * incremented since an external impl was provided */
+ pceplib_infra_ptr->num_allocates =
+ pceplib_infra_ptr->total_bytes_allocated =
+ pceplib_infra_ptr->num_frees =
+ pceplib_infra_ptr->total_bytes_freed = 0;
+ pceplib_messages_ptr->num_allocates =
+ pceplib_messages_ptr->total_bytes_allocated =
+ pceplib_messages_ptr->num_frees =
+ pceplib_messages_ptr->total_bytes_freed = 0;
+
+ /* Setup the external memory type */
+ struct test_memory_type infra_mt, messages_mt;
+ void *infra_ptr = &infra_mt;
+ void *messages_ptr = &messages_mt;
+ memset(infra_ptr, 0, sizeof(struct test_memory_type));
+ memset(messages_ptr, 0, sizeof(struct test_memory_type));
+ int free_counter = 1;
+
+ /* Initialize the PCEPlib memory system with an external implementation
+ */
+ pceplib_memory_initialize(infra_ptr, messages_ptr, test_pceplib_malloc,
+ test_pceplib_calloc, test_pceplib_realloc,
+ test_pceplib_strdup, test_pceplib_free);
+
+ /* Test malloc() */
+ void *ptr = pceplib_malloc(PCEPLIB_MESSAGES, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_MESSAGES, ptr);
+ verify_ext_memory_type(messages_ptr, 1, 0, 0, 0, free_counter++);
+
+ /* Test calloc() */
+ ptr = pceplib_calloc(PCEPLIB_MESSAGES, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_MESSAGES, ptr);
+ verify_ext_memory_type(messages_ptr, 1, 1, 0, 0, free_counter++);
+
+ /* Test realloc() */
+ ptr = pceplib_malloc(PCEPLIB_MESSAGES, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ ptr = pceplib_realloc(PCEPLIB_MESSAGES, ptr, alloc_size);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_MESSAGES, ptr);
+ verify_ext_memory_type(messages_ptr, 2, 1, 1, 0, free_counter++);
+
+ /* Test strdup() */
+ ptr = pceplib_malloc(PCEPLIB_MESSAGES, alloc_size);
+ /* Make strdup duplicate (alloc_size - 1) bytes */
+ memset(ptr, 'a', alloc_size);
+ ((char *)ptr)[alloc_size - 1] = '\0';
+ char *str = pceplib_strdup(PCEPLIB_MESSAGES, (char *)ptr);
+ CU_ASSERT_PTR_NOT_NULL(ptr);
+ pceplib_free(PCEPLIB_MESSAGES, ptr);
+ pceplib_free(PCEPLIB_MESSAGES, str);
+ verify_ext_memory_type(messages_ptr, 3, 1, 1, 1, free_counter + 1);
+
+ /* Make sure the internal memory counters are NOT incremented */
+ verify_memory_type(pceplib_infra_ptr, 0, 0, 0, 0);
+ verify_memory_type(pceplib_messages_ptr, 0, 0, 0, 0);
+
+ verify_ext_memory_type(infra_ptr, 0, 0, 0, 0, 0);
+}
diff --git a/pceplib/test/pcep_utils_memory_test.h b/pceplib/test/pcep_utils_memory_test.h
new file mode 100644
index 0000000..4e0c3fa
--- /dev/null
+++ b/pceplib/test/pcep_utils_memory_test.h
@@ -0,0 +1,33 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_MEMORY_TEST_H_
+#define PCEP_MEMORY_TEST_H_
+
+void test_memory_internal_impl(void);
+void test_memory_external_impl(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_utils_ordered_list_test.c b/pceplib/test/pcep_utils_ordered_list_test.c
new file mode 100644
index 0000000..12ac456
--- /dev/null
+++ b/pceplib/test/pcep_utils_ordered_list_test.c
@@ -0,0 +1,257 @@
+/*
+ * 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 <CUnit/CUnit.h>
+
+#include "pcep_utils_ordered_list.h"
+#include "pcep_utils_ordered_list_test.h"
+
+typedef struct node_data_ {
+ int int_data;
+
+} node_data;
+
+
+int node_data_compare(void *list_entry, void *new_entry)
+{
+ /*
+ * < 0 if new_entry < list_entry
+ * == 0 if new_entry == list_entry (new_entry will be inserted after
+ * list_entry) > 0 if new_entry > list_entry
+ */
+
+ return ((node_data *)new_entry)->int_data
+ - ((node_data *)list_entry)->int_data;
+}
+
+
+void test_empty_list()
+{
+ ordered_list_handle *handle =
+ ordered_list_initialize(node_data_compare);
+
+ CU_ASSERT_PTR_NOT_NULL(handle);
+ assert(handle != NULL);
+ CU_ASSERT_PTR_NULL(handle->head);
+ CU_ASSERT_PTR_NOT_NULL(handle->compare_function);
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+
+ ordered_list_destroy(handle);
+}
+
+
+void test_null_list_handle()
+{
+ node_data data;
+ ordered_list_node node_data;
+
+ void *ptr = ordered_list_add_node(NULL, &data);
+ CU_ASSERT_PTR_NULL(ptr);
+
+ ptr = ordered_list_find(NULL, &data);
+ CU_ASSERT_PTR_NULL(ptr);
+
+ ptr = ordered_list_remove_first_node(NULL);
+ CU_ASSERT_PTR_NULL(ptr);
+
+ ptr = ordered_list_remove_first_node_equals(NULL, &data);
+ CU_ASSERT_PTR_NULL(ptr);
+
+ ptr = ordered_list_remove_node(NULL, &node_data, &node_data);
+ CU_ASSERT_PTR_NULL(ptr);
+}
+
+
+void test_add_to_list()
+{
+ node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ ordered_list_handle *handle =
+ ordered_list_initialize(node_data_compare);
+
+ ordered_list_add_node(handle, &data3);
+ ordered_list_add_node(handle, &data1);
+ ordered_list_add_node(handle, &data2);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 3);
+
+ ordered_list_node *node = handle->head;
+ CU_ASSERT_PTR_EQUAL(node->data, &data1);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_EQUAL(node->data, &data2);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_EQUAL(node->data, &data3);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_EQUAL(node, NULL);
+
+ ordered_list_destroy(handle);
+}
+
+
+void test_find()
+{
+ node_data data1, data2, data3, data_not_inList;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+ data_not_inList.int_data = 5;
+
+ ordered_list_handle *handle =
+ ordered_list_initialize(node_data_compare);
+
+ ordered_list_add_node(handle, &data3);
+ ordered_list_add_node(handle, &data2);
+ ordered_list_add_node(handle, &data1);
+
+ ordered_list_node *node = ordered_list_find(handle, &data1);
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data1);
+
+ node = ordered_list_find(handle, &data2);
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data2);
+
+ node = ordered_list_find(handle, &data3);
+ CU_ASSERT_PTR_NOT_NULL(node);
+ assert(node != NULL);
+ CU_ASSERT_PTR_EQUAL(node->data, &data3);
+
+ node = ordered_list_find(handle, &data_not_inList);
+ CU_ASSERT_PTR_NULL(node);
+
+ ordered_list_destroy(handle);
+}
+
+
+void test_remove_first_node()
+{
+ node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ ordered_list_handle *handle =
+ ordered_list_initialize(node_data_compare);
+
+ ordered_list_add_node(handle, &data1);
+ ordered_list_add_node(handle, &data2);
+ ordered_list_add_node(handle, &data3);
+
+ void *node_data = ordered_list_remove_first_node(handle);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data1);
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ node_data = ordered_list_remove_first_node(handle);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data2);
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+
+ node_data = ordered_list_remove_first_node(handle);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data3);
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+ CU_ASSERT_PTR_NULL(handle->head);
+
+ node_data = ordered_list_remove_first_node(handle);
+ CU_ASSERT_PTR_NULL(node_data);
+
+ ordered_list_destroy(handle);
+}
+
+
+void test_remove_first_node_equals()
+{
+ node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ ordered_list_handle *handle =
+ ordered_list_initialize(node_data_compare);
+
+ ordered_list_add_node(handle, &data1);
+ ordered_list_add_node(handle, &data2);
+ ordered_list_add_node(handle, &data3);
+
+ void *node_data = ordered_list_remove_first_node_equals(handle, &data2);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data2);
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ node_data = ordered_list_remove_first_node_equals(handle, &data3);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data3);
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+
+ node_data = ordered_list_remove_first_node_equals(handle, &data1);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data1);
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+
+ node_data = ordered_list_remove_first_node_equals(handle, &data1);
+ CU_ASSERT_PTR_NULL(node_data);
+
+ ordered_list_destroy(handle);
+}
+
+
+void test_remove_node()
+{
+ node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ ordered_list_handle *handle =
+ ordered_list_initialize(node_data_compare);
+
+ ordered_list_node *node1 = ordered_list_add_node(handle, &data1);
+ ordered_list_node *node2 = ordered_list_add_node(handle, &data2);
+ ordered_list_node *node3 = ordered_list_add_node(handle, &data3);
+
+ void *node_data = ordered_list_remove_node(handle, node2, node3);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data3);
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ node_data = ordered_list_remove_node(handle, node1, node2);
+ CU_ASSERT_PTR_NOT_NULL(node_data);
+ CU_ASSERT_PTR_EQUAL(node_data, &data2);
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+
+ ordered_list_destroy(handle);
+}
diff --git a/pceplib/test/pcep_utils_ordered_list_test.h b/pceplib/test/pcep_utils_ordered_list_test.h
new file mode 100644
index 0000000..3686848
--- /dev/null
+++ b/pceplib/test/pcep_utils_ordered_list_test.h
@@ -0,0 +1,39 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_UTILS_ORDERED_LIST_TEST_H_
+#define PCEP_UTILS_ORDERED_LIST_TEST_H_
+
+void test_empty_list(void);
+void test_null_list_handle(void);
+void test_add_to_list(void);
+void test_find(void);
+void test_remove_first_node(void);
+void test_remove_first_node_equals(void);
+void test_remove_node(void);
+int node_data_compare(void *list_entry, void *new_entry);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_utils_queue_test.c b/pceplib/test/pcep_utils_queue_test.c
new file mode 100644
index 0000000..6e62c75
--- /dev/null
+++ b/pceplib/test/pcep_utils_queue_test.c
@@ -0,0 +1,163 @@
+/*
+ * 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 <CUnit/CUnit.h>
+
+#include "pcep_utils_queue.h"
+#include "pcep_utils_queue_test.h"
+
+typedef struct node_data_ {
+ int int_data;
+
+} node_data;
+
+
+void test_empty_queue()
+{
+ queue_handle *handle = queue_initialize();
+
+ CU_ASSERT_PTR_NOT_NULL(handle);
+ assert(handle != NULL);
+ CU_ASSERT_PTR_NULL(handle->head);
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+
+ queue_destroy(handle);
+}
+
+
+void test_null_queue_handle()
+{
+ /* test each method handles a NULL handle without crashing */
+ node_data data;
+ queue_destroy(NULL);
+ void *ptr = queue_enqueue(NULL, &data);
+ CU_ASSERT_PTR_NULL(ptr);
+
+ ptr = queue_dequeue(NULL);
+ CU_ASSERT_PTR_NULL(ptr);
+}
+
+
+void test_enqueue()
+{
+ node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ queue_handle *handle = queue_initialize();
+
+ queue_enqueue(handle, &data1);
+ queue_enqueue(handle, &data2);
+ queue_enqueue(handle, &data3);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 3);
+
+ queue_node *node = handle->head;
+ CU_ASSERT_PTR_EQUAL(node->data, &data1);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_EQUAL(node->data, &data2);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_EQUAL(node->data, &data3);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_NULL(node);
+
+ queue_destroy(handle);
+}
+
+
+void test_enqueue_with_limit()
+{
+ node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ queue_handle *handle = queue_initialize_with_size(2);
+
+ queue_node *node = queue_enqueue(handle, &data1);
+ CU_ASSERT_PTR_NOT_NULL(node);
+
+ node = queue_enqueue(handle, &data2);
+ CU_ASSERT_PTR_NOT_NULL(node);
+
+ node = queue_enqueue(handle, &data3);
+ CU_ASSERT_PTR_NULL(node);
+
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ node = handle->head;
+ CU_ASSERT_PTR_EQUAL(node->data, &data1);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_EQUAL(node->data, &data2);
+
+ node = node->next_node;
+ CU_ASSERT_PTR_NULL(node);
+
+ queue_destroy(handle);
+}
+
+
+void test_dequeue()
+{
+ node_data data1, data2, data3;
+ data1.int_data = 1;
+ data2.int_data = 2;
+ data3.int_data = 3;
+
+ queue_handle *handle = queue_initialize();
+
+ /* first test dequeue handles an empty queue */
+ void *node_data = queue_dequeue(handle);
+ CU_ASSERT_PTR_NULL(node_data);
+
+ queue_enqueue(handle, &data1);
+ queue_enqueue(handle, &data2);
+ queue_enqueue(handle, &data3);
+
+ node_data = queue_dequeue(handle);
+ CU_ASSERT_PTR_EQUAL(node_data, &data1);
+ CU_ASSERT_EQUAL(handle->num_entries, 2);
+
+ node_data = queue_dequeue(handle);
+ CU_ASSERT_PTR_EQUAL(node_data, &data2);
+ CU_ASSERT_EQUAL(handle->num_entries, 1);
+
+ node_data = queue_dequeue(handle);
+ CU_ASSERT_PTR_EQUAL(node_data, &data3);
+ CU_ASSERT_EQUAL(handle->num_entries, 0);
+
+ node_data = queue_dequeue(handle);
+ CU_ASSERT_PTR_NULL(node_data);
+
+ queue_destroy(handle);
+}
diff --git a/pceplib/test/pcep_utils_queue_test.h b/pceplib/test/pcep_utils_queue_test.h
new file mode 100644
index 0000000..16236d0
--- /dev/null
+++ b/pceplib/test/pcep_utils_queue_test.h
@@ -0,0 +1,36 @@
+/*
+ * 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 : Javier Garcia <javier.garcia@voltanet.io>
+ *
+ */
+
+/*
+ * Timer definitions to be used internally by the pcep_timers library.
+ */
+
+#ifndef PCEP_UTILS_QUEUE_TEST_H_
+#define PCEP_UTILS_QUEUE_TEST_H_
+
+void test_empty_queue(void);
+void test_null_queue_handle(void);
+void test_enqueue(void);
+void test_enqueue_with_limit(void);
+void test_dequeue(void);
+
+#endif /* PCEPTIMERINTERNALS_H_ */
diff --git a/pceplib/test/pcep_utils_tests.c b/pceplib/test/pcep_utils_tests.c
new file mode 100644
index 0000000..ad9f769
--- /dev/null
+++ b/pceplib/test/pcep_utils_tests.c
@@ -0,0 +1,140 @@
+/*
+ * 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 <CUnit/Basic.h>
+#include <CUnit/CUnit.h>
+#include <CUnit/TestDB.h>
+#include "pcep_utils_ordered_list_test.h"
+#include "pcep_utils_queue_test.h"
+#include "pcep_utils_double_linked_list_test.h"
+#include "pcep_utils_counters_test.h"
+#include "pcep_utils_memory_test.h"
+
+
+int main(int argc, char **argv)
+{
+ /* Unused parameters cause compilation warnings */
+ (void)argc;
+ (void)argv;
+
+ CU_initialize_registry();
+
+ CU_pSuite test_queue_suite =
+ CU_add_suite("PCEP Utils Queue Test Suite", NULL, NULL);
+ CU_add_test(test_queue_suite, "test_empty_queue", test_empty_queue);
+ CU_add_test(test_queue_suite, "test_null_queue_handle",
+ test_null_queue_handle);
+ CU_add_test(test_queue_suite, "test_enqueue", test_enqueue);
+ CU_add_test(test_queue_suite, "test_enqueue_with_limit",
+ test_enqueue_with_limit);
+ CU_add_test(test_queue_suite, "test_dequeue", test_dequeue);
+
+ CU_pSuite test_list_suite =
+ CU_add_suite("PCEP Utils Ordered List Test Suite", NULL, NULL);
+ CU_add_test(test_list_suite, "test_empty_list", test_empty_list);
+ CU_add_test(test_list_suite, "test_null_handle", test_null_list_handle);
+ CU_add_test(test_list_suite, "test_add_toList", test_add_to_list);
+ CU_add_test(test_list_suite, "test_find", test_find);
+ CU_add_test(test_list_suite, "test_remove_first_node",
+ test_remove_first_node);
+ CU_add_test(test_list_suite, "test_remove_first_node_equals",
+ test_remove_first_node_equals);
+ CU_add_test(test_list_suite, "test_remove_node", test_remove_node);
+
+ CU_pSuite test_dl_list_suite = CU_add_suite(
+ "PCEP Utils Double Linked List Test Suite", NULL, NULL);
+ CU_add_test(test_dl_list_suite, "test_empty_dl_list",
+ test_empty_dl_list);
+ CU_add_test(test_dl_list_suite, "test_null_dl_handle",
+ test_null_dl_list_handle);
+ CU_add_test(test_dl_list_suite, "test_dll_prepend_data",
+ test_dll_prepend_data);
+ CU_add_test(test_dl_list_suite, "test_dll_append_data",
+ test_dll_append_data);
+ CU_add_test(test_dl_list_suite, "test_dll_delete_first_node",
+ test_dll_delete_first_node);
+ CU_add_test(test_dl_list_suite, "test_dll_delete_last_node",
+ test_dll_delete_last_node);
+ CU_add_test(test_dl_list_suite, "test_dll_delete_node",
+ test_dll_delete_node);
+
+ CU_pSuite test_counters_suite =
+ CU_add_suite("PCEP Utils Counters Test Suite", NULL, NULL);
+ CU_add_test(test_counters_suite, "test_create_counters_group",
+ test_create_counters_group);
+ CU_add_test(test_counters_suite, "test_create_counters_subgroup",
+ test_create_counters_subgroup);
+ CU_add_test(test_counters_suite, "test_add_counters_subgroup",
+ test_add_counters_subgroup);
+ CU_add_test(test_counters_suite, "test_create_subgroup_counter",
+ test_create_subgroup_counter);
+ CU_add_test(test_counters_suite, "test_delete_counters_group",
+ test_delete_counters_group);
+ CU_add_test(test_counters_suite, "test_delete_counters_subgroup",
+ test_delete_counters_subgroup);
+ CU_add_test(test_counters_suite, "test_reset_group_counters",
+ test_reset_group_counters);
+ CU_add_test(test_counters_suite, "test_reset_subgroup_counters",
+ test_reset_subgroup_counters);
+ CU_add_test(test_counters_suite, "test_increment_counter",
+ test_increment_counter);
+ CU_add_test(test_counters_suite, "test_increment_subgroup_counter",
+ test_increment_subgroup_counter);
+ CU_add_test(test_counters_suite, "test_dump_counters_group_to_log",
+ test_dump_counters_group_to_log);
+ CU_add_test(test_counters_suite, "test_dump_counters_subgroup_to_log",
+ test_dump_counters_subgroup_to_log);
+
+ CU_pSuite test_memory_suite =
+ CU_add_suite("PCEP Utils Memory Test Suite", NULL, NULL);
+ CU_add_test(test_memory_suite, "test_memory_internal_impl",
+ test_memory_internal_impl);
+ CU_add_test(test_memory_suite, "test_memory_external_impl",
+ test_memory_external_impl);
+
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ CU_FailureRecord *failure_record = CU_get_failure_list();
+ if (failure_record != NULL) {
+ printf("\nFailed tests:\n\t [Suite] [Test] [File:line-number]\n");
+ do {
+ printf("\t [%s] [%s] [%s:%d]\n",
+ failure_record->pSuite->pName,
+ failure_record->pTest->pName,
+ failure_record->strFileName,
+ failure_record->uiLineNumber);
+ failure_record = failure_record->pNext;
+
+ } while (failure_record != NULL);
+ }
+
+ CU_pRunSummary run_summary = CU_get_run_summary();
+ int result = run_summary->nTestsFailed;
+ CU_cleanup_registry();
+
+ return result;
+}
diff --git a/pceplib/test/pcep_utils_tests_valgrind.sh b/pceplib/test/pcep_utils_tests_valgrind.sh
new file mode 100755
index 0000000..6348d82
--- /dev/null
+++ b/pceplib/test/pcep_utils_tests_valgrind.sh
@@ -0,0 +1,2 @@
+source pceplib/test/pcep_tests_valgrind.sh
+valgrind_test pceplib/test/pcep_utils_tests
diff --git a/pceplib/test/subdir.am b/pceplib/test/subdir.am
new file mode 100644
index 0000000..88af592
--- /dev/null
+++ b/pceplib/test/subdir.am
@@ -0,0 +1,122 @@
+if PATHD_PCEP
+if PATHD_PCEP_TEST
+
+# The default Automake target is check, add a test target to call check.
+# Also make sure the binaries are current before running the tests.
+test: pceplib/test/pcep_msg_tests pceplib/test/pcep_pcc_api_tests pceplib/test/pcep_session_logic_tests pceplib/test/pcep_socket_comm_tests pceplib/test/pcep_timers_tests pceplib/test/pcep_utils_tests
+
+check_SCRIPTS = pceplib/test/pcep_msg_tests pceplib/test/pcep_pcc_api_tests pceplib/test/pcep_session_logic_tests pceplib/test/pcep_socket_comm_tests pceplib/test/pcep_timers_tests pceplib/test/pcep_utils_tests
+TESTS = $(check_SCRIPTS)
+
+
+# Definitions to build the Unit Test binaries with CUnit
+noinst_PROGRAMS += pceplib/test/pcep_msg_tests \
+ pceplib/test/pcep_pcc_api_tests \
+ pceplib/test/pcep_session_logic_tests \
+ pceplib/test/pcep_socket_comm_tests \
+ pceplib/test/pcep_timers_tests \
+ pceplib/test/pcep_utils_tests
+
+noinst_HEADERS += pceplib/test/pcep_msg_messages_test.h \
+ pceplib/test/pcep_msg_object_error_types_test.h \
+ pceplib/test/pcep_msg_objects_test.h \
+ pceplib/test/pcep_msg_tlvs_test.h \
+ pceplib/test/pcep_msg_tools_test.h \
+ pceplib/test/pcep_pcc_api_test.h \
+ pceplib/test/pcep_session_logic_loop_test.h \
+ pceplib/test/pcep_session_logic_states_test.h \
+ pceplib/test/pcep_session_logic_test.h \
+ pceplib/test/pcep_socket_comm_loop_test.h \
+ pceplib/test/pcep_socket_comm_test.h \
+ pceplib/test/pcep_timers_event_loop_test.h \
+ pceplib/test/pcep_timers_test.h \
+ pceplib/test/pcep_utils_counters_test.h \
+ pceplib/test/pcep_utils_double_linked_list_test.h \
+ pceplib/test/pcep_utils_memory_test.h \
+ pceplib/test/pcep_utils_ordered_list_test.h \
+ pceplib/test/pcep_utils_queue_test.h
+
+pceplib_test_pcep_msg_tests_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/pceplib
+pceplib_test_pcep_msg_tests_LDADD = $(top_builddir)/pceplib/libpcep_pcc.la lib/libfrr.la -lcunit -lpthread
+pceplib_test_pcep_msg_tests_SOURCES = pceplib/test/pcep_msg_messages_test.c \
+ pceplib/test/pcep_msg_messages_tests.c \
+ pceplib/test/pcep_msg_object_error_types_test.c \
+ pceplib/test/pcep_msg_objects_test.c \
+ pceplib/test/pcep_msg_tlvs_test.c \
+ pceplib/test/pcep_msg_tools_test.c
+
+# The pcc_api_tests and pcep_session_logic_tests use the
+# socket_comm_mock, so the LDADD variable needs to be modified
+pceplib_test_pcep_pcc_api_tests_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/pceplib
+pceplib_test_pcep_pcc_api_tests_LDADD = $(top_builddir)/pceplib/libsocket_comm_mock.la $(top_builddir)/pceplib/libpcep_pcc.la lib/libfrr.la -lcunit -lpthread
+pceplib_test_pcep_pcc_api_tests_SOURCES = pceplib/test/pcep_pcc_api_test.c pceplib/test/pcep_pcc_api_tests.c
+
+pceplib_test_pcep_session_logic_tests_CFLAGS = -I$(top_srcdir)/pceplib
+pceplib_test_pcep_session_logic_tests_LDADD = $(top_builddir)/pceplib/libsocket_comm_mock.la $(top_builddir)/pceplib/libpcep_pcc.la lib/libfrr.la -lcunit -lpthread
+pceplib_test_pcep_session_logic_tests_SOURCES = pceplib/test/pcep_session_logic_loop_test.c \
+ pceplib/test/pcep_session_logic_states_test.c \
+ pceplib/test/pcep_session_logic_test.c \
+ pceplib/test/pcep_session_logic_tests.c
+
+pceplib_test_pcep_socket_comm_tests_CFLAGS = -I$(top_srcdir)/pceplib
+pceplib_test_pcep_socket_comm_tests_LDADD = $(top_builddir)/pceplib/libpcep_pcc.la lib/libfrr.la -lcunit -lpthread
+pceplib_test_pcep_socket_comm_tests_SOURCES = pceplib/test/pcep_socket_comm_loop_test.c \
+ pceplib/test/pcep_socket_comm_test.c \
+ pceplib/test/pcep_socket_comm_tests.c
+
+pceplib_test_pcep_timers_tests_CFLAGS = -I$(top_srcdir)/pceplib
+pceplib_test_pcep_timers_tests_LDADD = $(top_builddir)/pceplib/libpcep_pcc.la lib/libfrr.la -lcunit -lpthread
+pceplib_test_pcep_timers_tests_SOURCES = pceplib/test/pcep_timers_event_loop_test.c \
+ pceplib/test/pcep_timers_test.c \
+ pceplib/test/pcep_timers_tests.c
+
+pceplib_test_pcep_utils_tests_CFLAGS = -I$(top_srcdir)/pceplib
+pceplib_test_pcep_utils_tests_LDADD = $(top_builddir)/pceplib/libpcep_pcc.la lib/libfrr.la -lcunit -lpthread
+pceplib_test_pcep_utils_tests_SOURCES = pceplib/test/pcep_utils_counters_test.c \
+ pceplib/test/pcep_utils_double_linked_list_test.c \
+ pceplib/test/pcep_utils_memory_test.c \
+ pceplib/test/pcep_utils_ordered_list_test.c \
+ pceplib/test/pcep_utils_queue_test.c \
+ pceplib/test/pcep_utils_tests.c
+
+# These test scripts will call the test binaries
+# defined above in noinst_PROGRAMS with Valgrind
+if HAVE_VALGRIND_PCEP
+
+dist_noinst_SCRIPTS = pceplib/test/pcep_pcc_api_tests_valgrind.sh \
+ pceplib/test/pcep_session_logic_tests_valgrind.sh \
+ pceplib/test/pcep_socket_comm_tests_valgrind.sh \
+ pceplib/test/pcep_timers_tests_valgrind.sh \
+ pceplib/test/pcep_utils_tests_valgrind.sh \
+ pceplib/test/pcep_msg_tests_valgrind.sh \
+ pceplib/test/pcep_tests_valgrind.sh
+
+check_SCRIPTS += pceplib/test/pcep_msg_tests_valgrind.sh \
+ pceplib/test/pcep_pcc_api_tests_valgrind.sh \
+ pceplib/test/pcep_session_logic_tests_valgrind.sh \
+ pceplib/test/pcep_socket_comm_tests_valgrind.sh \
+ pceplib/test/pcep_timers_tests_valgrind.sh \
+ pceplib/test/pcep_utils_tests_valgrind.sh
+
+TESTS += $(check_SCRIPTS)
+
+
+
+pceplib/test/pcep_msg_tests_valgrind.sh:
+ chmod +x pceplib/test/pcep_msg_tests_valgrind.sh
+pceplib/test/pcep_pcc_api_tests_valgrind.sh:
+ chmod +x pceplib/test/pcep_pcc_api_tests_valgrind.sh
+pceplib/test/pcep_session_logic_tests_valgrind.sh:
+ chmod +x pceplib/test/pcep_session_logic_tests_valgrind.sh
+pceplib/test/pcep_socket_comm_tests_valgrind.sh:
+ chmod +x pceplib/test/pcep_socket_comm_tests_valgrind.sh
+pceplib/test/pcep_timers_tests_valgrind.sh:
+ chmod +x pceplib/test/pcep_timers_tests_valgrind.sh
+pceplib/test/pcep_utils_tests_valgrind.sh:
+ chmod +x pceplib/test/pcep_utils_tests_valgrind.sh
+
+
+endif
+
+endif
+endif