mirror of
https://github.com/vicliu624/trail-mate.git
synced 2026-07-02 18:11:40 +00:00
244 lines
7.3 KiB
C++
244 lines
7.3 KiB
C++
#include "ui/screens/team/team_page_deferred_dispatch.h"
|
|
|
|
#include <cassert>
|
|
|
|
namespace
|
|
{
|
|
|
|
class FakeDispatchPort final
|
|
: public team::ui::ITeamPageDeferredDispatchPort
|
|
{
|
|
public:
|
|
bool hasController() const override { return has_controller; }
|
|
|
|
bool sendKeyDistPlain(const team::proto::TeamKeyDist& key_dist,
|
|
chat::ChannelId,
|
|
chat::NodeId dest) override
|
|
{
|
|
keydist_send_count += 1;
|
|
last_keydist = key_dist;
|
|
last_keydist_dest = dest;
|
|
return keydist_ok;
|
|
}
|
|
|
|
bool sendStatus(const team::proto::TeamStatus& status,
|
|
chat::ChannelId,
|
|
chat::NodeId dest) override
|
|
{
|
|
status_send_count += 1;
|
|
last_status = status;
|
|
last_status_dest = dest;
|
|
return status_ok;
|
|
}
|
|
|
|
bool sendStatusPlain(const team::proto::TeamStatus& status,
|
|
chat::ChannelId,
|
|
chat::NodeId dest) override
|
|
{
|
|
status_plain_send_count += 1;
|
|
last_status = status;
|
|
last_status_plain_dest = dest;
|
|
return status_plain_ok;
|
|
}
|
|
|
|
team::TeamService::SendError lastSendError() const override
|
|
{
|
|
return error;
|
|
}
|
|
|
|
bool has_controller = true;
|
|
bool keydist_ok = true;
|
|
bool status_ok = true;
|
|
bool status_plain_ok = true;
|
|
team::TeamService::SendError error =
|
|
team::TeamService::SendError::None;
|
|
int keydist_send_count = 0;
|
|
int status_send_count = 0;
|
|
int status_plain_send_count = 0;
|
|
chat::NodeId last_keydist_dest = 0;
|
|
chat::NodeId last_status_dest = 1;
|
|
chat::NodeId last_status_plain_dest = 1;
|
|
team::proto::TeamKeyDist last_keydist;
|
|
team::proto::TeamStatus last_status;
|
|
};
|
|
|
|
team::TeamId testTeamId()
|
|
{
|
|
team::TeamId id{};
|
|
id[0] = 0xCA;
|
|
id[1] = 0xFE;
|
|
return id;
|
|
}
|
|
|
|
team::ui::TeamPageDeferredDispatchState readyState()
|
|
{
|
|
team::ui::TeamPageDeferredDispatchState state;
|
|
state.in_team = true;
|
|
state.has_team_id = true;
|
|
state.self_is_leader = true;
|
|
state.team_id = testTeamId();
|
|
state.security_round = 12;
|
|
state.has_team_psk = true;
|
|
state.team_psk[0] = 0x42;
|
|
return state;
|
|
}
|
|
|
|
team::ui::TeamPageDeferredDispatchQueue makeQueue()
|
|
{
|
|
team::ui::TeamPageDeferredDispatchConfig config;
|
|
config.keydist_max_retries = 2;
|
|
config.keydist_retry_interval_s = 5;
|
|
config.status_rebroadcast_interval_s = 2;
|
|
return team::ui::TeamPageDeferredDispatchQueue(config);
|
|
}
|
|
|
|
void testKeyDistRetriesRespectDelayAndDeduplicate()
|
|
{
|
|
auto queue = makeQueue();
|
|
FakeDispatchPort port;
|
|
auto state = readyState();
|
|
|
|
queue.enqueueKeyDist(0x22222222, 13, 100);
|
|
queue.enqueueKeyDist(0x22222222, 13, 100);
|
|
assert(queue.keyDistPendingCount() == 1);
|
|
|
|
auto effects = queue.processKeyDistRetries(state, port, 104);
|
|
assert(!effects.sent_keydist);
|
|
assert(port.keydist_send_count == 0);
|
|
|
|
effects = queue.processKeyDistRetries(state, port, 105);
|
|
assert(effects.sent_keydist);
|
|
assert(port.keydist_send_count == 1);
|
|
assert(port.last_keydist_dest == 0x22222222);
|
|
assert(port.last_keydist.team_id == testTeamId());
|
|
assert(port.last_keydist.key_id == 13);
|
|
assert(port.last_keydist.channel_psk_len ==
|
|
team::proto::kTeamChannelPskSize);
|
|
assert(port.last_keydist.channel_psk[0] == 0x42);
|
|
|
|
queue.confirmKeyDist(0x22222222, 13);
|
|
assert(queue.keyDistPendingCount() == 0);
|
|
}
|
|
|
|
void testKeyDistFailureEffects()
|
|
{
|
|
auto queue = makeQueue();
|
|
FakeDispatchPort port;
|
|
auto state = readyState();
|
|
port.keydist_ok = false;
|
|
port.error = team::TeamService::SendError::MeshSendFail;
|
|
|
|
queue.enqueueKeyDist(0x33333333, 21, 0);
|
|
auto effects = queue.processKeyDistRetries(state, port, 5);
|
|
|
|
assert(effects.sent_keydist);
|
|
assert(effects.failures.size() == 1);
|
|
assert(effects.failures[0].action ==
|
|
team::ui::TeamPageDeferredDispatchAction::KeyDist);
|
|
assert(effects.failures[0].kind ==
|
|
team::ui::TeamPageDeferredDispatchFailureKind::SendFailedDetail);
|
|
assert(effects.failures[0].error ==
|
|
team::TeamService::SendError::MeshSendFail);
|
|
|
|
port.keydist_ok = true;
|
|
effects = queue.processKeyDistRetries(state, port, 10);
|
|
assert(effects.failures.empty());
|
|
effects = queue.processKeyDistRetries(state, port, 15);
|
|
assert(effects.failures.size() == 1);
|
|
assert(effects.failures[0].kind ==
|
|
team::ui::TeamPageDeferredDispatchFailureKind::SendFailed);
|
|
assert(queue.keyDistPendingCount() == 0);
|
|
}
|
|
|
|
void testKeyDistMissingRuntimeDoesNothing()
|
|
{
|
|
auto queue = makeQueue();
|
|
FakeDispatchPort port;
|
|
auto state = readyState();
|
|
port.has_controller = false;
|
|
|
|
queue.enqueueKeyDist(0x33333333, 21, 0);
|
|
auto effects = queue.processKeyDistRetries(state, port, 5);
|
|
|
|
assert(!effects.sent_keydist);
|
|
assert(port.keydist_send_count == 0);
|
|
assert(queue.keyDistPendingCount() == 1);
|
|
|
|
state.has_team_psk = false;
|
|
port.has_controller = true;
|
|
effects = queue.processKeyDistRetries(state, port, 10);
|
|
assert(!effects.sent_keydist);
|
|
assert(port.keydist_send_count == 0);
|
|
}
|
|
|
|
void testStatusBroadcastSendsAndReschedules()
|
|
{
|
|
auto queue = makeQueue();
|
|
FakeDispatchPort port;
|
|
auto state = readyState();
|
|
team::proto::TeamStatus status;
|
|
status.key_id = 12;
|
|
status.members = {0x11111111, 0x22222222};
|
|
status.has_members = true;
|
|
status.leader_id = 0x11111111;
|
|
|
|
queue.scheduleStatusBroadcast(2, 100, 3);
|
|
assert(queue.statusBroadcastPendingCount() == 1);
|
|
|
|
auto effects = queue.processStatusBroadcasts(state, status, port, 102);
|
|
assert(!effects.sent_status);
|
|
assert(port.status_send_count == 0);
|
|
|
|
effects = queue.processStatusBroadcasts(state, status, port, 103);
|
|
assert(effects.sent_status);
|
|
assert(port.status_send_count == 1);
|
|
assert(port.status_plain_send_count == 1);
|
|
assert(port.last_status.key_id == 12);
|
|
assert(queue.statusBroadcastPendingCount() == 1);
|
|
|
|
effects = queue.processStatusBroadcasts(state, status, port, 105);
|
|
assert(effects.sent_status);
|
|
assert(port.status_send_count == 2);
|
|
assert(port.status_plain_send_count == 2);
|
|
assert(queue.statusBroadcastPendingCount() == 0);
|
|
}
|
|
|
|
void testStatusBroadcastFailureAndInvalidLeaderState()
|
|
{
|
|
auto queue = makeQueue();
|
|
FakeDispatchPort port;
|
|
auto state = readyState();
|
|
team::proto::TeamStatus status;
|
|
status.key_id = 3;
|
|
port.status_ok = false;
|
|
port.status_plain_ok = false;
|
|
|
|
queue.scheduleStatusBroadcast(1, 0, 0);
|
|
auto effects = queue.processStatusBroadcasts(state, status, port, 0);
|
|
|
|
assert(effects.sent_status);
|
|
assert(effects.failures.size() == 2);
|
|
assert(effects.failures[0].action ==
|
|
team::ui::TeamPageDeferredDispatchAction::Status);
|
|
assert(effects.failures[0].needs_keys);
|
|
assert(!effects.failures[1].needs_keys);
|
|
|
|
queue.scheduleStatusBroadcast(1, 10, 0);
|
|
state.self_is_leader = false;
|
|
effects = queue.processStatusBroadcasts(state, status, port, 10);
|
|
assert(!effects.sent_status);
|
|
assert(queue.statusBroadcastPendingCount() == 0);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main()
|
|
{
|
|
testKeyDistRetriesRespectDelayAndDeduplicate();
|
|
testKeyDistFailureEffects();
|
|
testKeyDistMissingRuntimeDoesNothing();
|
|
testStatusBroadcastSendsAndReschedules();
|
|
testStatusBroadcastFailureAndInvalidLeaderState();
|
|
return 0;
|
|
}
|