Cover NCD candidate policy constructor cancellation and nested removal
This commit is contained in:
1 parent
772c0728e1
commit
496a3c788e
2 files changed
+114
-3
No files matched your search
+110
-1
@@ -4,7 +4,11 @@
|
||||
#include "utun_instance.h"
|
||||
#include "etcp.h"
|
||||
#include "etcp_api.h"
|
||||
#include "etcp_connections.h"
|
||||
#include "node_conn_direct.h"
|
||||
#include "topo_group.h"
|
||||
#include "topo_node.h"
|
||||
#include "config_parser.h"
|
||||
#include "test_clock.h"
|
||||
#include "../lib/mem.h"
|
||||
|
||||
@@ -163,13 +167,118 @@ static void control_length(void) {
|
||||
test_clock_run_for(ua, 51000); CHECK(!inst->ncd_registry); teardown();
|
||||
}
|
||||
|
||||
static struct TOPO_NODE* known_node(unsigned addresses) {
|
||||
struct SC_MYKEYS peer; CHECK(sc_generate_keypair(&peer) == SC_OK);
|
||||
struct TOPO_NODE* node = u_calloc(1, sizeof(*node)); CHECK(node);
|
||||
node->node_id = sc_derive_node_id_from_pubkey(peer.public_key);
|
||||
memcpy(node->public_key, peer.public_key, sizeof(node->public_key));
|
||||
for (unsigned i = 0; i < addresses; i++) {
|
||||
struct TOPO_ADDR4* addr = memory_pool_alloc(inst->topo_groups->v4_addr_pool); CHECK(addr);
|
||||
*addr = (struct TOPO_ADDR4){.addr = {127,0,0,1}, .port = (uint16_t)(9 + i), .protocol = TOPO_PROTO_UDP,
|
||||
.next = node->v4_addrs};
|
||||
node->v4_addrs = addr;
|
||||
}
|
||||
CHECK(topo_node_registry_store(inst->topo_groups, node) == node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static struct ETCP_SOCKET* local_socket(void) {
|
||||
struct CFG_SERVER server = {.name = "NCD candidates", .type = CFG_SERVER_TYPE_LOCAL, .mtu = 1280};
|
||||
struct sockaddr_in* addr = (struct sockaddr_in*)&server.ip;
|
||||
addr->sin_family = AF_INET; addr->sin_addr.s_addr = htonl(0x7f000001);
|
||||
struct ETCP_SOCKET* sock = etcp_socket_add(inst, &server); CHECK(sock); return sock;
|
||||
}
|
||||
|
||||
static unsigned link_count(struct ETCP_CONN* conn) {
|
||||
unsigned count = 0;
|
||||
for (struct ETCP_LINK* link = conn->links; link; link = link->next) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Ошибка каждого ресурса нового транспорта оставляет только исходную запись узла. */
|
||||
static void new_transport_failures(void) {
|
||||
for (unsigned stage = 0; stage < 3; stage++) {
|
||||
setup(); struct TOPO_NODE* node = known_node(0); struct NODE_CONN_DIRECT* handle = NULL;
|
||||
if (stage == 0) fail_callback = 1;
|
||||
if (stage == 1) fail_connect = 1;
|
||||
if (stage == 2) fail_alloc = 1;
|
||||
CHECK(node_conn_direct_open_node(inst, node->node_id, NULL, NULL, &handle, node, NULL) == NCD_ERR);
|
||||
fail_callback = fail_connect = fail_alloc = 0;
|
||||
uasync_drain_immediate(ua);
|
||||
CHECK(!handle && !inst->ncd_registry && !inst->connections->count);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
static void candidate_policy(void) {
|
||||
setup(); struct TOPO_NODE* node = known_node(3);
|
||||
memcpy(node->v4_addrs->addr, (uint8_t[]){8,8,8,8}, 4);
|
||||
struct ETCP_SOCKET* first = local_socket(); struct NODE_CONN_DIRECT* handle = NULL;
|
||||
CHECK(node_conn_direct_open(inst, node->node_id, NULL, NULL, &handle, NULL) == NCD_NEW);
|
||||
struct ETCP_CONN* conn = node_conn_direct_get_conn(handle); CHECK(link_count(conn) == 2);
|
||||
struct ETCP_SOCKET* second = local_socket();
|
||||
CHECK(ncd_add_socket_links(inst, second) == 2 && link_count(conn) == 4);
|
||||
CHECK(ncd_add_socket_links(inst, second) == 0 && node_conn_direct_update_node(inst, node->node_id) == 0);
|
||||
second->type = CFG_SERVER_TYPE_PUBLIC;
|
||||
CHECK(ncd_add_socket_links(inst, second) == 1 && link_count(conn) == 5);
|
||||
struct NODE_CONN_DIRECT* explicit = NULL;
|
||||
CHECK(node_conn_direct_open_node(inst, node->node_id, NULL, NULL, &explicit, node, first) == NCD_REUSED);
|
||||
CHECK(link_count(conn) == 6);
|
||||
node_conn_direct_close(explicit);
|
||||
CHECK(ncd_remove_socket_links(inst, second) == 3 && link_count(conn) == 3);
|
||||
node_conn_direct_force_close(handle); teardown();
|
||||
}
|
||||
|
||||
static void socket_capacity(void) {
|
||||
setup(); struct TOPO_NODE* node = known_node(1);
|
||||
for (unsigned i = 0; i < 33; i++) local_socket();
|
||||
struct NODE_CONN_DIRECT* handle = NULL;
|
||||
CHECK(node_conn_direct_open(inst, node->node_id, NULL, NULL, &handle, NULL) == NCD_NEW);
|
||||
CHECK(link_count(node_conn_direct_get_conn(handle)) == 33);
|
||||
node_conn_direct_force_close(handle); teardown();
|
||||
}
|
||||
|
||||
static void cancel_open_link(struct ETCP_CONN* conn, struct ETCP_LINK* link, int old_state, int old_status, void* arg) {
|
||||
(void)link; (void)old_status; (void)arg;
|
||||
if (old_state == -1) etcp_connection_close(conn);
|
||||
}
|
||||
|
||||
static void open_cancelled(void) {
|
||||
setup(); struct TOPO_NODE* node = known_node(1); local_socket();
|
||||
struct NODE_CONN_DIRECT* handle = NULL; struct events state = {0};
|
||||
etcp_add_link_status_cbk(inst, cancel_open_link, NULL);
|
||||
CHECK(node_conn_direct_open(inst, node->node_id, changed, &state, &handle, NULL) == NCD_ERR);
|
||||
etcp_remove_link_status_cbk(inst, cancel_open_link, NULL);
|
||||
uasync_drain_immediate(ua);
|
||||
CHECK(!handle && !inst->ncd_registry && !inst->connections->count && !state.closed && !state.up);
|
||||
teardown();
|
||||
}
|
||||
|
||||
static void remove_neighbor(struct ETCP_CONN* conn, struct ETCP_LINK* link, int old_state, int old_status, void* arg) {
|
||||
(void)old_state; (void)old_status; (void)arg;
|
||||
if (link->closing && conn->links) etcp_link_close(conn->links);
|
||||
}
|
||||
|
||||
static void nested_remove(void) {
|
||||
setup(); struct TOPO_NODE* node = known_node(2); struct ETCP_SOCKET* sock = local_socket();
|
||||
struct NODE_CONN_DIRECT* handle = NULL;
|
||||
CHECK(node_conn_direct_open(inst, node->node_id, NULL, NULL, &handle, NULL) == NCD_NEW);
|
||||
struct ETCP_CONN* conn = node_conn_direct_get_conn(handle); CHECK(link_count(conn) == 2);
|
||||
etcp_add_link_status_cbk(inst, remove_neighbor, NULL);
|
||||
CHECK(ncd_remove_socket_links(inst, sock) == 1 && !conn->links);
|
||||
etcp_remove_link_status_cbk(inst, remove_neighbor, NULL);
|
||||
node_conn_direct_force_close(handle); teardown();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO);
|
||||
if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG);
|
||||
test_clock_init(1000);
|
||||
struct { const char* name; void (*run)(void); } cases[] = {
|
||||
{"callback", callback_failure}, {"up", up_failure}, {"timer", timer_failure},
|
||||
{"fin_wait", fin_wait_failure}, {"nested", nested_events}, {"control", control_length}
|
||||
{"fin_wait", fin_wait_failure}, {"nested", nested_events}, {"control", control_length},
|
||||
{"new", new_transport_failures}, {"policy", candidate_policy}, {"capacity", socket_capacity},
|
||||
{"cancel", open_cancelled}, {"remove", nested_remove}
|
||||
};
|
||||
unsigned selected = 0;
|
||||
for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
|
||||
@@ -289,9 +289,11 @@ static void t8(void* arg) {
|
||||
|
||||
struct TOPO_NODE* ni = u_calloc(1, sizeof(struct TOPO_NODE));
|
||||
if (!ni) { fail("alloc ni"); return; }
|
||||
uint64_t fake_id = 0xF000000000000001ULL;
|
||||
struct SC_MYKEYS unreachable;
|
||||
if (sc_generate_keypair(&unreachable) != SC_OK) { u_free(ni); fail("unreachable identity"); return; }
|
||||
uint64_t fake_id = sc_derive_node_id_from_pubkey(unreachable.public_key);
|
||||
ni->group_ref_count = 0; ni->node_id = fake_id; ni->ver = 0;
|
||||
memcpy(ni->public_key, pubkey_b, SC_PUBKEY_SIZE);
|
||||
memcpy(ni->public_key, unreachable.public_key, SC_PUBKEY_SIZE);
|
||||
|
||||
struct TOPO_SOCKMETA4* sm = memory_pool_alloc(g_a->topo_groups->v4_sock_meta_pool);
|
||||
if (sm) { sm->id = 0; sm->config_type = CFG_SERVER_TYPE_PUBLIC; sm->address_profile = (struct address_profile){0}; sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; }
|
||||
|
||||
Reference in new issue
Block a user