4
4
//! This enables simulation of real-world scenarios and makes SteadyState stand out from other solutions
5
5
//! by providing a robust way to test graphs.
6
6
7
+ use crate :: core_tx;
7
8
use std:: any:: Any ;
8
9
use std:: collections:: HashMap ;
9
10
use std:: fmt:: Debug ;
@@ -24,6 +25,8 @@ use crate::channel_builder::{ChannelBacking, InternalReceiver, InternalSender};
24
25
use ringbuf:: traits:: Observer ;
25
26
use crate :: actor_builder:: NodeTxRx ;
26
27
use crate :: commander:: SendOutcome ;
28
+ use crate :: core_rx:: RxCore ;
29
+ use crate :: core_tx:: TxCore ;
27
30
28
31
/// Represents the result of a graph test, which can either be `Ok` with a value of type `K`
29
32
/// or `Err` with a value of type `E`.
@@ -148,12 +151,66 @@ impl SideChannelHub {
148
151
}
149
152
150
153
/// The `SideChannelResponder` struct provides a way to respond to messages from a side channel.
154
+ #[ derive( Clone ) ]
151
155
pub struct SideChannelResponder {
152
156
pub ( crate ) arc : Arc < Mutex < ( SideChannel , Receiver < ( ) > ) > > ,
153
157
pub ( crate ) identity : ActorIdentity ,
154
158
}
155
159
156
160
impl SideChannelResponder {
161
+
162
+ pub async fn simulate_echo < ' a , T : ' static , X : TxCore < MsgIn < ' a > = T > , C : SteadyCommander > ( & self , tx_core : & mut X , cmd : & Arc < Mutex < C > > ) -> bool
163
+ where <X as TxCore >:: MsgOut : std:: marker:: Send , <X as TxCore >:: MsgOut : Sync , <X as core_tx:: TxCore >:: MsgOut : ' static {
164
+ if self . should_apply :: < T > ( ) . await { //we got a message and now confirm we have room to send it
165
+
166
+ if tx_core. shared_wait_vacant_units ( tx_core. one ( ) ) . await {
167
+ //we hold cmd just as long as it takes us to respond.
168
+ let mut cmd_guard = cmd. lock ( ) . await ;
169
+ self . respond_with ( move |message| {
170
+ match cmd_guard. try_send ( tx_core, * message. downcast :: < T > ( ) . expect ( "error casting" ) ) {
171
+ SendOutcome :: Success => { Box :: new ( "ok" . to_string ( ) ) }
172
+ SendOutcome :: Blocked ( msg) => { Box :: new ( msg) }
173
+ }
174
+ } ) . await
175
+ } else {
176
+ false
177
+ }
178
+ } else {
179
+ false
180
+ }
181
+ }
182
+
183
+ pub async fn simulate_equals < T : Debug + Eq + ' static , X : RxCore < MsgOut = T > , C : SteadyCommander > ( & self , rx_core : & mut X , cmd : & Arc < Mutex < C > > ) -> bool where <X as RxCore >:: MsgOut : std:: fmt:: Debug {
184
+ if self . should_apply :: < T > ( ) . await { //we have a message and now block until a unit arrives
185
+ if rx_core. shared_wait_avail_units ( 1 ) . await {
186
+ //for testing we hold the cmd lock only while we check equals and respond
187
+ let mut cmd_guard = cmd. lock ( ) . await ;
188
+ self . respond_with ( move |message| {
189
+ // Attempt to downcast to the expected message type
190
+ let msg = * message. downcast :: < T > ( ) . expect ( "error casting" ) ;
191
+ match cmd_guard. try_take ( rx_core) {
192
+ Some ( measured) => {
193
+ if msg. eq ( & measured) {
194
+ Box :: new ( "ok" . to_string ( ) )
195
+ } else {
196
+ let failure = format ! ( "no match {:?} {:?}" , msg, measured) ;
197
+ Box :: new ( failure)
198
+ }
199
+ }
200
+ None => {
201
+ Box :: new ( "no message" . to_string ( ) )
202
+ }
203
+ }
204
+ } ) . await
205
+ } else {
206
+ false
207
+ }
208
+ } else {
209
+ false
210
+ }
211
+ }
212
+
213
+
157
214
/// Creates a new `SideChannelResponder`.
158
215
///
159
216
/// # Arguments
@@ -201,18 +258,15 @@ impl SideChannelResponder {
201
258
///
202
259
/// # Returns
203
260
/// - `bool`: `true` if the operation succeeded; otherwise, `false`.
204
- pub async fn echo_responder < M : ' static + Clone + Debug + Send + Sync , C : SteadyCommander > (
261
+ pub async fn echo_responder < M : ' static + Debug + Send + Sync , C : SteadyCommander > (
205
262
& self ,
206
263
cmd : & mut C ,
207
264
target_tx : & mut Tx < M > ,
208
265
) -> bool {
209
266
if self . should_apply :: < M > ( ) . await {
210
267
if cmd. wait_vacant ( target_tx, 1 ) . await {
211
268
self . respond_with ( move |message| {
212
- // Attempt to downcast to the expected message type
213
- let msg = message. downcast_ref :: < M > ( ) . expect ( "error casting" ) ;
214
- // Try sending the message to the target channel
215
- match cmd. try_send ( target_tx, msg. clone ( ) ) {
269
+ match cmd. try_send ( target_tx, * message. downcast :: < M > ( ) . expect ( "error casting" ) ) {
216
270
SendOutcome :: Success => { Box :: new ( "ok" . to_string ( ) ) }
217
271
SendOutcome :: Blocked ( msg) => { Box :: new ( msg) }
218
272
}
@@ -274,7 +328,7 @@ impl SideChannelResponder {
274
328
///
275
329
/// # Returns
276
330
/// - `bool`: `true` if the operation succeeded; otherwise, `false`.
277
- pub async fn equals_responder < M : ' static + Clone + Debug + Send + Eq , C : SteadyCommander > (
331
+ pub async fn equals_responder < M : ' static + Debug + Send + Eq , C : SteadyCommander > (
278
332
& self ,
279
333
cmd : & mut C ,
280
334
source_rx : & mut Rx < M > ,
@@ -284,7 +338,6 @@ impl SideChannelResponder {
284
338
self . respond_with ( move |message| {
285
339
// Attempt to downcast to the expected message type
286
340
let msg = * message. downcast :: < M > ( ) . expect ( "error casting" ) ;
287
-
288
341
match cmd. try_take ( source_rx) {
289
342
Some ( measured) => {
290
343
if measured. eq ( & msg) {
0 commit comments