diff --git a/tests/test_chat_sync_stress.c b/tests/test_chat_sync_stress.c index 971348c2..d034e210 100644 --- a/tests/test_chat_sync_stress.c +++ b/tests/test_chat_sync_stress.c @@ -18,6 +18,7 @@ #include "../src/config_updater.h" #include "../src/chat/db_sync.h" #include "topo_node_sqlite.h" +#include "../src/routing_layer/topo_group.h" #include "secure_channel.h" #include "../lib/u_async.h" #include "../lib/debug_config.h" diff --git a/tests/test_dm_invite.c b/tests/test_dm_invite.c index ba5114d8..840d312e 100644 --- a/tests/test_dm_invite.c +++ b/tests/test_dm_invite.c @@ -10,6 +10,7 @@ #include "../src/chat/chat_event.h" #include "../src/chat/chat_join.h" #include "../src/chat/chat_sync.h" +#include "../src/chat/db_sync.h" #include "../src/chat/invite_build.h" #include "../src/chat/invite_link.h" #include "../src/dm/dm_core.h" @@ -92,6 +93,11 @@ static int join_link(struct UASYNC* ua, const char* link) { static int start_node(struct UASYNC* ua, const char* directory, int index, int port) { struct SC_MYKEYS keys; if (sc_generate_keypair(&keys) != SC_OK) return -1; + if (index == 1) { + int master = getenv("UTUN_TEST_INVITEE_MASTER") != NULL; + while ((sc_derive_node_id_from_pubkey(keys.public_key) > nodes[0]->node_id) != master) + if (sc_generate_keypair(&keys) != SC_OK) return -1; + } char pub[65], priv[65], path[768], database[768]; for (int i = 0; i < 32; i++) { snprintf(pub + i * 2, 3, "%02x", keys.public_key[i]); @@ -117,7 +123,8 @@ int main(void) { if (getenv("UTUN_TEST_DEBUG")) { debug_set_category_level(DEBUG_CATEGORY_DM, DEBUG_LEVEL_DEBUG); debug_set_category_level(DEBUG_CATEGORY_CHAT_SYNC, DEBUG_LEVEL_DEBUG); - debug_set_category_level(DEBUG_CATEGORY_MEMBER_SYNC, DEBUG_LEVEL_INFO); + debug_set_category_level(DEBUG_CATEGORY_MEMBER_SYNC, DEBUG_LEVEL_DEBUG); + debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_INFO); } utun_instance_set_tun_init_enabled(0); struct UASYNC* ua = uasync_create(); @@ -139,6 +146,16 @@ int main(void) { chat_core_create_channel_auto(nodes[0], "target"); CHECK(!scalar(nodes[0], "SELECT channel_id FROM channels WHERE name='target'", &target), "create different target group"); CHECK(target != source && !message_count(), "initial empty PM"); + char target_id[64]; snprintf(target_id, sizeof(target_id), "%llu", (unsigned long long)target); + for (int i = 0; i < 5; i++) { + char text[64]; snprintf(text, sizeof(text), "history before invitation %d", i); + struct chat_msg_submit message = {0}; + snprintf(message.channel_id, sizeof(message.channel_id), "%s", target_id); + snprintf(message.content_type, sizeof(message.content_type), "text"); + message.data = (uint8_t*)text; message.data_len = (uint32_t)strlen(text); + chat_core_submit_message(nodes[0], &message); + } + CHECK(chat_core_count(nodes[0], target_id) == 5 && !chat_core_count(nodes[1], target_id), "five messages exist before PM invite"); request(1, target, source_id, 0); CHECK(!message_count() && !calls[1], "no PM before registration ACK"); @@ -179,7 +196,6 @@ int main(void) { CHECK(JOIN_KEY_TTL_SECONDS == 600 && chat_join_lookup_inviter(nodes[0], target, received.join_key) == nodes[0]->node_id, "delivered link is registered with ten minute lifetime"); CHECK(!join_link(ua, link), "B joins target group using received PM link"); - char target_id[64]; snprintf(target_id, sizeof(target_id), "%llu", (unsigned long long)target); chat_core_connect_channel(nodes[1], target_id); deadline = get_time_tb() + 100000; while (!topo_node_sqlite_member_in_channel(nodes[1]->topo_sqlite_db, target_id, nodes[1]->node_id) && @@ -189,6 +205,20 @@ int main(void) { topo_node_sqlite_member_in_channel(nodes[1]->topo_sqlite_db, target_id, nodes[1]->node_id)); CHECK(topo_node_sqlite_member_in_channel(nodes[0]->topo_sqlite_db, target_id, nodes[1]->node_id) && topo_node_sqlite_member_in_channel(nodes[1]->topo_sqlite_db, target_id, nodes[1]->node_id), "membership committed on both nodes"); + deadline = get_time_tb() + 300000; + while (chat_core_count(nodes[1], target_id) != 5 && get_time_tb() < deadline) uasync_poll(ua, 100); + CHECK(chat_core_count(nodes[1], target_id) == 5, "history created before invitation arrives after JOIN"); + CHECK(!chat_core_get_messages_json(nodes[1], target_id, 10, 0, messages, sizeof(messages), &length), "read received history"); + for (int i = 0; i < 5; i++) { + char text[64]; snprintf(text, sizeof(text), "history before invitation %d", i); + CHECK(strstr(messages, text), "every old message is present"); + } + struct DB_SYNC_INSTANCE* history_a = db_sync_instance_find(nodes[0], target); + struct DB_SYNC_INSTANCE* history_b = db_sync_instance_find(nodes[1], target); + uint64_t hash_a, hash_b; + CHECK(history_a && history_b && !db_sync_last_chain_hash8(history_a, &hash_a) && + !db_sync_last_chain_hash8(history_b, &hash_b) && hash_a == hash_b && + !db_sync_chain_verify(history_a) && !db_sync_chain_verify(history_b), "received history signatures and chains agree"); const char* text = "joined through PM invitation"; struct chat_msg_submit message = {0}; snprintf(message.channel_id, sizeof(message.channel_id), "%s", target_id); @@ -196,7 +226,7 @@ int main(void) { message.data = (uint8_t*)text; message.data_len = (uint32_t)strlen(text); chat_core_submit_message(nodes[1], &message); deadline = get_time_tb() + 100000; - while (!chat_core_count(nodes[0], target_id) && get_time_tb() < deadline) uasync_poll(ua, 100); + while (chat_core_count(nodes[0], target_id) != 6 && get_time_tb() < deadline) uasync_poll(ua, 100); CHECK(!chat_core_get_messages_json(nodes[0], target_id, 10, 0, messages, sizeof(messages), &length) && strstr(messages, text), "joined client can send a group message to the inviter"); request(6, target, "", 0);