mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-06-27 19:49:31 +00:00
chore: test refactor
This commit is contained in:
parent
8835492d6f
commit
a5d760468a
@ -20,6 +20,12 @@ impl TestLogosAccount {
|
||||
verifying_key,
|
||||
}
|
||||
}
|
||||
|
||||
/// This account's cryptographic id: the hex of its verifying key. This is
|
||||
/// what a credential carries and what `validate_sender` resolves to
|
||||
pub fn iden_id(&self) -> IdentId {
|
||||
IdentId::new(hex::encode(self.verifying_key.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IdentityProvider for TestLogosAccount {
|
||||
|
||||
@ -20,12 +20,6 @@ pub struct Content {
|
||||
pub struct ConvoOutcome {
|
||||
pub convo_id: ConversationId,
|
||||
pub content: Option<Content>,
|
||||
/// The *unvalidated* sender credential for `content`: the claimed Account
|
||||
/// and the device (LocalIdentity) it was sent from. The device key is
|
||||
/// MLS-authenticated, but the account claim must be validated against an
|
||||
/// [`AccountService`](logos_account::AccountService) before it is trusted.
|
||||
/// `None` for control messages (e.g. MLS commits) carrying no application
|
||||
/// content, and for conversation types that don't yet surface a credential.
|
||||
pub credential: Option<SenderCredential>,
|
||||
}
|
||||
|
||||
|
||||
@ -41,13 +41,15 @@ pub struct ReceivedMessage<T> {
|
||||
pub struct TestClient {
|
||||
inner: ClientType,
|
||||
received_messages: Vec<ReceivedMessage<Vec<u8>>>,
|
||||
sender_identity: MessageSender,
|
||||
}
|
||||
|
||||
impl TestClient {
|
||||
fn init(client: ClientType) -> Self {
|
||||
fn init(client: ClientType, sender_identity: MessageSender) -> Self {
|
||||
Self {
|
||||
inner: client,
|
||||
received_messages: vec![],
|
||||
sender_identity,
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,6 +57,10 @@ impl TestClient {
|
||||
self.inner.ident_id().clone()
|
||||
}
|
||||
|
||||
pub fn as_sender(&self) -> MessageSender {
|
||||
self.sender_identity.clone()
|
||||
}
|
||||
|
||||
fn drain_outcomes(&mut self) -> Vec<PayloadOutcome> {
|
||||
let mut messages = vec![];
|
||||
while let Some(data) = self.inner.ds().poll() {
|
||||
@ -102,9 +108,9 @@ impl TestClient {
|
||||
&self.received_messages
|
||||
}
|
||||
|
||||
pub fn check(&self, convo_id: &str, content: &[u8]) -> bool {
|
||||
pub fn check(&self, convo_id: &str, content: &[u8], sender: Option<MessageSender>) -> bool {
|
||||
for msg in &self.received_messages {
|
||||
if msg.convo_id == convo_id && msg.contents == content {
|
||||
if msg.convo_id == convo_id && msg.contents == content && msg.sender == sender {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -172,11 +178,16 @@ impl<const N: usize> TestHarness<N> {
|
||||
let ident = TestLogosAccount::new(Self::names(i));
|
||||
|
||||
addresses.insert(i, ident.id().clone());
|
||||
let iden_id = ident.iden_id();
|
||||
let sender_identity = MessageSender {
|
||||
account: iden_id.clone(),
|
||||
local_identity: iden_id,
|
||||
};
|
||||
let core_client =
|
||||
ClientType::new_with_name(ident, ds.clone(), rs.clone(), wp, MemStore::new())
|
||||
.unwrap();
|
||||
|
||||
let client = TestClient::init(core_client);
|
||||
let client = TestClient::init(core_client, sender_identity);
|
||||
|
||||
clients.push(client);
|
||||
}
|
||||
@ -348,6 +359,8 @@ mod tests {
|
||||
|
||||
harness.process(Duration::from_millis(200));
|
||||
|
||||
assert!(harness.raya().check(&convo_id, b"Hello"))
|
||||
// GroupV2 (de-mls) carries no account-bound credential yet, so the
|
||||
// sender can't be validated — it resolves to `None`.
|
||||
assert!(harness.raya().check(&convo_id, b"Hello", None))
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,35 +49,36 @@ fn create_group() {
|
||||
.expect("Pax send");
|
||||
harness.process(Duration::from_millis(500));
|
||||
|
||||
assert!(harness.saro().check(&convo_id, M_R1));
|
||||
assert!(harness.saro().check(&convo_id, M_P1));
|
||||
// The sender a recipient resolves each author to — the key-based identity,
|
||||
// captured from the account (not the display name in `ident_id`).
|
||||
let raya_sender = harness.raya().as_sender();
|
||||
let pax_sender = harness.pax().as_sender();
|
||||
|
||||
assert!(!harness.raya().check(&convo_id, M_R1));
|
||||
assert!(harness.raya().check(&convo_id, M_P1));
|
||||
// Each message must arrive *and* carry the validated sender of its author:
|
||||
// M_R1 from Raya, M_P1 from Pax.
|
||||
assert!(
|
||||
harness
|
||||
.saro()
|
||||
.check(&convo_id, M_R1, Some(raya_sender.clone()))
|
||||
);
|
||||
assert!(harness.saro().check(&convo_id, M_P1, Some(pax_sender.clone())));
|
||||
|
||||
assert!(!harness.pax().check(&convo_id, M_R1));
|
||||
assert!(!harness.pax().check(&convo_id, M_P1));
|
||||
assert!(
|
||||
!harness
|
||||
.raya()
|
||||
.check(&convo_id, M_R1, Some(raya_sender.clone()))
|
||||
);
|
||||
assert!(harness.raya().check(&convo_id, M_P1, Some(pax_sender.clone())));
|
||||
|
||||
// Every delivered message carries a verified sender: both the Account and
|
||||
// the LocalIdentity it was sent from. On testnet each identity is its own
|
||||
// single-device account, so the two resolve to the same key.
|
||||
let raya_sender = harness
|
||||
.saro()
|
||||
.sender_of(&convo_id, M_R1)
|
||||
.expect("Saro should see who sent Raya's message")
|
||||
.clone();
|
||||
assert!(!harness.pax().check(&convo_id, M_R1, Some(raya_sender.clone())));
|
||||
assert!(!harness.pax().check(&convo_id, M_P1, Some(pax_sender.clone())));
|
||||
|
||||
// Single-key testnet account: account and local identity are the same key.
|
||||
assert_eq!(
|
||||
raya_sender.account, raya_sender.local_identity,
|
||||
"single-key testnet account resolves Account == LocalIdentity"
|
||||
);
|
||||
|
||||
let pax_sender = harness
|
||||
.saro()
|
||||
.sender_of(&convo_id, M_P1)
|
||||
.expect("Saro should see who sent Pax's message")
|
||||
.clone();
|
||||
|
||||
// Distinct identities resolve to distinct senders — the basis for telling
|
||||
// Distinct identities resolve to distinct accounts — the basis for telling
|
||||
// group members apart and for collapsing an account's devices to one Account.
|
||||
assert_ne!(
|
||||
raya_sender.account, pax_sender.account,
|
||||
|
||||
@ -32,12 +32,12 @@ fn groupv2_2way_roundtrip() {
|
||||
.send_content(&convo_id, S_M1)
|
||||
.expect("saro send");
|
||||
|
||||
harness.process_until(|h| h.raya().check(&convo_id, S_M1));
|
||||
harness.process_until(|h| h.raya().check(&convo_id, S_M1, None));
|
||||
|
||||
// Raya replies; settle until Saro receives it.
|
||||
info!(target: "chat", "Raya -> sending:{R_M1:?}");
|
||||
harness.raya().send_content(&convo_id, R_M1).unwrap();
|
||||
harness.process_until(|h| h.saro().check(&convo_id, R_M1));
|
||||
harness.process_until(|h| h.saro().check(&convo_id, R_M1, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -70,7 +70,7 @@ fn core_client() {
|
||||
.send_content(&convo_id, S_M1)
|
||||
.expect("saro send");
|
||||
|
||||
harness.process_until_label("Recv S_M1", |h| h.raya().check(&convo_id, S_M1));
|
||||
harness.process_until_label("Recv S_M1", |h| h.raya().check(&convo_id, S_M1, None));
|
||||
|
||||
// Raya replies; settle until Saro receives it.
|
||||
info!(target: "chat", "Raya -> sending: {R_M1:?}");
|
||||
@ -79,7 +79,7 @@ fn core_client() {
|
||||
.send_content(&convo_id, R_M1)
|
||||
.expect("raya send");
|
||||
|
||||
harness.process_until_label("Recv R_M1", |h| h.saro().check(&convo_id, R_M1));
|
||||
harness.process_until_label("Recv R_M1", |h| h.saro().check(&convo_id, R_M1, None));
|
||||
|
||||
// Raya (a non-creator) invites Pax; settle until Pax has joined.
|
||||
let particpants = &[&harness.pax().addr()];
|
||||
@ -96,7 +96,7 @@ fn core_client() {
|
||||
harness.saro().send_content(&convo_id, S_M2).unwrap();
|
||||
|
||||
harness.process_until_label("epoch check", |h| {
|
||||
h.raya().check(&convo_id, S_M2) && h.pax().check(&convo_id, S_M2)
|
||||
h.raya().check(&convo_id, S_M2, None) && h.pax().check(&convo_id, S_M2, None)
|
||||
});
|
||||
}
|
||||
|
||||
@ -171,8 +171,8 @@ fn core_client_four_members_two_epochs() {
|
||||
.expect("Saro send");
|
||||
|
||||
harness.process_until_label("all chats converge", |h| {
|
||||
h.raya().check(&convo_id, MSG)
|
||||
&& h.pax().check(&convo_id, MSG)
|
||||
&& h.mira().check(&convo_id, MSG)
|
||||
h.raya().check(&convo_id, MSG, None)
|
||||
&& h.pax().check(&convo_id, MSG, None)
|
||||
&& h.mira().check(&convo_id, MSG, None)
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user