util.rs
1 //! Internal utilities for `tor_rtmock` 2 3 use derive_deftly::define_derive_deftly; 4 use futures::channel::mpsc; 5 6 define_derive_deftly! { 7 /// Implements `Runtime` for a struct made of multiple sub-providers 8 /// 9 /// The type must be a struct containing 10 /// field(s) which implement `SleepProvider`, `NetProvider`, etc. 11 /// 12 /// The corresponding fields must be decorated with: 13 /// 14 /// * `#[deftly(mock(task))]` to indicate the field implementing `Spawn + BlockOn` 15 /// * `#[deftly(mock(net))]` to indicate the field implementing `NetProvider` 16 /// * `#[deftly(mock(sleep))]` to indicate the field implementing `SleepProvider` 17 /// and `CoarseTimeProvider`. 18 // This could perhaps be further reduced: 19 // ambassador might be able to remove most of the body (although does it do async well?) 20 SomeMockRuntime for struct, expect items: 21 22 $( 23 ${when fmeta(mock(task))} 24 25 impl <$tgens> Spawn for $ttype { 26 fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { 27 self.$fname.spawn_obj(future) 28 } 29 } 30 31 impl <$tgens> SpawnBlocking for $ttype { 32 type Handle<T: Send + 'static> = <$ftype as SpawnBlocking>::Handle<T>; 33 34 fn spawn_blocking<F, T>(&self, f: F) -> <$ftype as SpawnBlocking>::Handle<T> 35 where 36 F: FnOnce() -> T + Send + 'static, 37 T: Send + 'static { 38 self.$fname.spawn_blocking(f) 39 } 40 } 41 42 impl <$tgens> BlockOn for $ttype { 43 fn block_on<F: Future>(&self, future: F) -> F::Output { 44 self.$fname.block_on(future) 45 } 46 } 47 48 ) 49 $( 50 ${when fmeta(mock(net))} 51 52 #[async_trait] 53 impl <$tgens> NetStreamProvider for $ttype { 54 type Stream = <$ftype as NetStreamProvider>::Stream; 55 type Listener = <$ftype as NetStreamProvider>::Listener; 56 57 async fn connect(&self, addr: &SocketAddr) -> IoResult<Self::Stream> { 58 self.$fname.connect(addr).await 59 } 60 async fn listen(&self, addr: &SocketAddr) -> IoResult<Self::Listener> { 61 self.$fname.listen(addr).await 62 } 63 } 64 65 #[async_trait] 66 impl <$tgens> NetStreamProvider<tor_general_addr::unix::SocketAddr> for $ttype { 67 type Stream = FakeStream; 68 type Listener = FakeListener<tor_general_addr::unix::SocketAddr>; 69 70 async fn connect(&self, _addr: &tor_general_addr::unix::SocketAddr) -> IoResult<Self::Stream> { 71 Err(tor_general_addr::unix::NoUnixAddressSupport::default().into()) 72 } 73 async fn listen(&self, _addr: &tor_general_addr::unix::SocketAddr) -> IoResult<Self::Listener> { 74 Err(tor_general_addr::unix::NoUnixAddressSupport::default().into()) 75 } 76 } 77 78 impl <$tgens> TlsProvider<<$ftype as NetStreamProvider>::Stream> for $ttype { 79 type Connector = <$ftype as TlsProvider< 80 <$ftype as NetStreamProvider>::Stream 81 >>::Connector; 82 type TlsStream = <$ftype as TlsProvider< 83 <$ftype as NetStreamProvider>::Stream 84 >>::TlsStream; 85 fn tls_connector(&self) -> Self::Connector { 86 self.$fname.tls_connector() 87 } 88 fn supports_keying_material_export(&self) -> bool { 89 self.$fname.supports_keying_material_export() 90 } 91 } 92 93 #[async_trait] 94 impl <$tgens> UdpProvider for $ttype { 95 type UdpSocket = <$ftype as UdpProvider>::UdpSocket; 96 97 #[inline] 98 async fn bind(&self, addr: &SocketAddr) -> IoResult<Self::UdpSocket> { 99 self.$fname.bind(addr).await 100 } 101 } 102 103 ) 104 $( 105 ${when fmeta(mock(sleep))} 106 107 impl <$tgens> SleepProvider for $ttype { 108 type SleepFuture = <$ftype as SleepProvider>::SleepFuture; 109 110 fn sleep(&self, dur: Duration) -> Self::SleepFuture { 111 self.$fname.sleep(dur) 112 } 113 fn now(&self) -> Instant { 114 self.$fname.now() 115 } 116 fn wallclock(&self) -> SystemTime { 117 self.$fname.wallclock() 118 } 119 fn block_advance<T: Into<String>>(&self, reason: T) { 120 self.$fname.block_advance(reason); 121 } 122 fn release_advance<T: Into<String>>(&self, reason: T) { 123 self.$fname.release_advance(reason); 124 } 125 fn allow_one_advance(&self, dur: Duration) { 126 self.$fname.allow_one_advance(dur); 127 } 128 } 129 130 impl <$tgens> CoarseTimeProvider for $ttype { 131 fn now_coarse(&self) -> CoarseInstant { 132 self.$fname.now_coarse() 133 } 134 } 135 136 ) 137 138 // TODO this wants to be assert_impl but it fails at generics 139 const _: fn() = || { 140 fn x(_: impl Runtime) { } 141 fn check_impl_runtime<$tgens>(t: $ttype) { x(t) } 142 }; 143 } 144 145 /// Prelude that must be imported to derive 146 /// [`SomeMockRuntime`](derive_deftly_template_SomeMockRuntime) 147 // 148 // This could have been part of the expansion of `impl_runtime!`, 149 // but it seems rather too exciting for a macro to import things as a side gig. 150 // 151 // Arguably this ought to be an internal crate::prelude instead. 152 // But crate-internal preludes are controversial within the Arti team. -Diziet 153 // 154 // For macro visibility reasons, this must come *lexically after* the macro, 155 // to allow it to refer to the macro in the doc comment. 156 pub(crate) mod impl_runtime_prelude { 157 pub(crate) use async_trait::async_trait; 158 pub(crate) use derive_deftly::Deftly; 159 pub(crate) use futures::task::{FutureObj, Spawn, SpawnError}; 160 pub(crate) use futures::Future; 161 pub(crate) use std::io::Result as IoResult; 162 pub(crate) use std::net::SocketAddr; 163 pub(crate) use std::time::{Duration, Instant, SystemTime}; 164 pub(crate) use tor_rtcompat::{ 165 unimpl::FakeListener, unimpl::FakeStream, BlockOn, CoarseInstant, CoarseTimeProvider, 166 NetStreamProvider, Runtime, SleepProvider, SpawnBlocking, TlsProvider, UdpProvider, 167 }; 168 } 169 170 /// Wrapper for `futures::channel::mpsc::channel` that embodies the `#[allow]` 171 /// 172 /// We don't care about mq tracking in this test crate. 173 /// 174 /// Exactly like `tor_async_utils::mpsc_channel_no_memquota`, 175 /// but we can't use that here for crate hierarchy reasons. 176 #[allow(clippy::disallowed_methods)] 177 pub(crate) fn mpsc_channel<T>(buffer: usize) -> (mpsc::Sender<T>, mpsc::Receiver<T>) { 178 mpsc::channel(buffer) 179 }