#[cfg(test)]
mod tests {
use std::any::Any;
use std::env;
use std::time::Duration;
use tracing_subscriber::EnvFilter;
use crate::actor::actor::actor_error::ActorError;
use crate::actor::actor::actor_inner_error::ActorInnerError;
use crate::actor::actor::continuer::Continuer;
use crate::actor::actor::props::Props;
use crate::actor::actor_system::ActorSystem;
use crate::actor::auto_respond::AutoRespond;
use crate::actor::context::{BasePart, InfoPart, MessagePart, SenderPart, SpawnerPart};
use crate::actor::message::message::Message;
use crate::actor::message::message_handle::MessageHandle;
use crate::actor::message::response::ResponseHandle;
use crate::actor::message::touched::Touched;
#[tokio::test]
async fn test_actor_continue_future_in_actor() {
let _ = env::set_var("RUST_LOG", "debug");
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();
let system = ActorSystem::new().await;
let mut root_context = system.get_root_context().await;
let pid = root_context
.spawn(
Props::from_actor_receiver(move |ctx| async move {
if let Some(msg) = ctx.get_message_handle().await.to_typed::<String>() {
let self_pid = ctx.get_self().await;
if msg == "request" {
ctx.respond(ResponseHandle::new("done".to_string())).await;
Ok(())
} else if msg == "start" {
let future = ctx
.request_future(
self_pid,
MessageHandle::new("request".to_string()),
Duration::from_secs(5),
)
.await;
let cloned_ctx = ctx.clone();
ctx
.reenter_after(
future,
Continuer::new(move |msg, _| {
let cloned_ctx = cloned_ctx.clone();
let cloned_msg = msg.clone().unwrap().to_typed::<String>().unwrap().clone();
async move {
cloned_ctx.respond(ResponseHandle::new(cloned_msg)).await;
}
}),
)
.await;
Ok(())
} else {
Err(ActorError::ReceiveError(ActorInnerError::new(format!(
"unknown message: msg = {}",
msg
))))
}
} else {
Ok(())
}
})
.await,
)
.await;
let res = root_context
.request_future(pid, MessageHandle::new("start".to_string()), Duration::from_secs(10))
.await
.result()
.await
.unwrap();
tracing::debug!("res = {:?}", res);
let response = res.to_typed::<String>().unwrap().clone();
assert_eq!(response, "done".to_string());
}
#[derive(Debug, Clone)]
struct DummyAutoRespond {}
impl Message for DummyAutoRespond {
fn eq_message(&self, other: &dyn Message) -> bool {
other.as_any().is::<DummyAutoRespond>()
}
fn as_any(&self) -> &(dyn Any + Send + Sync + 'static) {
self
}
}
#[tokio::test]
async fn test_actor_context_auto_respond_message() {
let _ = env::set_var("RUST_LOG", "debug");
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();
let system = ActorSystem::new().await;
let mut root_context = system.get_root_context().await;
let actor_receiver = move |_| async move { Ok(()) };
let pid = root_context
.spawn(Props::from_actor_receiver(actor_receiver).await)
.await;
let result = root_context
.request_future(
pid,
MessageHandle::new(AutoRespond::new(move |_| async move {
ResponseHandle::new(MessageHandle::new(DummyAutoRespond {}))
})),
Duration::from_secs(1),
)
.await
.result()
.await
.unwrap();
assert!(result.as_any().is::<DummyAutoRespond>());
}
#[tokio::test]
async fn test_actor_context_auto_respond_touched_message() {
let _ = env::set_var("RUST_LOG", "debug");
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();
let system = ActorSystem::new().await;
let mut root_context = system.get_root_context().await;
let actor_receiver = move |_| async move { Ok(()) };
let pid = root_context
.spawn(Props::from_actor_receiver(actor_receiver).await)
.await;
let result = root_context
.request_future(
pid.clone(),
MessageHandle::new(AutoRespond::new(move |ctx| async move {
ResponseHandle::new(MessageHandle::new(Touched {
who: Some(ctx.get_self().await.inner_pid.clone()),
}))
})),
Duration::from_secs(1),
)
.await
.result()
.await
.unwrap();
let result2 = result.to_typed::<Touched>();
assert!(result2.is_some());
assert_eq!(result2.unwrap().who.unwrap(), pid.inner_pid);
}
}