Test normal call busy confirmation and all incoming rejection policies

This commit is contained in:
evgeny committed 2026-10-19 14:59:55 +02:00
1 parent 79b4235960
commit b21aeaa6f8
1 file changed
+64 -2
+64 -2
View File
@@ -79,6 +79,7 @@ enum call_phase {
P_DECLINE, /* B: call_decline */
P_WAIT_ENDED2, /* обе ENDED + A DECLINED */
P_TIMEOUT_START, P_TIMEOUT_INCOMING, P_TIMEOUT_ACTIVE, P_TIMEOUT_ENDED,
P_POLICY_START, P_POLICY_WAIT, P_POLICY_RING, P_POLICY_END,
P_DONE,
};
@@ -93,11 +94,12 @@ struct call_test_ctx {
uint64_t call_id; /* текущий call_id */
uint64_t previous_call_id;
int video_restart_tested;
int policy_index;
};
/* записи событий CHAT_EVT_CALL_* на узел */
struct call_evt {
int incoming, ringing, accepted, ended, declined, errors;
int incoming, ringing, accepted, ended, declined, errors, phone_busy;
uint64_t route_peer, route_group;
uint64_t incoming_call_id;
uint64_t accepted_call_id;
@@ -318,6 +320,9 @@ static void call_evt_handler(struct UTUN_INSTANCE* inst, int type, const uint8_t
struct call_evt* ev = (struct call_evt*)inst->test_user_ptr;
if (!ev) return;
switch (type) {
case CHAT_EVT_CALL_PHONE_BUSY:
ev->phone_busy++;
break;
case CHAT_EVT_CALL_ERROR:
ev->errors++;
break;
@@ -863,8 +868,65 @@ static void call_tick(void* arg) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "unconfirmed end did not release sessions cleanly"); t->result = 2; break;
}
DEBUG_INFO(DEBUG_CATEGORY_CALL, "call end regression: epoch reset, ACK loss, stale end, simultaneous end and deadline passed");
t->phase = P_DONE;
t->phase = P_POLICY_START;
break;
case P_POLICY_START: {
static const struct { int state; unsigned policy; } policies[] = {
{0, CALL_POLICY_WARN_PHONE}, {2, CALL_POLICY_PUBLISH_PHONE}, {2, CALL_POLICY_WARN_PHONE},
{2, CALL_POLICY_WARN_PHONE}, {2, CALL_POLICY_WARN_PHONE | CALL_POLICY_REJECT_PHONE},
{0, CALL_POLICY_BLOCK_CALLS}, {2, CALL_POLICY_BLOCK_CALLS | CALL_POLICY_WARN_PHONE},
{2, CALL_POLICY_BLOCK_RADIO}, {2, CALL_POLICY_WARN_PHONE}, {2, CALL_POLICY_WARN_PHONE}
};
if (t->policy_index == (int)(sizeof(policies) / sizeof(policies[0]))) {
call_set_phone_state(B, 0, CALL_POLICY_PUBLISH_PHONE);
DEBUG_INFO(DEBUG_CATEGORY_CALL, "phone policy passed: independent flags, no incoming UI before choice, override, cancel, rejection, deadline");
t->phase = P_DONE; break;
}
memset(ea, 0, sizeof(*ea)); memset(eb, 0, sizeof(*eb));
call_set_phone_state(B, policies[t->policy_index].state, policies[t->policy_index].policy);
++t->call_id;
call_start(A, CH_ID, nb, t->call_id);
t->phase = P_POLICY_WAIT; break;
}
case P_POLICY_WAIT:
if (t->policy_index == 4 || t->policy_index == 5 || t->policy_index == 6) {
if (!ea->ended) break;
int expected = t->policy_index == 4 ? CALL_REASON_PHONE_BUSY : CALL_REASON_DECLINE;
if (eb->incoming || ea->phone_busy || ea->ended_reason != expected) goto policy_failed;
t->phase = P_POLICY_END; break;
}
if (t->policy_index == 2 || t->policy_index == 3 || t->policy_index >= 8) {
if (!ea->phone_busy) break;
if (eb->incoming || ea->ringing || ea->phone_busy != 1) goto policy_failed;
if (t->policy_index == 2) {
call_hangup(A, t->call_id); t->phase = P_POLICY_END;
} else if (t->policy_index == 8) {
struct call_session* s = call_session_find(A->call, t->call_id);
s->started_tb -= CALL_RING_TIMEOUT_TB;
call_continue(A, t->call_id);
if (ea->ended_reason != CALL_REASON_RING_TIMEOUT) goto policy_failed;
t->phase = P_POLICY_END;
} else {
if (t->policy_index == 9) call_set_phone_state(B, 2, CALL_POLICY_BLOCK_CALLS | CALL_POLICY_WARN_PHONE);
call_continue(A, t->call_id);
t->phase = t->policy_index == 9 ? P_POLICY_END : P_POLICY_RING;
}
} else t->phase = P_POLICY_RING;
break;
case P_POLICY_RING:
if (!eb->incoming) break;
if (eb->incoming_call_id != t->call_id || (t->policy_index != 3 && ea->phone_busy)) goto policy_failed;
call_decline(B, t->call_id); t->phase = P_POLICY_END; break;
case P_POLICY_END:
if (!ea->ended || !eb->ended || call_session_find(A->call, t->call_id) || call_session_find(B->call, t->call_id)) break;
if (ea->ended != 1 || eb->ended != 1 || (t->policy_index == 9 && (eb->incoming || ea->ended_reason != CALL_REASON_DECLINE)))
goto policy_failed;
call_continue(A, t->call_id); // Поздняя команда не должна создавать новую сессию.
++t->policy_index; t->phase = P_POLICY_START; break;
policy_failed:
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "phone policy failed scenario=%d incoming=%d busy_events=%d reason=%u",
t->policy_index, eb->incoming, ea->phone_busy, ea->ended_reason);
t->result = 2; break;
case P_DONE:
t->result = 1;
uasync_stop(t->ua);