litep2p/transport/
dummy.rs

1// Copyright 2023 litep2p developers
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21//! Dummy transport.
22
23use crate::{
24    transport::{Transport, TransportEvent},
25    types::ConnectionId,
26};
27
28use futures::Stream;
29use multiaddr::Multiaddr;
30
31use std::{
32    collections::VecDeque,
33    pin::Pin,
34    task::{Context, Poll},
35};
36
37/// Dummy transport.
38pub(crate) struct DummyTransport {
39    /// Events.
40    events: VecDeque<TransportEvent>,
41}
42
43impl DummyTransport {
44    /// Create new [`DummyTransport`].
45    #[cfg(test)]
46    pub(crate) fn new() -> Self {
47        Self {
48            events: VecDeque::new(),
49        }
50    }
51
52    /// Inject event into `DummyTransport`.
53    #[cfg(test)]
54    pub(crate) fn inject_event(&mut self, event: TransportEvent) {
55        self.events.push_back(event);
56    }
57}
58
59impl Stream for DummyTransport {
60    type Item = TransportEvent;
61
62    fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
63        if self.events.is_empty() {
64            return Poll::Pending;
65        }
66
67        Poll::Ready(self.events.pop_front())
68    }
69}
70
71impl Transport for DummyTransport {
72    fn dial(&mut self, _: ConnectionId, _: Multiaddr) -> crate::Result<()> {
73        Ok(())
74    }
75
76    fn accept(&mut self, _: ConnectionId) -> crate::Result<()> {
77        Ok(())
78    }
79
80    fn accept_pending(&mut self, _connection_id: ConnectionId) -> crate::Result<()> {
81        Ok(())
82    }
83
84    fn reject_pending(&mut self, _connection_id: ConnectionId) -> crate::Result<()> {
85        Ok(())
86    }
87
88    fn reject(&mut self, _: ConnectionId) -> crate::Result<()> {
89        Ok(())
90    }
91
92    fn open(&mut self, _: ConnectionId, _: Vec<Multiaddr>) -> crate::Result<()> {
93        Ok(())
94    }
95
96    fn negotiate(&mut self, _: ConnectionId) -> crate::Result<()> {
97        Ok(())
98    }
99
100    /// Cancel opening connections.
101    fn cancel(&mut self, _: ConnectionId) {}
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107    use crate::{error::DialError, transport::Endpoint, PeerId};
108    use futures::StreamExt;
109
110    #[tokio::test]
111    async fn pending_event() {
112        let mut transport = DummyTransport::new();
113
114        transport.inject_event(TransportEvent::DialFailure {
115            connection_id: ConnectionId::from(1338usize),
116            address: Multiaddr::empty(),
117            error: DialError::Timeout,
118        });
119
120        let peer = PeerId::random();
121        let endpoint = Endpoint::listener(Multiaddr::empty(), ConnectionId::from(1337usize));
122
123        transport.inject_event(TransportEvent::ConnectionEstablished {
124            peer,
125            endpoint: endpoint.clone(),
126        });
127
128        match transport.next().await.unwrap() {
129            TransportEvent::DialFailure {
130                connection_id,
131                address,
132                ..
133            } => {
134                assert_eq!(connection_id, ConnectionId::from(1338usize));
135                assert_eq!(address, Multiaddr::empty());
136            }
137            _ => panic!("invalid event"),
138        }
139
140        match transport.next().await.unwrap() {
141            TransportEvent::ConnectionEstablished {
142                peer: event_peer,
143                endpoint: event_endpoint,
144            } => {
145                assert_eq!(peer, event_peer);
146                assert_eq!(endpoint, event_endpoint);
147            }
148            _ => panic!("invalid event"),
149        }
150
151        futures::future::poll_fn(|cx| match transport.poll_next_unpin(cx) {
152            Poll::Pending => Poll::Ready(()),
153            _ => panic!("invalid event"),
154        })
155        .await;
156    }
157
158    #[test]
159    fn dummy_handle_connection_states() {
160        let mut transport = DummyTransport::new();
161
162        assert!(transport.reject(ConnectionId::new()).is_ok());
163        assert!(transport.open(ConnectionId::new(), Vec::new()).is_ok());
164        assert!(transport.negotiate(ConnectionId::new()).is_ok());
165        transport.cancel(ConnectionId::new());
166    }
167}