// test_etcp_ping.c - unit test for etcp_send_ping with callback on PONG/timeout #include #include #include #include #include "../src/etcp_connections.h" #include "../src/utun_instance.h" #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "../lib/mem.h" #include "../src/secure_channel.h" #define TEST_TIMEOUT_MS 500 static int test_completed = 0; static int cb_called = 0; static int cb_success = -1; static uint64_t test_nonce = 0; static void ping_test_callback(int success, void* arg, uint64_t nonce) { (void)arg; cb_called++; cb_success = success; test_nonce = nonce; DEBUG_INFO(DEBUG_CATEGORY_ETCP, "ping_test_callback: success=%d nonce=%016llx", success, (unsigned long long)nonce); test_completed = 1; } int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_TRACE); debug_set_categories(DEBUG_CATEGORY_ALL); DEBUG_INFO(DEBUG_CATEGORY_ETCP, "=== ETCP Ping Test ==="); struct UASYNC* ua = uasync_create(); if (!ua) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "uasync_create failed"); return 1; } struct UTUN_INSTANCE* instance = u_calloc(1, sizeof(struct UTUN_INSTANCE)); if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "instance alloc failed"); uasync_destroy(ua, 0); return 1; } instance->ua = ua; instance->node_id = 0x1234567890ABCDEFULL; // dummy keys for test (full init in production) for (int i = 0; i < SC_PRIVKEY_SIZE; i++) { instance->my_keys.private_key[i] = i; instance->my_keys.public_key[i] = i + 64; } struct ETCP_SOCKET* dummy_sock = u_calloc(1, sizeof(struct ETCP_SOCKET)); if (!dummy_sock) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "dummy sock alloc failed"); utun_instance_destroy(instance); uasync_destroy(ua, 0); return 1; } dummy_sock->instance = instance; dummy_sock->fd = socket(AF_INET, SOCK_DGRAM, 0); dummy_sock->local_addr.ss_family = AF_INET; instance->etcp_sockets = dummy_sock; // dummy pubkey uint8_t dummy_pubkey[SC_PUBKEY_SIZE]; for (int i = 0; i < SC_PUBKEY_SIZE; i++) dummy_pubkey[i] = i; struct sockaddr_storage test_addr; memset(&test_addr, 0, sizeof(test_addr)); struct sockaddr_in* sin = (struct sockaddr_in*)&test_addr; sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin->sin_port = htons(12345); // test timeout path (no receiver, expect success=0) int ret = etcp_send_ping(instance, dummy_pubkey, &test_addr, 100, ping_test_callback, NULL); if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_send_ping failed ret=%d", ret); utun_instance_destroy(instance); uasync_destroy(ua, 0); return 1; } // run uasync to trigger timeout cb for (int i = 0; i < 20 && !test_completed; i++) { uasync_poll(ua, 50); } if (cb_called != 1 || cb_success != 0) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "callback not triggered correctly: called=%d success=%d", cb_called, cb_success); utun_instance_destroy(instance); uasync_destroy(ua, 0); return 1; } DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Ping timeout test PASSED (cb called with success=0)"); // cleanup utun_instance_destroy(instance); uasync_destroy(ua, 0); DEBUG_INFO(DEBUG_CATEGORY_ETCP, "ETCP ping unit test PASSED"); return 0; }