use coerce::actor::context::ActorContext; use coerce::actor::message::{Envelope, EnvelopeType, Handler, Message, MessageWrapErr}; use coerce::actor::system::ActorSystem; use coerce::actor::{Actor, IntoActor, Receiver}; use futures::FutureExt; use tokio::sync::mpsc::{channel, Sender}; use util::*; pub mod util; #[macro_use] extern crate serde; #[macro_use] extern crate async_trait; #[tokio::test] pub async fn test_actor_req_res() { let actor_ref = ActorSystem::new() .new_anon_actor(TestActor::new()) .await .unwrap(); let response = actor_ref.send(GetStatusRequest).await; assert_eq!(response, Ok(GetStatusResponse::None)); } #[tokio::test] pub async fn test_actor_req_res_multiple_actors() { let ctx = ActorSystem::new(); let test_ref = ctx.new_anon_actor(TestActor::new()).await.unwrap(); let echo_ref = ctx.new_anon_actor(EchoActor::new()).await.unwrap(); let test_res = test_ref.send(GetCounterRequest()).await; let echo_res = echo_ref.send(GetCounterRequest()).await; assert_eq!(test_res, Ok(42)); assert_eq!(echo_res, Ok(42)); } #[tokio::test] pub async fn test_actor_req_res_mutation() { let actor_ref = ActorSystem::new() .new_anon_actor(TestActor::new()) .await .unwrap(); let initial_status = actor_ref.send(GetStatusRequest).await; let _ = actor_ref .send(SetStatusRequest { status: TestActorStatus::Active, }) .await; let current_status = actor_ref.send(GetStatusRequest).await; let _ = actor_ref .send(SetStatusRequest { status: TestActorStatus::Inactive, }) .await; let inactive_status = actor_ref.send(GetStatusRequest).await; assert_eq!(initial_status, Ok(GetStatusResponse::None)); assert_eq!( inactive_status, Ok(GetStatusResponse::Ok(TestActorStatus::Inactive)) ); assert_eq!( current_status, Ok(GetStatusResponse::Ok(TestActorStatus::Active)) ); } #[tokio::test] pub async fn test_actor_exec_mutation() { let actor_ref = ActorSystem::new() .new_anon_actor(TestActor::new()) .await .unwrap(); let initial_status = actor_ref.send(GetStatusRequest).await; actor_ref .exec(|mut actor| { actor.status = Some(TestActorStatus::Active); }) .await .expect("exec"); let current_status = actor_ref.send(GetStatusRequest).await; assert_eq!(initial_status, Ok(GetStatusResponse::None)); assert_eq!( current_status, Ok(GetStatusResponse::Ok(TestActorStatus::Active)) ); } #[tokio::test] pub async fn test_actor_exec_chain_mutation() { let actor_ref = ActorSystem::new() .new_anon_actor(TestActor::new()) .await .unwrap(); let _a = actor_ref .exec(|mut actor| { actor.counter = 1; }) .await; let _ = actor_ref.exec(|mut actor| actor.counter = 2).await; let counter = actor_ref.exec(|actor| actor.counter).await; assert_eq!(counter, Ok(2)); } #[tokio::test] pub async fn test_actor_notify() { let actor_ref = ActorSystem::new() .new_anon_actor(TestActor::new()) .await .unwrap(); for i in 1..=25_i32 { let _ = actor_ref.notify_exec(move |mut actor| actor.counter = i); } let counter = actor_ref.exec(|actor| actor.counter).await; assert_eq!(counter, Ok(25)); } struct NewActor; struct OtherActor; struct ReportingActor { tx: Sender, } impl Actor for NewActor {} impl Actor for OtherActor {} impl Actor for ReportingActor {} #[async_trait] impl Handler for NewActor { async fn handle( &mut self, _message: GetStatusRequest, _ctx: &mut ActorContext, ) -> ::Result { GetStatusResponse::Ok(TestActorStatus::Active) } } #[async_trait] impl Handler for OtherActor { async fn handle( &mut self, _message: GetStatusRequest, _ctx: &mut ActorContext, ) -> ::Result { GetStatusResponse::Ok(TestActorStatus::Active) } } #[async_trait] impl Handler for ReportingActor { async fn handle( &mut self, message: GetStatusRequest, _ctx: &mut ActorContext, ) -> ::Result { let _ = self.tx.send(message).await; GetStatusResponse::Ok(TestActorStatus::Active) } } #[tokio::test] pub async fn test_actor_receiver() { let sys = ActorSystem::new(); let actor_a = NewActor .into_actor::(None, &sys) .await .expect("NewActor"); let actor_b = OtherActor .into_actor::(None, &sys) .await .expect("OtherActor"); let mut receivers: Vec> = vec![actor_a.into(), actor_b.into()]; let results = futures::future::join_all(receivers.iter_mut().map(|r| r.send(GetStatusRequest))) .await .into_iter() .map(|s| s.unwrap()) .collect::>(); assert_eq!( results, vec![ GetStatusResponse::Ok(TestActorStatus::Active), GetStatusResponse::Ok(TestActorStatus::Active) ] ) } #[tokio::test] pub async fn test_actor_receiver_clone() { let sys = ActorSystem::new(); let actor_a = NewActor .into_actor::(None, &sys) .await .expect("NewActor"); let actor_b = NewActor .into_actor::(None, &sys) .await .expect("NewActor"); let mut receivers: Vec> = vec![actor_a.into(), actor_b.into()]; let mut results = vec![]; for receiver in receivers.iter_mut() { let receiver_clone = receiver.clone(); let result = tokio::spawn(async move { receiver_clone.send(GetStatusRequest).await.unwrap() }); results.push(result); } let results = futures::future::join_all(results) .await .into_iter() .map(|s| s.unwrap()) .collect::>(); assert_eq!( results, vec![ GetStatusResponse::Ok(TestActorStatus::Active), GetStatusResponse::Ok(TestActorStatus::Active) ] ) } #[tokio::test] pub async fn test_actor_receiver_notify() { let sys = ActorSystem::new(); let (tx, mut rx) = channel(1); let actor = ReportingActor { tx } .into_actor::(None, &sys) .await .expect("ReportingActor"); let receiver: Receiver = actor.into(); receiver.notify(GetStatusRequest).unwrap(); let result = rx.recv().await.unwrap(); assert_eq!(result, GetStatusRequest); } #[derive(coerce_macros::JsonMessage, Serialize, Deserialize)] #[result("()")] struct MessageOne {} struct NonSerializableMessage {} impl Message for NonSerializableMessage { type Result = (); } #[tokio::test] pub async fn test_messages_into_remote_envelope() { let message = MessageOne {}; let non_serializable_message = NonSerializableMessage {}; let serializable_message = message.into_envelope(EnvelopeType::Remote); let non_serializable_envelope = non_serializable_message.into_envelope(EnvelopeType::Remote); let serialized_bytes = match serializable_message { Ok(Envelope::Remote(bytes)) => Some(bytes), _ => None, }; assert!(serialized_bytes.is_some()); assert!(non_serializable_envelope.is_err()); assert_eq!( non_serializable_envelope.err(), Some(MessageWrapErr::NotTransmittable) ); }