|
|
|
|
@ -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); |
|
|
|
|
|