This commit is contained in:
osmaczko 2026-03-26 21:47:00 +01:00
parent 6db3363aad
commit 5189bcf872
No known key found for this signature in database
GPG Key ID: 6A385380FD275B44
7 changed files with 67 additions and 28 deletions

View File

@ -1,24 +1,6 @@
use std::collections::VecDeque;
use libchat::AddressedEnvelope;
pub trait DeliveryService {
type Error: std::fmt::Debug;
fn deliver(&mut self, envelope: AddressedEnvelope) -> Result<(), Self::Error>;
}
/// In-memory delivery for tests. Envelopes are pushed to `inbox`; tests pop
/// them and feed bytes to the peer's `receive()`.
#[derive(Default)]
pub struct InMemoryDelivery {
pub inbox: VecDeque<Vec<u8>>,
}
impl DeliveryService for InMemoryDelivery {
type Error = std::convert::Infallible;
fn deliver(&mut self, envelope: AddressedEnvelope) -> Result<(), Self::Error> {
self.inbox.push_back(envelope.data);
Ok(())
}
}

View File

@ -1,10 +1,13 @@
mod client;
mod delivery;
mod errors;
mod platform;
pub mod platforms;
pub use client::ChatClient;
pub use delivery::{DeliveryService, InMemoryDelivery};
pub use delivery::DeliveryService;
pub use errors::ClientError;
pub use platform::Platform;
// Re-export types callers need to interact with ChatClient
pub use libchat::{ContentData, ConversationIdOwned, StorageConfig};

View File

@ -0,0 +1,8 @@
use crate::{client::ChatClient, delivery::DeliveryService};
pub trait Platform {
type Delivery: DeliveryService;
type Error: std::fmt::Debug;
fn into_client(self, name: impl Into<String>) -> Result<ChatClient<Self::Delivery>, Self::Error>;
}

View File

@ -0,0 +1 @@
pub mod test;

View File

@ -0,0 +1,21 @@
use std::collections::VecDeque;
use libchat::AddressedEnvelope;
use crate::delivery::DeliveryService;
/// Mock delivery for TestPlatform. Envelopes are pushed to `inbox`; tests pop
/// them manually and feed bytes into the peer's `receive()`.
#[derive(Default)]
pub struct MockDelivery {
pub inbox: VecDeque<Vec<u8>>,
}
impl DeliveryService for MockDelivery {
type Error = std::convert::Infallible;
fn deliver(&mut self, envelope: AddressedEnvelope) -> Result<(), Self::Error> {
self.inbox.push_back(envelope.data);
Ok(())
}
}

View File

@ -0,0 +1,21 @@
mod delivery;
pub use delivery::MockDelivery;
use crate::{client::ChatClient, platform::Platform};
/// TestEngine platform: ephemeral identity, in-memory persistence, mock delivery.
///
/// Suitable for unit/integration tests and local experimentation.
/// Maps to the "Platform: TestEngine" box in the architecture diagram.
pub struct TestPlatform;
impl Platform for TestPlatform {
type Delivery = MockDelivery;
type Error = std::convert::Infallible;
fn into_client(self, name: impl Into<String>) -> Result<ChatClient<MockDelivery>, Self::Error> {
// ChatClient::new uses Context::new_with_name → in-memory storage + ephemeral identity
Ok(ChatClient::new(name, MockDelivery::default()))
}
}

View File

@ -1,9 +1,14 @@
use client::{ChatClient, ContentData, ConversationIdOwned, InMemoryDelivery};
use client::platforms::test::{MockDelivery, TestPlatform};
use client::{ChatClient, ContentData, ConversationIdOwned, Platform, StorageConfig};
use std::sync::Arc;
fn new_client(name: &str) -> ChatClient<MockDelivery> {
TestPlatform.into_client(name).unwrap()
}
fn pop_and_receive(
sender: &mut ChatClient<InMemoryDelivery>,
receiver: &mut ChatClient<InMemoryDelivery>,
sender: &mut ChatClient<MockDelivery>,
receiver: &mut ChatClient<MockDelivery>,
) -> Option<ContentData> {
let raw = sender.delivery_mut().inbox.pop_front().expect("expected envelope");
receiver.receive(&raw).expect("receive failed")
@ -11,8 +16,8 @@ fn pop_and_receive(
#[test]
fn alice_bob_message_exchange() {
let mut alice = ChatClient::new("alice", InMemoryDelivery::default());
let mut bob = ChatClient::new("bob", InMemoryDelivery::default());
let mut alice = new_client("alice");
let mut bob = new_client("bob");
// Exchange intro bundles out-of-band
let bob_bundle = bob.create_intro_bundle().unwrap();
@ -55,17 +60,15 @@ fn alice_bob_message_exchange() {
#[test]
fn open_persistent_client() {
use client::StorageConfig;
let dir = tempfile::tempdir().unwrap();
let db_path = dir.path().join("test.db").to_string_lossy().to_string();
let config = StorageConfig::File(db_path);
let client1 = ChatClient::open("alice", config.clone(), InMemoryDelivery::default()).unwrap();
let client1 = ChatClient::open("alice", config.clone(), MockDelivery::default()).unwrap();
let name1 = client1.installation_name().to_string();
drop(client1);
let client2 = ChatClient::open("alice", config, InMemoryDelivery::default()).unwrap();
let client2 = ChatClient::open("alice", config, MockDelivery::default()).unwrap();
let name2 = client2.installation_name().to_string();
assert_eq!(name1, name2, "installation name should persist across restarts");