actr_framework/
test_support.rs

1//! Test helpers for actr-framework
2//!
3//! Currently provides a simple `DummyContext` implementation of the `Context` trait
4//! for unit tests that need a context but do not exercise transport logic.
5
6use crate::{Context, Dest, MediaSample};
7use actr_protocol::{ActorResult, ActrError, ActrId, ActrType, ProtocolError, RpcRequest};
8use async_trait::async_trait;
9use futures_util::future::BoxFuture;
10
11/// Minimal `Context` implementation for tests.
12#[derive(Clone, Debug)]
13pub struct DummyContext {
14    self_id: ActrId,
15    caller_id: Option<ActrId>,
16    request_id: String,
17}
18
19impl DummyContext {
20    /// Create a new dummy context with random request id.
21    pub fn new(self_id: ActrId) -> Self {
22        Self {
23            self_id,
24            caller_id: None,
25            request_id: uuid::Uuid::new_v4().to_string(),
26        }
27    }
28
29    /// Set caller id (useful for tests that verify propagation).
30    pub fn with_caller_id(mut self, caller_id: Option<ActrId>) -> Self {
31        self.caller_id = caller_id;
32        self
33    }
34
35    /// Override request id for deterministic testing.
36    pub fn with_request_id(mut self, request_id: impl Into<String>) -> Self {
37        self.request_id = request_id.into();
38        self
39    }
40
41    fn not_implemented(feature: &str) -> ProtocolError {
42        ProtocolError::Actr(ActrError::NotImplemented {
43            feature: feature.to_string(),
44        })
45    }
46}
47
48#[async_trait]
49impl Context for DummyContext {
50    fn self_id(&self) -> &ActrId {
51        &self.self_id
52    }
53
54    fn caller_id(&self) -> Option<&ActrId> {
55        self.caller_id.as_ref()
56    }
57
58    fn request_id(&self) -> &str {
59        &self.request_id
60    }
61
62    async fn call<R: RpcRequest>(&self, _target: &Dest, _request: R) -> ActorResult<R::Response> {
63        Err(Self::not_implemented("DummyContext::call"))
64    }
65
66    async fn tell<R: RpcRequest>(&self, _target: &Dest, _message: R) -> ActorResult<()> {
67        Err(Self::not_implemented("DummyContext::tell"))
68    }
69
70    async fn register_stream<F>(&self, _stream_id: String, _callback: F) -> ActorResult<()>
71    where
72        F: Fn(actr_protocol::DataStream, ActrId) -> BoxFuture<'static, ActorResult<()>>
73            + Send
74            + Sync
75            + 'static,
76    {
77        Ok(())
78    }
79
80    async fn unregister_stream(&self, _stream_id: &str) -> ActorResult<()> {
81        Ok(())
82    }
83
84    async fn send_data_stream(
85        &self,
86        _target: &Dest,
87        _chunk: actr_protocol::DataStream,
88    ) -> ActorResult<()> {
89        Err(Self::not_implemented("DummyContext::send_data_stream"))
90    }
91
92    async fn discover_route_candidate(&self, _target_type: &ActrType) -> ActorResult<ActrId> {
93        Err(Self::not_implemented(
94            "DummyContext::discover_route_candidate",
95        ))
96    }
97
98    async fn register_media_track<F>(&self, _track_id: String, _callback: F) -> ActorResult<()>
99    where
100        F: Fn(MediaSample, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static,
101    {
102        Ok(())
103    }
104
105    async fn unregister_media_track(&self, _track_id: &str) -> ActorResult<()> {
106        Ok(())
107    }
108
109    async fn send_media_sample(
110        &self,
111        _target: &Dest,
112        _track_id: &str,
113        _sample: MediaSample,
114    ) -> ActorResult<()> {
115        Err(Self::not_implemented("DummyContext::send_media_sample"))
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[tokio::test]
124    async fn dummy_context_exposes_ids() {
125        let id = ActrId::default();
126        let ctx = DummyContext::new(id.clone()).with_request_id("r1");
127
128        assert_eq!(ctx.self_id(), &id);
129        assert_eq!(ctx.request_id(), "r1");
130    }
131}