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    trace_id: String,
17    request_id: String,
18}
19
20impl DummyContext {
21    /// Create a new dummy context with random trace/request ids.
22    pub fn new(self_id: ActrId) -> Self {
23        Self {
24            self_id,
25            caller_id: None,
26            trace_id: uuid::Uuid::new_v4().to_string(),
27            request_id: uuid::Uuid::new_v4().to_string(),
28        }
29    }
30
31    /// Set caller id (useful for tests that verify propagation).
32    pub fn with_caller_id(mut self, caller_id: Option<ActrId>) -> Self {
33        self.caller_id = caller_id;
34        self
35    }
36
37    /// Override trace id for deterministic testing.
38    pub fn with_trace_id(mut self, trace_id: impl Into<String>) -> Self {
39        self.trace_id = trace_id.into();
40        self
41    }
42
43    /// Override request id for deterministic testing.
44    pub fn with_request_id(mut self, request_id: impl Into<String>) -> Self {
45        self.request_id = request_id.into();
46        self
47    }
48
49    fn not_implemented(feature: &str) -> ProtocolError {
50        ProtocolError::Actr(ActrError::NotImplemented {
51            feature: feature.to_string(),
52        })
53    }
54}
55
56#[async_trait]
57impl Context for DummyContext {
58    fn self_id(&self) -> &ActrId {
59        &self.self_id
60    }
61
62    fn caller_id(&self) -> Option<&ActrId> {
63        self.caller_id.as_ref()
64    }
65
66    fn trace_id(&self) -> &str {
67        &self.trace_id
68    }
69
70    fn request_id(&self) -> &str {
71        &self.request_id
72    }
73
74    async fn call<R: RpcRequest>(&self, _target: &Dest, _request: R) -> ActorResult<R::Response> {
75        Err(Self::not_implemented("DummyContext::call"))
76    }
77
78    async fn tell<R: RpcRequest>(&self, _target: &Dest, _message: R) -> ActorResult<()> {
79        Err(Self::not_implemented("DummyContext::tell"))
80    }
81
82    async fn register_stream<F>(&self, _stream_id: String, _callback: F) -> ActorResult<()>
83    where
84        F: Fn(actr_protocol::DataStream, ActrId) -> BoxFuture<'static, ActorResult<()>>
85            + Send
86            + Sync
87            + 'static,
88    {
89        Ok(())
90    }
91
92    async fn unregister_stream(&self, _stream_id: &str) -> ActorResult<()> {
93        Ok(())
94    }
95
96    async fn send_data_stream(
97        &self,
98        _target: &Dest,
99        _chunk: actr_protocol::DataStream,
100    ) -> ActorResult<()> {
101        Err(Self::not_implemented("DummyContext::send_data_stream"))
102    }
103
104    async fn discover_route_candidate(&self, _target_type: &ActrType) -> ActorResult<ActrId> {
105        Err(Self::not_implemented(
106            "DummyContext::discover_route_candidate",
107        ))
108    }
109
110    async fn register_media_track<F>(&self, _track_id: String, _callback: F) -> ActorResult<()>
111    where
112        F: Fn(MediaSample, ActrId) -> BoxFuture<'static, ActorResult<()>> + Send + Sync + 'static,
113    {
114        Ok(())
115    }
116
117    async fn unregister_media_track(&self, _track_id: &str) -> ActorResult<()> {
118        Ok(())
119    }
120
121    async fn send_media_sample(
122        &self,
123        _target: &Dest,
124        _track_id: &str,
125        _sample: MediaSample,
126    ) -> ActorResult<()> {
127        Err(Self::not_implemented("DummyContext::send_media_sample"))
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134
135    #[tokio::test]
136    async fn dummy_context_exposes_ids() {
137        let id = ActrId::default();
138        let ctx = DummyContext::new(id.clone())
139            .with_trace_id("t1")
140            .with_request_id("r1");
141
142        assert_eq!(ctx.self_id(), &id);
143        assert_eq!(ctx.trace_id(), "t1");
144        assert_eq!(ctx.request_id(), "r1");
145    }
146}