use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use futures::future::BoxFuture;
use futures::stream::FuturesUnordered;
use mm1_address::address::Address;
use mm1_address::pool::Lease as AddressLease;
use mm1_address::subnet::NetAddress;
use tokio::sync::{Mutex, Notify, mpsc};
mod actor_fn;
mod context;
pub mod event;
pub mod query;
mod runtime;
#[derive(Debug, thiserror::Error)]
pub enum RuntimeError {
#[error("no actor: {}", _0)]
NoActor(Address),
#[error("duplicate: {}", _0)]
Duplicate(Address),
}
#[derive(Debug, Clone)]
pub struct TestRuntime<R> {
queries_tx: mpsc::UnboundedSender<Query<R>>,
shared: Arc<Mutex<RuntimeShared<R>>>,
}
#[derive(derive_more::Debug)]
pub struct Event<R, K> {
#[debug(skip)]
runtime: Arc<Mutex<RuntimeShared<R>>>,
pub kind: K,
}
#[derive(Debug)]
pub enum EventKind<R> {
Done(ActorTaskOutcome),
Query(Query<R>),
}
#[derive(derive_more::Debug)]
pub struct TestContext<R> {
task_key: TaskKey,
queries_tx: mpsc::UnboundedSender<Query<R>>,
address_lease: Option<AddressLease>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TaskKey {
pub actor: Address,
pub context: Address,
}
#[derive(Debug, derive_more::From)]
pub enum Query<R> {
InitDone(query::InitDone),
Spawn(query::Spawn<R>),
Start(query::Start<R>),
Recv(query::Recv),
RecvClose(query::RecvClose),
Fork(query::Fork<R>),
ForkRun(query::ForkRun),
Quit(query::Quit),
Tell(query::Tell),
Watch(query::Watch),
Unwatch(query::Unwatch),
Link(query::Link),
Unlink(query::Unlink),
SetTrapExit(query::SetTrapExit),
Exit(query::Exit),
Kill(query::Kill),
BindNetAddress(query::Bind<NetAddress>),
}
#[derive(derive_more::Debug)]
struct RuntimeShared<R> {
queries_rx: mpsc::UnboundedReceiver<Query<R>>,
tasks: FuturesUnordered<BoxFuture<'static, ActorTaskOutcome>>,
entries: HashMap<Address, ActorEntry>,
}
#[derive(derive_more::Debug)]
struct ActorEntry {
forks: HashSet<Address>,
#[debug(skip)]
actor_canceled: Arc<Notify>,
#[debug(skip)]
actor_done: Arc<Notify>,
}
#[derive(Debug)]
pub enum ActorTaskOutcome {
Main(MainActorOutcome),
Fork(ForkTaskOutcome),
}
#[derive(Debug)]
pub struct MainActorOutcome {
pub address: Address,
pub address_lease: Option<AddressLease>,
}
#[derive(Debug)]
pub struct ForkTaskOutcome {
pub task_key: TaskKey,
pub address_lease: Option<AddressLease>,
}