瀏覽代碼

Add tests for TCP state machine.

whitequark 8 年之前
父節點
當前提交
c2311a3cff
共有 2 個文件被更改,包括 119 次插入1 次删除
  1. 118 0
      src/socket/tcp.rs
  2. 1 1
      src/wire/ip.rs

+ 118 - 0
src/socket/tcp.rs

@@ -334,4 +334,122 @@ mod test {
         assert_eq!(buffer.dequeue(8), b"zho");          // ........
         buffer.enqueue(8).copy_from_slice(b"gefug");    // ...gefug
     }
+
+    const LOCAL_IP:     IpAddress  = IpAddress::v4(10, 0, 0, 1);
+    const REMOTE_IP:    IpAddress  = IpAddress::v4(10, 0, 0, 2);
+    const LOCAL_PORT:   u16        = 80;
+    const REMOTE_PORT:  u16        = 49500;
+    const LOCAL_END:    IpEndpoint = IpEndpoint::new(LOCAL_IP, LOCAL_PORT);
+    const REMOTE_END:   IpEndpoint = IpEndpoint::new(REMOTE_IP, REMOTE_PORT);
+    const LOCAL_SEQ:    i32        = 100;
+    const REMOTE_SEQ:   i32        = !100;
+
+    const SEND_TEMPL: TcpRepr<'static> = TcpRepr {
+        src_port: REMOTE_PORT, dst_port: LOCAL_PORT,
+        control: TcpControl::None,
+        seq_number: 0, ack_number: Some(0),
+        window_len: 256, payload: &[]
+    };
+    const RECV_TEMPL:  TcpRepr<'static> = TcpRepr {
+        src_port: LOCAL_PORT, dst_port: REMOTE_PORT,
+        control: TcpControl::None,
+        seq_number: 0, ack_number: Some(0),
+        window_len: 128, payload: &[]
+    };
+
+    macro_rules! send {
+        ($socket:ident, $repr:expr) => ({
+            let repr = $repr;
+            let mut buffer = vec![0; repr.buffer_len()];
+            let mut packet = TcpPacket::new(&mut buffer).unwrap();
+            repr.emit(&mut packet, &REMOTE_IP, &LOCAL_IP);
+            let result = $socket.collect(&REMOTE_IP, &LOCAL_IP, IpProtocol::Tcp,
+                                         &packet.into_inner()[..]);
+            result.expect("send error")
+        })
+    }
+
+    macro_rules! recv {
+        ($socket:ident, $expected:expr) => ({
+            let result = $socket.dispatch(&mut |src_addr, dst_addr, protocol, payload| {
+                assert_eq!(protocol, IpProtocol::Tcp);
+                assert_eq!(src_addr, &LOCAL_IP);
+                assert_eq!(dst_addr, &REMOTE_IP);
+
+                let mut buffer = vec![0; payload.buffer_len()];
+                payload.emit(src_addr, dst_addr, &mut buffer);
+                let packet = TcpPacket::new(&buffer[..]).unwrap();
+                let repr = TcpRepr::parse(&packet, src_addr, dst_addr).unwrap();
+                assert_eq!(repr, $expected);
+                Ok(())
+            });
+            assert_eq!(result, Ok(()));
+            let result = $socket.dispatch(&mut |_src_addr, _dst_addr, _protocol, _payload| {
+                Ok(())
+            });
+            assert_eq!(result, Err(Error::Exhausted));
+        })
+    }
+
+    fn init_logger() {
+        extern crate log;
+        use std::boxed::Box;
+
+        struct Logger(());
+
+        impl log::Log for Logger {
+            fn enabled(&self, _metadata: &log::LogMetadata) -> bool {
+                true
+            }
+
+            fn log(&self, record: &log::LogRecord) {
+                println!("{}", record.args());
+            }
+        }
+
+        let _ = log::set_logger(|max_level| {
+            max_level.set(log::LogLevelFilter::Trace);
+            Box::new(Logger(()))
+        });
+
+        println!("");
+    }
+
+    fn socket() -> TcpSocket<'static> {
+        init_logger();
+
+        let rx_buffer = SocketBuffer::new(vec![0; 128]);
+        let tx_buffer = SocketBuffer::new(vec![0; 128]);
+        match TcpSocket::new(rx_buffer, tx_buffer) {
+            Socket::Tcp(socket) => socket,
+            _ => unreachable!()
+        }
+    }
+
+    #[test]
+    fn test_handshake() {
+        let mut s = socket();
+        s.listen(IpEndpoint::new(IpAddress::default(), LOCAL_PORT));
+        assert_eq!(s.state(), State::Listen);
+
+        send!(s, TcpRepr {
+            control: TcpControl::Syn,
+            seq_number: LOCAL_SEQ, ack_number: None,
+            ..SEND_TEMPL
+        });
+        assert_eq!(s.state(), State::SynReceived);
+        assert_eq!(s.local_endpoint(), LOCAL_END);
+        assert_eq!(s.remote_endpoint(), REMOTE_END);
+        recv!(s, TcpRepr {
+            control: TcpControl::Syn,
+            seq_number: REMOTE_SEQ, ack_number: Some(LOCAL_SEQ + 1),
+            ..RECV_TEMPL
+        });
+        send!(s, TcpRepr {
+            control: TcpControl::None,
+            seq_number: LOCAL_SEQ + 1, ack_number: Some(REMOTE_SEQ + 1),
+            ..SEND_TEMPL
+        });
+        assert_eq!(s.state(), State::Established);
+    }
 }

+ 1 - 1
src/wire/ip.rs

@@ -87,7 +87,7 @@ impl Endpoint {
     pub const UNSPECIFIED: Endpoint = Endpoint { addr: Address::Unspecified, port: 0 };
 
     /// Create an endpoint address from given address and port.
-    pub fn new(addr: Address, port: u16) -> Endpoint {
+    pub const fn new(addr: Address, port: u16) -> Endpoint {
         Endpoint { addr: addr, port: port }
     }
 }