/** * Unit tests for routing.c */ #include "routing.h" #include #include #include #include #include static void test_create_destroy(void) { routing_table_t *table = routing_table_create(); assert(table != NULL); assert(table->count == 0); assert(table->capacity > 0); routing_table_destroy(table); printf("PASS: test_create_destroy\n"); } static void test_insert_lookup(void) { routing_table_t *table = routing_table_create(); assert(table != NULL); route_entry_t entry = {0}; entry.network = inet_addr("10.0.0.0"); entry.prefix_length = 24; entry.next_hop_ip = inet_addr("192.168.1.1"); entry.next_hop = NULL; entry.type = ROUTE_TYPE_STATIC; entry.flags = ROUTE_FLAG_ACTIVE; entry.metrics.bandwidth_kbps = 1000; entry.metrics.latency_ms = 10; entry.metrics.packet_loss_rate = 50; // 0.5% entry.metrics.hop_count = 1; bool inserted = routing_table_insert(table, &entry); assert(inserted == true); assert(table->count == 1); route_entry_t found = {0}; bool found_route = routing_table_lookup(table, inet_addr("10.0.0.5"), &found); assert(found_route == true); assert(found.network == entry.network); assert(found.prefix_length == entry.prefix_length); assert(found.next_hop_ip == entry.next_hop_ip); // Lookup non-existent found_route = routing_table_lookup(table, inet_addr("192.168.2.1"), &found); assert(found_route == false); routing_table_destroy(table); printf("PASS: test_insert_lookup\n"); } static void test_validation(void) { routing_table_t *table = routing_table_create(); assert(table != NULL); // Add allowed dynamic subnet bool added = routing_add_dynamic_subnet(table, inet_addr("172.16.0.0"), 16); assert(added == true); // Try to insert a dynamic route that matches allowed subnet route_entry_t entry = {0}; entry.network = inet_addr("172.16.1.0"); entry.prefix_length = 24; entry.next_hop_ip = inet_addr("192.168.1.1"); entry.type = ROUTE_TYPE_DYNAMIC; entry.flags = ROUTE_FLAG_ACTIVE; bool inserted = routing_table_insert(table, &entry); assert(inserted == true); // Try to insert a dynamic route outside allowed subnet (should fail validation) route_entry_t entry2 = {0}; entry2.network = inet_addr("10.0.0.0"); entry2.prefix_length = 24; entry2.next_hop_ip = inet_addr("192.168.1.1"); entry2.type = ROUTE_TYPE_DYNAMIC; entry2.flags = ROUTE_FLAG_ACTIVE; inserted = routing_table_insert(table, &entry2); assert(inserted == false); // should be rejected // Static routes should bypass validation route_entry_t entry3 = {0}; entry3.network = inet_addr("10.0.0.0"); entry3.prefix_length = 24; entry3.next_hop_ip = inet_addr("192.168.1.1"); entry3.type = ROUTE_TYPE_STATIC; entry3.flags = ROUTE_FLAG_ACTIVE; inserted = routing_table_insert(table, &entry3); assert(inserted == true); // static allowed routing_table_destroy(table); printf("PASS: test_validation\n"); } static void test_delete(void) { routing_table_t *table = routing_table_create(); assert(table != NULL); route_entry_t entry = {0}; entry.network = inet_addr("10.0.0.0"); entry.prefix_length = 24; entry.next_hop_ip = inet_addr("192.168.1.1"); entry.type = ROUTE_TYPE_STATIC; entry.flags = ROUTE_FLAG_ACTIVE; bool inserted = routing_table_insert(table, &entry); assert(inserted == true); assert(table->count == 1); bool deleted = routing_table_delete(table, inet_addr("10.0.0.0"), 24, entry.next_hop_ip); assert(deleted == true); assert(table->count == 0); // Delete non-existent deleted = routing_table_delete(table, inet_addr("10.0.0.0"), 24, entry.next_hop_ip); assert(deleted == false); routing_table_destroy(table); printf("PASS: test_delete\n"); } static void test_local_subnets(void) { routing_table_t *table = routing_table_create(); assert(table != NULL); bool added = routing_add_local_subnet(table, inet_addr("192.168.0.0"), 24); assert(added == true); // Local subnet validation should pass for local routes route_entry_t entry = {0}; entry.network = inet_addr("192.168.0.0"); entry.prefix_length = 24; entry.next_hop_ip = inet_addr("0.0.0.0"); entry.type = ROUTE_TYPE_LOCAL; entry.flags = ROUTE_FLAG_ACTIVE; bool inserted = routing_table_insert(table, &entry); assert(inserted == true); routing_table_destroy(table); printf("PASS: test_local_subnets\n"); } static void test_get_all_routes(void) { routing_table_t *table = routing_table_create(); assert(table != NULL); // Insert multiple routes for same network route_entry_t entry1 = {0}; entry1.network = inet_addr("10.0.0.0"); entry1.prefix_length = 24; entry1.next_hop_ip = inet_addr("192.168.1.1"); entry1.type = ROUTE_TYPE_STATIC; entry1.flags = ROUTE_FLAG_ACTIVE; route_entry_t entry2 = {0}; entry2.network = inet_addr("10.0.0.0"); entry2.prefix_length = 24; entry2.next_hop_ip = inet_addr("192.168.1.2"); entry2.type = ROUTE_TYPE_STATIC; entry2.flags = ROUTE_FLAG_ACTIVE; assert(routing_table_insert(table, &entry1) == true); assert(routing_table_insert(table, &entry2) == true); route_entry_t *routes = NULL; size_t count = 0; bool got = routing_get_all_routes(table, inet_addr("10.0.0.0"), 24, &routes, &count); assert(got == true); assert(count == 2); // Clean up allocated routes free(routes); routing_table_destroy(table); printf("PASS: test_get_all_routes\n"); } int main(void) { printf("Running routing unit tests...\n"); test_create_destroy(); test_insert_lookup(); test_validation(); test_delete(); test_local_subnets(); test_get_all_routes(); printf("All tests passed!\n"); return 0; }