Browse Source

Test CCM limits and offline DM custody across restart

master
evgeny 1 week ago
parent
commit
937ef9fcef
  1. 32
      tests/test_dm.c
  2. 30
      tests/test_dm_e2e.c

32
tests/test_dm.c

@ -13,6 +13,7 @@
#include <string.h>
#include <stdio.h>
#include "../lib/mem.h"
int main(void) {
debug_config_init();
@ -100,6 +101,37 @@ int main(void) {
}
}
/* Границы CCM, включая пустое тело и порции медиа; повреждённый tag не принимается. */
uint8_t* large = u_malloc(DM_CCM_PLAIN_MAX + DM_TAG_SIZE + 1);
uint8_t* cipher = u_malloc(DM_CCM_PLAIN_MAX + DM_TAG_SIZE + 1);
uint8_t* restored = u_malloc(DM_CCM_PLAIN_MAX + 1);
if (!large || !cipher || !restored) return 1;
memset(large, 0x91, DM_CCM_PLAIN_MAX + 1);
const size_t sizes[] = {0, DM_MEDIA_PLAIN_SIZE, DM_CCM_PLAIN_MAX};
for (size_t i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) {
size_t n = sizes[i], clen = 0, plen = 0;
dm_build_nonce(id_ab, a, 100 + i, nonce);
if (dm_encrypt(key1, nonce, n ? large : NULL, n, cipher, &clen) != 0 || clen != n + DM_TAG_SIZE ||
dm_decrypt(key2, nonce, cipher, clen, restored, &plen) != 0 || plen != n || memcmp(large, restored, n)) failures++;
cipher[clen - 1] ^= 1;
if (dm_decrypt(key2, nonce, cipher, clen, restored, &plen) == 0 || plen != 0) failures++;
}
if (dm_encrypt(key1, nonce, large, DM_CCM_PLAIN_MAX + 1, cipher, &enc_len) == 0) failures++;
uint8_t media_id[16] = {1}, media_nonce[DM_NONCE_SIZE], other_nonce[DM_NONCE_SIZE];
dm_build_media_nonce(a, media_id, 0, media_nonce);
dm_build_media_nonce(a, media_id, 1, other_nonce);
if (!memcmp(media_nonce, other_nonce, DM_NONCE_SIZE)) failures++;
dm_build_media_nonce(b, media_id, 0, other_nonce);
if (!memcmp(media_nonce, other_nonce, DM_NONCE_SIZE)) failures++;
media_id[1] = 1;
dm_build_media_nonce(a, media_id, 0, other_nonce);
if (!memcmp(media_nonce, other_nonce, DM_NONCE_SIZE)) failures++;
dm_build_nonce(id_ab, a, 0, other_nonce);
if (!memcmp(media_nonce, other_nonce, DM_NONCE_SIZE)) failures++;
u_free(large);
u_free(cipher);
u_free(restored);
if (failures == 0) {
printf("TEST PASSED\n");
return 0;

30
tests/test_dm_e2e.c

@ -36,7 +36,6 @@
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <unistd.h>
#define CH_ID "4242424242424242"
@ -208,9 +207,9 @@ static int dm_msg_has(struct UTUN_INSTANCE* inst, const char* needle) {
/* количество блобов в dm_mail для recipient=B от sender=A (одна проверка) */
static int dm_mail_count(struct UTUN_INSTANCE* inst) {
sqlite3_stmt* s = NULL;
int n = 0;
int n = -1;
if (sqlite3_prepare_v2(inst->topo_sqlite_db,
"SELECT COUNT(*) FROM dm_mail WHERE recipient=? AND sender=?",
"SELECT COUNT(*) FROM dm_pending_messages WHERE recipient=? AND sender=?",
-1, &s, NULL) == SQLITE_OK) {
sqlite3_bind_int64(s, 1, (sqlite3_int64)g_sh.nid[IDX_B]);
sqlite3_bind_int64(s, 2, (sqlite3_int64)g_sh.nid[IDX_A]);
@ -248,7 +247,7 @@ static void member_put_placeholder(struct UTUN_INSTANCE* inst, int idx, const ch
/* мембер C со флагом storage=yes (adm_tags подписан канальным ключом) */
static void member_put_storage(struct UTUN_INSTANCE* inst, int idx, const char* name) {
char userinfo[256]; snprintf(userinfo, sizeof(userinfo), "{\"name\":\"%s\"}", name);
char adm_tags[64]; snprintf(adm_tags, sizeof(adm_tags), "{\"storage\":\"yes\",\"ver\":\"1\"}");
char adm_tags[80]; snprintf(adm_tags, sizeof(adm_tags), "{\"storage\":\"yes\",\"supernode\":\"yes\",\"ver\":\"1\"}");
uint8_t ats[64];
uint8_t amsg[256]; size_t off = strlen(adm_tags);
memcpy(amsg, adm_tags, off);
@ -279,6 +278,7 @@ static void do_setup(struct UTUN_INSTANCE* inst, int role) {
case IDX_C:
channel_put_shared(inst, 0);
member_put_self(inst, "C");
member_put_storage(inst, IDX_C, "C");
member_put_placeholder(inst, IDX_A, "A");
member_put_placeholder(inst, IDX_B, "B");
member_sync_start(inst, g_sh.nid[IDX_A], CH_ID, NULL, NULL);
@ -447,7 +447,23 @@ static void dm2_tick(void* arg) {
}
break;
case S2_WAIT_MAIL:
if (dm_mail_count(C) > 0) t->phase = S2_RECONNECT;
if (dm_mail_count(C) > 0) {
/* У отправителя больше нет процесса; очередь суперузла также проходит restart. */
utun_instance_destroy(A);
t->inst[IDX_A] = NULL;
utun_instance_destroy(C);
t->inst[IDX_C] = NULL;
char cfg[512];
snprintf(cfg, sizeof(cfg), "%s/c.conf", getenv("UTUN_TEST_DIR"));
t->inst[IDX_C] = utun_instance_create(t->ua, cfg);
if (!t->inst[IDX_C] || utun_instance_init(t->inst[IDX_C]) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "s2: supernode restart failed");
t->result = 2;
uasync_stop(t->ua);
return;
}
t->phase = S2_RECONNECT;
}
break;
case S2_RECONNECT: {
char cfg[512];
@ -554,10 +570,10 @@ int main(int argc, char** argv) {
char dir2[512]; snprintf(dir2, sizeof(dir2), "/tmp/utun_dm_e2e2_XXXXXX");
if (test_mkdtemp(dir2) != 0) { fprintf(stderr, "mkdtemp dir2 failed\n"); return 1; }
test_setenv("UTUN_TEST_DIR", dir2, 1);
fill_shared(70000 + (getpid() % 2000));
fill_shared(61000 + (getpid() % 1000));
write_configs(dir2);
TEST("first message offline: mailbox delivery without prior conversation"); {
TEST("first offline DM: supernode restart, sender remains offline"); {
struct UASYNC* ua = uasync_create();
if (!ua) { FAIL("uasync_create failed"); return 1; }

Loading…
Cancel
Save