1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
//! Macros used with tests /// Creates TestProbe matcher function from the user specified block of code /// /// # Examples /// /// ``` /// matcher!(v => { /// if let Some(m) = v.downcast_ref::<some_actor::SomeMsg>() { /// if m.data > 100 { /// true /// } else { /// false /// } /// } else { /// false /// } /// }); /// ``` #[macro_export] macro_rules! matcher { ($value:ident => $body:expr) => { Box::new(move |$value: Message| { $body }) }; } /// Creates TestProbe matcher function which match specified message type. /// /// # Examples /// /// ``` /// type_matcher!(some_actor::SomeMsg); /// ``` /// #[macro_export] macro_rules! type_matcher { ($t:path) => { Box::new(move |v: Message| { if let Some(_) = v.get().downcast_ref::<$t>() { true } else { false } }) }; } /// Creates TestProbe matcher function which match specified message by match arm. Match arm must be /// specified without guards. /// /// # Examples /// /// ``` /// type_matcher!(some_actor::SomeMsg => some_actor::SomeMsg { data: 100 }); /// /// // Message type => Match arm /// /// ``` /// #[macro_export] macro_rules! pat_matcher { ($t:path => $pat:pat) => { Box::new(move |v: Message| { if let Some(m) = v.get().downcast_ref::<$t>() { match m { $pat => true, _ => false } } else { false } }) }; } /// Creates TestProbe matcher function which match specified message type and if is was success, /// apply specified user function to the result. /// /// # Examples /// /// ``` /// extended_type_matcher!(some_actor::SomeMsg, v => { /// if v.data > 100 { /// true /// } else { /// false /// } /// }); /// /// // Inner function must return bool value /// /// ``` /// #[macro_export] macro_rules! extended_type_matcher { ($t:path , $v:ident => $body:expr) => { Box::new(move |v: Message| { if let Some($v) = v.get().downcast_ref::<$t>() { $body } else { false } }) }; } /// Extract actor object from TestActorRef. This object is immutable and may be used for reversion /// of the internal actor's state. For use this macros, target actor must implement the as_any /// method from the Actor trait. Without satisfying this condition, macros will cause panic. /// /// # Examples /// /// ``` /// in_state! (target, Foo, actor => { /// assert_eq!(actor.data, 599); /// }); /// /// // target - TestActorRef /// // Foo - actor type under actor reference /// ``` /// #[macro_export] macro_rules! in_state { ($r:ident , $t:path, $a:ident => $e:expr) => { { let target_any = $r.as_any(); let sd = target_any.downcast_ref::<Box<TestLocalActorRef>>().unwrap(); let mut actor = sd.actor.lock().unwrap(); let actor = actor.as_any(); let $a = actor.downcast_ref::<$t>().unwrap(); $e; } }; } /// Casts some Message to the specified type and call user function with this value. Macro /// may be used as extractor of data from a messages, because he may return values from itself /// based on the data from a message /// /// # Example /// /// ``` /// // As validator /// cast!(msg, responses::MsgResponse, m => { /// assert_eq!(m.data, 99); /// }); /// /// // As extractor /// let data = cast!(msg, responses::MsgResponse, m => { /// m.data; /// }); /// ``` /// /// # Panic /// /// Macro will case panic, if downcast operation will be failed. /// #[macro_export] macro_rules! cast { ($m:ident , $t:path , $v:ident => $body:expr) => { { let msg = $m.get(); if let Some($v) = msg.downcast_ref::<$t>() { $body } else { panic!("Unable to cast a message"); } } }; }