about summary refs log tree commit diff
path: root/library/std/src/net
diff options
context:
space:
mode:
authorLzu Tao <taolzu@gmail.com>2020-08-27 13:45:01 +0000
committerLzu Tao <taolzu@gmail.com>2020-08-31 02:56:59 +0000
commita4e926daeeaedc9178846711daf1f4cb6ce505fb (patch)
tree0c830f716f6f5ad17736d459f5de9b9199006d54 /library/std/src/net
parentdb6cbfc49ca655739ba8caae43ebd7c77c8a1179 (diff)
downloadrust-a4e926daeeaedc9178846711daf1f4cb6ce505fb.tar.gz
rust-a4e926daeeaedc9178846711daf1f4cb6ce505fb.zip
std: move "mod tests/benches" to separate files
Also doing fmt inplace as requested.
Diffstat (limited to 'library/std/src/net')
-rw-r--r--library/std/src/net/addr.rs236
-rw-r--r--library/std/src/net/addr/tests.rs229
-rw-r--r--library/std/src/net/ip.rs863
-rw-r--r--library/std/src/net/ip/tests.rs811
-rw-r--r--library/std/src/net/parser.rs146
-rw-r--r--library/std/src/net/parser/tests.rs139
-rw-r--r--library/std/src/net/tcp.rs870
-rw-r--r--library/std/src/net/tcp/tests.rs862
-rw-r--r--library/std/src/net/udp.rs380
-rw-r--r--library/std/src/net/udp/tests.rs372
10 files changed, 2430 insertions, 2478 deletions
diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs
index d7d96862b21..1ba243804fe 100644
--- a/library/std/src/net/addr.rs
+++ b/library/std/src/net/addr.rs
@@ -1,3 +1,6 @@
+#[cfg(all(test, not(target_os = "emscripten")))]
+mod tests;
+
 use crate::cmp::Ordering;
 use crate::convert::TryInto;
 use crate::fmt;
@@ -991,236 +994,3 @@ impl ToSocketAddrs for String {
         (&**self).to_socket_addrs()
     }
 }
-
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod tests {
-    use crate::net::test::{sa4, sa6, tsa};
-    use crate::net::*;
-
-    #[test]
-    fn to_socket_addr_ipaddr_u16() {
-        let a = Ipv4Addr::new(77, 88, 21, 11);
-        let p = 12345;
-        let e = SocketAddr::V4(SocketAddrV4::new(a, p));
-        assert_eq!(Ok(vec![e]), tsa((a, p)));
-    }
-
-    #[test]
-    fn to_socket_addr_str_u16() {
-        let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352);
-        assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352)));
-
-        let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53);
-        assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53)));
-
-        let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
-        #[cfg(not(target_env = "sgx"))]
-        assert!(tsa(("localhost", 23924)).unwrap().contains(&a));
-        #[cfg(target_env = "sgx")]
-        let _ = a;
-    }
-
-    #[test]
-    fn to_socket_addr_str() {
-        let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352);
-        assert_eq!(Ok(vec![a]), tsa("77.88.21.11:24352"));
-
-        let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53);
-        assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53"));
-
-        let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
-        #[cfg(not(target_env = "sgx"))]
-        assert!(tsa("localhost:23924").unwrap().contains(&a));
-        #[cfg(target_env = "sgx")]
-        let _ = a;
-    }
-
-    #[test]
-    fn to_socket_addr_string() {
-        let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352);
-        assert_eq!(Ok(vec![a]), tsa(&*format!("{}:{}", "77.88.21.11", "24352")));
-        assert_eq!(Ok(vec![a]), tsa(&format!("{}:{}", "77.88.21.11", "24352")));
-        assert_eq!(Ok(vec![a]), tsa(format!("{}:{}", "77.88.21.11", "24352")));
-
-        let s = format!("{}:{}", "77.88.21.11", "24352");
-        assert_eq!(Ok(vec![a]), tsa(s));
-        // s has been moved into the tsa call
-    }
-
-    #[test]
-    fn bind_udp_socket_bad() {
-        // rust-lang/rust#53957: This is a regression test for a parsing problem
-        // discovered as part of issue rust-lang/rust#23076, where we were
-        // incorrectly parsing invalid input and then that would result in a
-        // successful `UdpSocket` binding when we would expect failure.
-        //
-        // At one time, this test was written as a call to `tsa` with
-        // INPUT_23076. However, that structure yields an unreliable test,
-        // because it ends up passing junk input to the DNS server, and some DNS
-        // servers will respond with `Ok` to such input, with the ip address of
-        // the DNS server itself.
-        //
-        // This form of the test is more robust: even when the DNS server
-        // returns its own address, it is still an error to bind a UDP socket to
-        // a non-local address, and so we still get an error here in that case.
-
-        const INPUT_23076: &'static str = "1200::AB00:1234::2552:7777:1313:34300";
-
-        assert!(crate::net::UdpSocket::bind(INPUT_23076).is_err())
-    }
-
-    #[test]
-    fn set_ip() {
-        fn ip4(low: u8) -> Ipv4Addr {
-            Ipv4Addr::new(77, 88, 21, low)
-        }
-        fn ip6(low: u16) -> Ipv6Addr {
-            Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low)
-        }
-
-        let mut v4 = SocketAddrV4::new(ip4(11), 80);
-        assert_eq!(v4.ip(), &ip4(11));
-        v4.set_ip(ip4(12));
-        assert_eq!(v4.ip(), &ip4(12));
-
-        let mut addr = SocketAddr::V4(v4);
-        assert_eq!(addr.ip(), IpAddr::V4(ip4(12)));
-        addr.set_ip(IpAddr::V4(ip4(13)));
-        assert_eq!(addr.ip(), IpAddr::V4(ip4(13)));
-        addr.set_ip(IpAddr::V6(ip6(14)));
-        assert_eq!(addr.ip(), IpAddr::V6(ip6(14)));
-
-        let mut v6 = SocketAddrV6::new(ip6(1), 80, 0, 0);
-        assert_eq!(v6.ip(), &ip6(1));
-        v6.set_ip(ip6(2));
-        assert_eq!(v6.ip(), &ip6(2));
-
-        let mut addr = SocketAddr::V6(v6);
-        assert_eq!(addr.ip(), IpAddr::V6(ip6(2)));
-        addr.set_ip(IpAddr::V6(ip6(3)));
-        assert_eq!(addr.ip(), IpAddr::V6(ip6(3)));
-        addr.set_ip(IpAddr::V4(ip4(4)));
-        assert_eq!(addr.ip(), IpAddr::V4(ip4(4)));
-    }
-
-    #[test]
-    fn set_port() {
-        let mut v4 = SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80);
-        assert_eq!(v4.port(), 80);
-        v4.set_port(443);
-        assert_eq!(v4.port(), 443);
-
-        let mut addr = SocketAddr::V4(v4);
-        assert_eq!(addr.port(), 443);
-        addr.set_port(8080);
-        assert_eq!(addr.port(), 8080);
-
-        let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 0);
-        assert_eq!(v6.port(), 80);
-        v6.set_port(443);
-        assert_eq!(v6.port(), 443);
-
-        let mut addr = SocketAddr::V6(v6);
-        assert_eq!(addr.port(), 443);
-        addr.set_port(8080);
-        assert_eq!(addr.port(), 8080);
-    }
-
-    #[test]
-    fn set_flowinfo() {
-        let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0);
-        assert_eq!(v6.flowinfo(), 10);
-        v6.set_flowinfo(20);
-        assert_eq!(v6.flowinfo(), 20);
-    }
-
-    #[test]
-    fn set_scope_id() {
-        let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 10);
-        assert_eq!(v6.scope_id(), 10);
-        v6.set_scope_id(20);
-        assert_eq!(v6.scope_id(), 20);
-    }
-
-    #[test]
-    fn is_v4() {
-        let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80));
-        assert!(v4.is_ipv4());
-        assert!(!v4.is_ipv6());
-    }
-
-    #[test]
-    fn is_v6() {
-        let v6 = SocketAddr::V6(SocketAddrV6::new(
-            Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1),
-            80,
-            10,
-            0,
-        ));
-        assert!(!v6.is_ipv4());
-        assert!(v6.is_ipv6());
-    }
-
-    #[test]
-    fn socket_v4_to_str() {
-        let socket = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 8080);
-
-        assert_eq!(format!("{}", socket), "192.168.0.1:8080");
-        assert_eq!(format!("{:<20}", socket), "192.168.0.1:8080    ");
-        assert_eq!(format!("{:>20}", socket), "    192.168.0.1:8080");
-        assert_eq!(format!("{:^20}", socket), "  192.168.0.1:8080  ");
-        assert_eq!(format!("{:.10}", socket), "192.168.0.");
-    }
-
-    #[test]
-    fn socket_v6_to_str() {
-        let socket: SocketAddrV6 = "[2a02:6b8:0:1::1]:53".parse().unwrap();
-
-        assert_eq!(format!("{}", socket), "[2a02:6b8:0:1::1]:53");
-        assert_eq!(format!("{:<24}", socket), "[2a02:6b8:0:1::1]:53    ");
-        assert_eq!(format!("{:>24}", socket), "    [2a02:6b8:0:1::1]:53");
-        assert_eq!(format!("{:^24}", socket), "  [2a02:6b8:0:1::1]:53  ");
-        assert_eq!(format!("{:.15}", socket), "[2a02:6b8:0:1::");
-    }
-
-    #[test]
-    fn compare() {
-        let v4_1 = "224.120.45.1:23456".parse::<SocketAddrV4>().unwrap();
-        let v4_2 = "224.210.103.5:12345".parse::<SocketAddrV4>().unwrap();
-        let v4_3 = "224.210.103.5:23456".parse::<SocketAddrV4>().unwrap();
-        let v6_1 = "[2001:db8:f00::1002]:23456".parse::<SocketAddrV6>().unwrap();
-        let v6_2 = "[2001:db8:f00::2001]:12345".parse::<SocketAddrV6>().unwrap();
-        let v6_3 = "[2001:db8:f00::2001]:23456".parse::<SocketAddrV6>().unwrap();
-
-        // equality
-        assert_eq!(v4_1, v4_1);
-        assert_eq!(v6_1, v6_1);
-        assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1));
-        assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
-        assert!(v4_1 != v4_2);
-        assert!(v6_1 != v6_2);
-
-        // compare different addresses
-        assert!(v4_1 < v4_2);
-        assert!(v6_1 < v6_2);
-        assert!(v4_2 > v4_1);
-        assert!(v6_2 > v6_1);
-
-        // compare the same address with different ports
-        assert!(v4_2 < v4_3);
-        assert!(v6_2 < v6_3);
-        assert!(v4_3 > v4_2);
-        assert!(v6_3 > v6_2);
-
-        // compare different addresses with the same port
-        assert!(v4_1 < v4_3);
-        assert!(v6_1 < v6_3);
-        assert!(v4_3 > v4_1);
-        assert!(v6_3 > v6_1);
-
-        // compare with an inferred right-hand side
-        assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
-        assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());
-        assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap());
-    }
-}
diff --git a/library/std/src/net/addr/tests.rs b/library/std/src/net/addr/tests.rs
new file mode 100644
index 00000000000..cee9087e13b
--- /dev/null
+++ b/library/std/src/net/addr/tests.rs
@@ -0,0 +1,229 @@
+use crate::net::test::{sa4, sa6, tsa};
+use crate::net::*;
+
+#[test]
+fn to_socket_addr_ipaddr_u16() {
+    let a = Ipv4Addr::new(77, 88, 21, 11);
+    let p = 12345;
+    let e = SocketAddr::V4(SocketAddrV4::new(a, p));
+    assert_eq!(Ok(vec![e]), tsa((a, p)));
+}
+
+#[test]
+fn to_socket_addr_str_u16() {
+    let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352);
+    assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352)));
+
+    let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53);
+    assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53)));
+
+    let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+    #[cfg(not(target_env = "sgx"))]
+    assert!(tsa(("localhost", 23924)).unwrap().contains(&a));
+    #[cfg(target_env = "sgx")]
+    let _ = a;
+}
+
+#[test]
+fn to_socket_addr_str() {
+    let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352);
+    assert_eq!(Ok(vec![a]), tsa("77.88.21.11:24352"));
+
+    let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53);
+    assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53"));
+
+    let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+    #[cfg(not(target_env = "sgx"))]
+    assert!(tsa("localhost:23924").unwrap().contains(&a));
+    #[cfg(target_env = "sgx")]
+    let _ = a;
+}
+
+#[test]
+fn to_socket_addr_string() {
+    let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352);
+    assert_eq!(Ok(vec![a]), tsa(&*format!("{}:{}", "77.88.21.11", "24352")));
+    assert_eq!(Ok(vec![a]), tsa(&format!("{}:{}", "77.88.21.11", "24352")));
+    assert_eq!(Ok(vec![a]), tsa(format!("{}:{}", "77.88.21.11", "24352")));
+
+    let s = format!("{}:{}", "77.88.21.11", "24352");
+    assert_eq!(Ok(vec![a]), tsa(s));
+    // s has been moved into the tsa call
+}
+
+#[test]
+fn bind_udp_socket_bad() {
+    // rust-lang/rust#53957: This is a regression test for a parsing problem
+    // discovered as part of issue rust-lang/rust#23076, where we were
+    // incorrectly parsing invalid input and then that would result in a
+    // successful `UdpSocket` binding when we would expect failure.
+    //
+    // At one time, this test was written as a call to `tsa` with
+    // INPUT_23076. However, that structure yields an unreliable test,
+    // because it ends up passing junk input to the DNS server, and some DNS
+    // servers will respond with `Ok` to such input, with the ip address of
+    // the DNS server itself.
+    //
+    // This form of the test is more robust: even when the DNS server
+    // returns its own address, it is still an error to bind a UDP socket to
+    // a non-local address, and so we still get an error here in that case.
+
+    const INPUT_23076: &'static str = "1200::AB00:1234::2552:7777:1313:34300";
+
+    assert!(crate::net::UdpSocket::bind(INPUT_23076).is_err())
+}
+
+#[test]
+fn set_ip() {
+    fn ip4(low: u8) -> Ipv4Addr {
+        Ipv4Addr::new(77, 88, 21, low)
+    }
+    fn ip6(low: u16) -> Ipv6Addr {
+        Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low)
+    }
+
+    let mut v4 = SocketAddrV4::new(ip4(11), 80);
+    assert_eq!(v4.ip(), &ip4(11));
+    v4.set_ip(ip4(12));
+    assert_eq!(v4.ip(), &ip4(12));
+
+    let mut addr = SocketAddr::V4(v4);
+    assert_eq!(addr.ip(), IpAddr::V4(ip4(12)));
+    addr.set_ip(IpAddr::V4(ip4(13)));
+    assert_eq!(addr.ip(), IpAddr::V4(ip4(13)));
+    addr.set_ip(IpAddr::V6(ip6(14)));
+    assert_eq!(addr.ip(), IpAddr::V6(ip6(14)));
+
+    let mut v6 = SocketAddrV6::new(ip6(1), 80, 0, 0);
+    assert_eq!(v6.ip(), &ip6(1));
+    v6.set_ip(ip6(2));
+    assert_eq!(v6.ip(), &ip6(2));
+
+    let mut addr = SocketAddr::V6(v6);
+    assert_eq!(addr.ip(), IpAddr::V6(ip6(2)));
+    addr.set_ip(IpAddr::V6(ip6(3)));
+    assert_eq!(addr.ip(), IpAddr::V6(ip6(3)));
+    addr.set_ip(IpAddr::V4(ip4(4)));
+    assert_eq!(addr.ip(), IpAddr::V4(ip4(4)));
+}
+
+#[test]
+fn set_port() {
+    let mut v4 = SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80);
+    assert_eq!(v4.port(), 80);
+    v4.set_port(443);
+    assert_eq!(v4.port(), 443);
+
+    let mut addr = SocketAddr::V4(v4);
+    assert_eq!(addr.port(), 443);
+    addr.set_port(8080);
+    assert_eq!(addr.port(), 8080);
+
+    let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 0);
+    assert_eq!(v6.port(), 80);
+    v6.set_port(443);
+    assert_eq!(v6.port(), 443);
+
+    let mut addr = SocketAddr::V6(v6);
+    assert_eq!(addr.port(), 443);
+    addr.set_port(8080);
+    assert_eq!(addr.port(), 8080);
+}
+
+#[test]
+fn set_flowinfo() {
+    let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0);
+    assert_eq!(v6.flowinfo(), 10);
+    v6.set_flowinfo(20);
+    assert_eq!(v6.flowinfo(), 20);
+}
+
+#[test]
+fn set_scope_id() {
+    let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 10);
+    assert_eq!(v6.scope_id(), 10);
+    v6.set_scope_id(20);
+    assert_eq!(v6.scope_id(), 20);
+}
+
+#[test]
+fn is_v4() {
+    let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80));
+    assert!(v4.is_ipv4());
+    assert!(!v4.is_ipv6());
+}
+
+#[test]
+fn is_v6() {
+    let v6 = SocketAddr::V6(SocketAddrV6::new(
+        Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1),
+        80,
+        10,
+        0,
+    ));
+    assert!(!v6.is_ipv4());
+    assert!(v6.is_ipv6());
+}
+
+#[test]
+fn socket_v4_to_str() {
+    let socket = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 8080);
+
+    assert_eq!(format!("{}", socket), "192.168.0.1:8080");
+    assert_eq!(format!("{:<20}", socket), "192.168.0.1:8080    ");
+    assert_eq!(format!("{:>20}", socket), "    192.168.0.1:8080");
+    assert_eq!(format!("{:^20}", socket), "  192.168.0.1:8080  ");
+    assert_eq!(format!("{:.10}", socket), "192.168.0.");
+}
+
+#[test]
+fn socket_v6_to_str() {
+    let socket: SocketAddrV6 = "[2a02:6b8:0:1::1]:53".parse().unwrap();
+
+    assert_eq!(format!("{}", socket), "[2a02:6b8:0:1::1]:53");
+    assert_eq!(format!("{:<24}", socket), "[2a02:6b8:0:1::1]:53    ");
+    assert_eq!(format!("{:>24}", socket), "    [2a02:6b8:0:1::1]:53");
+    assert_eq!(format!("{:^24}", socket), "  [2a02:6b8:0:1::1]:53  ");
+    assert_eq!(format!("{:.15}", socket), "[2a02:6b8:0:1::");
+}
+
+#[test]
+fn compare() {
+    let v4_1 = "224.120.45.1:23456".parse::<SocketAddrV4>().unwrap();
+    let v4_2 = "224.210.103.5:12345".parse::<SocketAddrV4>().unwrap();
+    let v4_3 = "224.210.103.5:23456".parse::<SocketAddrV4>().unwrap();
+    let v6_1 = "[2001:db8:f00::1002]:23456".parse::<SocketAddrV6>().unwrap();
+    let v6_2 = "[2001:db8:f00::2001]:12345".parse::<SocketAddrV6>().unwrap();
+    let v6_3 = "[2001:db8:f00::2001]:23456".parse::<SocketAddrV6>().unwrap();
+
+    // equality
+    assert_eq!(v4_1, v4_1);
+    assert_eq!(v6_1, v6_1);
+    assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1));
+    assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
+    assert!(v4_1 != v4_2);
+    assert!(v6_1 != v6_2);
+
+    // compare different addresses
+    assert!(v4_1 < v4_2);
+    assert!(v6_1 < v6_2);
+    assert!(v4_2 > v4_1);
+    assert!(v6_2 > v6_1);
+
+    // compare the same address with different ports
+    assert!(v4_2 < v4_3);
+    assert!(v6_2 < v6_3);
+    assert!(v4_3 > v4_2);
+    assert!(v6_3 > v6_2);
+
+    // compare different addresses with the same port
+    assert!(v4_1 < v4_3);
+    assert!(v6_1 < v6_3);
+    assert!(v4_3 > v4_1);
+    assert!(v6_3 > v6_1);
+
+    // compare with an inferred right-hand side
+    assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
+    assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());
+    assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap());
+}
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 85bb6b60e68..10676b49d43 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -6,6 +6,10 @@
     issue = "27709"
 )]
 
+// Tests for this module
+#[cfg(all(test, not(target_os = "emscripten")))]
+mod tests;
+
 use crate::cmp::Ordering;
 use crate::fmt::{self, Write as FmtWrite};
 use crate::hash;
@@ -1895,862 +1899,3 @@ impl From<[u16; 8]> for IpAddr {
         IpAddr::V6(Ipv6Addr::from(segments))
     }
 }
-
-// Tests for this module
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod tests {
-    use crate::net::test::{sa4, sa6, tsa};
-    use crate::net::*;
-    use crate::str::FromStr;
-
-    #[test]
-    fn test_from_str_ipv4() {
-        assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
-        assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
-        assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
-
-        // out of range
-        let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
-        assert_eq!(None, none);
-        // too short
-        let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
-        assert_eq!(None, none);
-        // too long
-        let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
-        assert_eq!(None, none);
-        // no number between dots
-        let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn test_from_str_ipv6() {
-        assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
-        assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
-
-        assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
-        assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
-
-        assert_eq!(
-            Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
-            "2a02:6b8::11:11".parse()
-        );
-
-        // too long group
-        let none: Option<Ipv6Addr> = "::00000".parse().ok();
-        assert_eq!(None, none);
-        // too short
-        let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
-        assert_eq!(None, none);
-        // too long
-        let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
-        assert_eq!(None, none);
-        // triple colon
-        let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
-        assert_eq!(None, none);
-        // two double colons
-        let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
-        assert_eq!(None, none);
-        // `::` indicating zero groups of zeros
-        let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn test_from_str_ipv4_in_ipv6() {
-        assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
-        assert_eq!(
-            Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
-            "::FFFF:192.0.2.33".parse()
-        );
-        assert_eq!(
-            Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
-            "64:ff9b::192.0.2.33".parse()
-        );
-        assert_eq!(
-            Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
-            "2001:db8:122:c000:2:2100:192.0.2.33".parse()
-        );
-
-        // colon after v4
-        let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
-        assert_eq!(None, none);
-        // not enough groups
-        let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
-        assert_eq!(None, none);
-        // too many groups
-        let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn test_from_str_socket_addr() {
-        assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
-        assert_eq!(
-            Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
-            "77.88.21.11:80".parse()
-        );
-        assert_eq!(
-            Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
-            "[2a02:6b8:0:1::1]:53".parse()
-        );
-        assert_eq!(
-            Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
-            "[2a02:6b8:0:1::1]:53".parse()
-        );
-        assert_eq!(
-            Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
-            "[::127.0.0.1]:22".parse()
-        );
-        assert_eq!(
-            Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
-            "[::127.0.0.1]:22".parse()
-        );
-
-        // without port
-        let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
-        assert_eq!(None, none);
-        // without port
-        let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
-        assert_eq!(None, none);
-        // wrong brackets around v4
-        let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
-        assert_eq!(None, none);
-        // port out of range
-        let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn ipv4_addr_to_string() {
-        assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
-        // Short address
-        assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
-        // Long address
-        assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
-
-        // Test padding
-        assert_eq!(&format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1         ");
-        assert_eq!(&format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), "         1.1.1.1");
-    }
-
-    #[test]
-    fn ipv6_addr_to_string() {
-        // ipv4-mapped address
-        let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
-        assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
-
-        // ipv4-compatible address
-        let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
-        assert_eq!(a1.to_string(), "::192.0.2.128");
-
-        // v6 address with no zero segments
-        assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
-
-        // longest possible IPv6 length
-        assert_eq!(
-            Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888)
-                .to_string(),
-            "1111:2222:3333:4444:5555:6666:7777:8888"
-        );
-        // padding
-        assert_eq!(
-            &format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
-            "1:2:3:4:5:6:7:8     "
-        );
-        assert_eq!(
-            &format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
-            "     1:2:3:4:5:6:7:8"
-        );
-
-        // reduce a single run of zeros
-        assert_eq!(
-            "ae::ffff:102:304",
-            Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
-        );
-
-        // don't reduce just a single zero segment
-        assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
-
-        // 'any' address
-        assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
-
-        // loopback address
-        assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
-
-        // ends in zeros
-        assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
-
-        // two runs of zeros, second one is longer
-        assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
-
-        // two runs of zeros, equal length
-        assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
-    }
-
-    #[test]
-    fn ipv4_to_ipv6() {
-        assert_eq!(
-            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
-            Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
-        );
-        assert_eq!(
-            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
-            Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
-        );
-    }
-
-    #[test]
-    fn ipv6_to_ipv4_mapped() {
-        assert_eq!(
-            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
-            Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
-        );
-        assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
-    }
-
-    #[test]
-    fn ipv6_to_ipv4() {
-        assert_eq!(
-            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
-            Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
-        );
-        assert_eq!(
-            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
-            Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
-        );
-        assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
-    }
-
-    #[test]
-    fn ip_properties() {
-        macro_rules! ip {
-            ($s:expr) => {
-                IpAddr::from_str($s).unwrap()
-            };
-        }
-
-        macro_rules! check {
-            ($s:expr) => {
-                check!($s, 0);
-            };
-
-            ($s:expr, $mask:expr) => {{
-                let unspec: u8 = 1 << 0;
-                let loopback: u8 = 1 << 1;
-                let global: u8 = 1 << 2;
-                let multicast: u8 = 1 << 3;
-                let doc: u8 = 1 << 4;
-
-                if ($mask & unspec) == unspec {
-                    assert!(ip!($s).is_unspecified());
-                } else {
-                    assert!(!ip!($s).is_unspecified());
-                }
-
-                if ($mask & loopback) == loopback {
-                    assert!(ip!($s).is_loopback());
-                } else {
-                    assert!(!ip!($s).is_loopback());
-                }
-
-                if ($mask & global) == global {
-                    assert!(ip!($s).is_global());
-                } else {
-                    assert!(!ip!($s).is_global());
-                }
-
-                if ($mask & multicast) == multicast {
-                    assert!(ip!($s).is_multicast());
-                } else {
-                    assert!(!ip!($s).is_multicast());
-                }
-
-                if ($mask & doc) == doc {
-                    assert!(ip!($s).is_documentation());
-                } else {
-                    assert!(!ip!($s).is_documentation());
-                }
-            }};
-        }
-
-        let unspec: u8 = 1 << 0;
-        let loopback: u8 = 1 << 1;
-        let global: u8 = 1 << 2;
-        let multicast: u8 = 1 << 3;
-        let doc: u8 = 1 << 4;
-
-        check!("0.0.0.0", unspec);
-        check!("0.0.0.1");
-        check!("0.1.0.0");
-        check!("10.9.8.7");
-        check!("127.1.2.3", loopback);
-        check!("172.31.254.253");
-        check!("169.254.253.242");
-        check!("192.0.2.183", doc);
-        check!("192.1.2.183", global);
-        check!("192.168.254.253");
-        check!("198.51.100.0", doc);
-        check!("203.0.113.0", doc);
-        check!("203.2.113.0", global);
-        check!("224.0.0.0", global | multicast);
-        check!("239.255.255.255", global | multicast);
-        check!("255.255.255.255");
-        // make sure benchmarking addresses are not global
-        check!("198.18.0.0");
-        check!("198.18.54.2");
-        check!("198.19.255.255");
-        // make sure addresses reserved for protocol assignment are not global
-        check!("192.0.0.0");
-        check!("192.0.0.255");
-        check!("192.0.0.100");
-        // make sure reserved addresses are not global
-        check!("240.0.0.0");
-        check!("251.54.1.76");
-        check!("254.255.255.255");
-        // make sure shared addresses are not global
-        check!("100.64.0.0");
-        check!("100.127.255.255");
-        check!("100.100.100.0");
-
-        check!("::", unspec);
-        check!("::1", loopback);
-        check!("::0.0.0.2", global);
-        check!("1::", global);
-        check!("fc00::");
-        check!("fdff:ffff::");
-        check!("fe80:ffff::");
-        check!("febf:ffff::");
-        check!("fec0::", global);
-        check!("ff01::", multicast);
-        check!("ff02::", multicast);
-        check!("ff03::", multicast);
-        check!("ff04::", multicast);
-        check!("ff05::", multicast);
-        check!("ff08::", multicast);
-        check!("ff0e::", global | multicast);
-        check!("2001:db8:85a3::8a2e:370:7334", doc);
-        check!("102:304:506:708:90a:b0c:d0e:f10", global);
-    }
-
-    #[test]
-    fn ipv4_properties() {
-        macro_rules! ip {
-            ($s:expr) => {
-                Ipv4Addr::from_str($s).unwrap()
-            };
-        }
-
-        macro_rules! check {
-            ($s:expr) => {
-                check!($s, 0);
-            };
-
-            ($s:expr, $mask:expr) => {{
-                let unspec: u16 = 1 << 0;
-                let loopback: u16 = 1 << 1;
-                let private: u16 = 1 << 2;
-                let link_local: u16 = 1 << 3;
-                let global: u16 = 1 << 4;
-                let multicast: u16 = 1 << 5;
-                let broadcast: u16 = 1 << 6;
-                let documentation: u16 = 1 << 7;
-                let benchmarking: u16 = 1 << 8;
-                let ietf_protocol_assignment: u16 = 1 << 9;
-                let reserved: u16 = 1 << 10;
-                let shared: u16 = 1 << 11;
-
-                if ($mask & unspec) == unspec {
-                    assert!(ip!($s).is_unspecified());
-                } else {
-                    assert!(!ip!($s).is_unspecified());
-                }
-
-                if ($mask & loopback) == loopback {
-                    assert!(ip!($s).is_loopback());
-                } else {
-                    assert!(!ip!($s).is_loopback());
-                }
-
-                if ($mask & private) == private {
-                    assert!(ip!($s).is_private());
-                } else {
-                    assert!(!ip!($s).is_private());
-                }
-
-                if ($mask & link_local) == link_local {
-                    assert!(ip!($s).is_link_local());
-                } else {
-                    assert!(!ip!($s).is_link_local());
-                }
-
-                if ($mask & global) == global {
-                    assert!(ip!($s).is_global());
-                } else {
-                    assert!(!ip!($s).is_global());
-                }
-
-                if ($mask & multicast) == multicast {
-                    assert!(ip!($s).is_multicast());
-                } else {
-                    assert!(!ip!($s).is_multicast());
-                }
-
-                if ($mask & broadcast) == broadcast {
-                    assert!(ip!($s).is_broadcast());
-                } else {
-                    assert!(!ip!($s).is_broadcast());
-                }
-
-                if ($mask & documentation) == documentation {
-                    assert!(ip!($s).is_documentation());
-                } else {
-                    assert!(!ip!($s).is_documentation());
-                }
-
-                if ($mask & benchmarking) == benchmarking {
-                    assert!(ip!($s).is_benchmarking());
-                } else {
-                    assert!(!ip!($s).is_benchmarking());
-                }
-
-                if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
-                    assert!(ip!($s).is_ietf_protocol_assignment());
-                } else {
-                    assert!(!ip!($s).is_ietf_protocol_assignment());
-                }
-
-                if ($mask & reserved) == reserved {
-                    assert!(ip!($s).is_reserved());
-                } else {
-                    assert!(!ip!($s).is_reserved());
-                }
-
-                if ($mask & shared) == shared {
-                    assert!(ip!($s).is_shared());
-                } else {
-                    assert!(!ip!($s).is_shared());
-                }
-            }};
-        }
-
-        let unspec: u16 = 1 << 0;
-        let loopback: u16 = 1 << 1;
-        let private: u16 = 1 << 2;
-        let link_local: u16 = 1 << 3;
-        let global: u16 = 1 << 4;
-        let multicast: u16 = 1 << 5;
-        let broadcast: u16 = 1 << 6;
-        let documentation: u16 = 1 << 7;
-        let benchmarking: u16 = 1 << 8;
-        let ietf_protocol_assignment: u16 = 1 << 9;
-        let reserved: u16 = 1 << 10;
-        let shared: u16 = 1 << 11;
-
-        check!("0.0.0.0", unspec);
-        check!("0.0.0.1");
-        check!("0.1.0.0");
-        check!("10.9.8.7", private);
-        check!("127.1.2.3", loopback);
-        check!("172.31.254.253", private);
-        check!("169.254.253.242", link_local);
-        check!("192.0.2.183", documentation);
-        check!("192.1.2.183", global);
-        check!("192.168.254.253", private);
-        check!("198.51.100.0", documentation);
-        check!("203.0.113.0", documentation);
-        check!("203.2.113.0", global);
-        check!("224.0.0.0", global | multicast);
-        check!("239.255.255.255", global | multicast);
-        check!("255.255.255.255", broadcast);
-        check!("198.18.0.0", benchmarking);
-        check!("198.18.54.2", benchmarking);
-        check!("198.19.255.255", benchmarking);
-        check!("192.0.0.0", ietf_protocol_assignment);
-        check!("192.0.0.255", ietf_protocol_assignment);
-        check!("192.0.0.100", ietf_protocol_assignment);
-        check!("240.0.0.0", reserved);
-        check!("251.54.1.76", reserved);
-        check!("254.255.255.255", reserved);
-        check!("100.64.0.0", shared);
-        check!("100.127.255.255", shared);
-        check!("100.100.100.0", shared);
-    }
-
-    #[test]
-    fn ipv6_properties() {
-        macro_rules! ip {
-            ($s:expr) => {
-                Ipv6Addr::from_str($s).unwrap()
-            };
-        }
-
-        macro_rules! check {
-            ($s:expr, &[$($octet:expr),*], $mask:expr) => {
-                assert_eq!($s, ip!($s).to_string());
-                let octets = &[$($octet),*];
-                assert_eq!(&ip!($s).octets(), octets);
-                assert_eq!(Ipv6Addr::from(*octets), ip!($s));
-
-                let unspecified: u16 = 1 << 0;
-                let loopback: u16 = 1 << 1;
-                let unique_local: u16 = 1 << 2;
-                let global: u16 = 1 << 3;
-                let unicast_link_local: u16 = 1 << 4;
-                let unicast_link_local_strict: u16 = 1 << 5;
-                let unicast_site_local: u16 = 1 << 6;
-                let unicast_global: u16 = 1 << 7;
-                let documentation: u16 = 1 << 8;
-                let multicast_interface_local: u16 = 1 << 9;
-                let multicast_link_local: u16 = 1 << 10;
-                let multicast_realm_local: u16 = 1 << 11;
-                let multicast_admin_local: u16 = 1 << 12;
-                let multicast_site_local: u16 = 1 << 13;
-                let multicast_organization_local: u16 = 1 << 14;
-                let multicast_global: u16 = 1 << 15;
-                let multicast: u16 = multicast_interface_local
-                    | multicast_admin_local
-                    | multicast_global
-                    | multicast_link_local
-                    | multicast_realm_local
-                    | multicast_site_local
-                    | multicast_organization_local;
-
-                if ($mask & unspecified) == unspecified {
-                    assert!(ip!($s).is_unspecified());
-                } else {
-                    assert!(!ip!($s).is_unspecified());
-                }
-                if ($mask & loopback) == loopback {
-                    assert!(ip!($s).is_loopback());
-                } else {
-                    assert!(!ip!($s).is_loopback());
-                }
-                if ($mask & unique_local) == unique_local {
-                    assert!(ip!($s).is_unique_local());
-                } else {
-                    assert!(!ip!($s).is_unique_local());
-                }
-                if ($mask & global) == global {
-                    assert!(ip!($s).is_global());
-                } else {
-                    assert!(!ip!($s).is_global());
-                }
-                if ($mask & unicast_link_local) == unicast_link_local {
-                    assert!(ip!($s).is_unicast_link_local());
-                } else {
-                    assert!(!ip!($s).is_unicast_link_local());
-                }
-                if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
-                    assert!(ip!($s).is_unicast_link_local_strict());
-                } else {
-                    assert!(!ip!($s).is_unicast_link_local_strict());
-                }
-                if ($mask & unicast_site_local) == unicast_site_local {
-                    assert!(ip!($s).is_unicast_site_local());
-                } else {
-                    assert!(!ip!($s).is_unicast_site_local());
-                }
-                if ($mask & unicast_global) == unicast_global {
-                    assert!(ip!($s).is_unicast_global());
-                } else {
-                    assert!(!ip!($s).is_unicast_global());
-                }
-                if ($mask & documentation) == documentation {
-                    assert!(ip!($s).is_documentation());
-                } else {
-                    assert!(!ip!($s).is_documentation());
-                }
-                if ($mask & multicast) != 0 {
-                    assert!(ip!($s).multicast_scope().is_some());
-                    assert!(ip!($s).is_multicast());
-                } else {
-                    assert!(ip!($s).multicast_scope().is_none());
-                    assert!(!ip!($s).is_multicast());
-                }
-                if ($mask & multicast_interface_local) == multicast_interface_local {
-                    assert_eq!(ip!($s).multicast_scope().unwrap(),
-                               Ipv6MulticastScope::InterfaceLocal);
-                }
-                if ($mask & multicast_link_local) == multicast_link_local {
-                    assert_eq!(ip!($s).multicast_scope().unwrap(),
-                               Ipv6MulticastScope::LinkLocal);
-                }
-                if ($mask & multicast_realm_local) == multicast_realm_local {
-                    assert_eq!(ip!($s).multicast_scope().unwrap(),
-                               Ipv6MulticastScope::RealmLocal);
-                }
-                if ($mask & multicast_admin_local) == multicast_admin_local {
-                    assert_eq!(ip!($s).multicast_scope().unwrap(),
-                               Ipv6MulticastScope::AdminLocal);
-                }
-                if ($mask & multicast_site_local) == multicast_site_local {
-                    assert_eq!(ip!($s).multicast_scope().unwrap(),
-                               Ipv6MulticastScope::SiteLocal);
-                }
-                if ($mask & multicast_organization_local) == multicast_organization_local {
-                    assert_eq!(ip!($s).multicast_scope().unwrap(),
-                               Ipv6MulticastScope::OrganizationLocal);
-                }
-                if ($mask & multicast_global) == multicast_global {
-                    assert_eq!(ip!($s).multicast_scope().unwrap(),
-                               Ipv6MulticastScope::Global);
-                }
-            }
-        }
-
-        let unspecified: u16 = 1 << 0;
-        let loopback: u16 = 1 << 1;
-        let unique_local: u16 = 1 << 2;
-        let global: u16 = 1 << 3;
-        let unicast_link_local: u16 = 1 << 4;
-        let unicast_link_local_strict: u16 = 1 << 5;
-        let unicast_site_local: u16 = 1 << 6;
-        let unicast_global: u16 = 1 << 7;
-        let documentation: u16 = 1 << 8;
-        let multicast_interface_local: u16 = 1 << 9;
-        let multicast_link_local: u16 = 1 << 10;
-        let multicast_realm_local: u16 = 1 << 11;
-        let multicast_admin_local: u16 = 1 << 12;
-        let multicast_site_local: u16 = 1 << 13;
-        let multicast_organization_local: u16 = 1 << 14;
-        let multicast_global: u16 = 1 << 15;
-
-        check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
-
-        check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
-
-        check!(
-            "::0.0.0.2",
-            &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
-            global | unicast_global
-        );
-
-        check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
-
-        check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
-
-        check!(
-            "fdff:ffff::",
-            &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            unique_local
-        );
-
-        check!(
-            "fe80:ffff::",
-            &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            unicast_link_local
-        );
-
-        check!(
-            "fe80::",
-            &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            unicast_link_local | unicast_link_local_strict
-        );
-
-        check!(
-            "febf:ffff::",
-            &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            unicast_link_local
-        );
-
-        check!(
-            "febf::",
-            &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            unicast_link_local
-        );
-
-        check!(
-            "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
-            &[
-                0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff
-            ],
-            unicast_link_local
-        );
-
-        check!(
-            "fe80::ffff:ffff:ffff:ffff",
-            &[
-                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff
-            ],
-            unicast_link_local | unicast_link_local_strict
-        );
-
-        check!(
-            "fe80:0:0:1::",
-            &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
-            unicast_link_local
-        );
-
-        check!(
-            "fec0::",
-            &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            unicast_site_local | unicast_global | global
-        );
-
-        check!(
-            "ff01::",
-            &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            multicast_interface_local
-        );
-
-        check!(
-            "ff02::",
-            &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            multicast_link_local
-        );
-
-        check!(
-            "ff03::",
-            &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            multicast_realm_local
-        );
-
-        check!(
-            "ff04::",
-            &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            multicast_admin_local
-        );
-
-        check!(
-            "ff05::",
-            &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            multicast_site_local
-        );
-
-        check!(
-            "ff08::",
-            &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            multicast_organization_local
-        );
-
-        check!(
-            "ff0e::",
-            &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            multicast_global | global
-        );
-
-        check!(
-            "2001:db8:85a3::8a2e:370:7334",
-            &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
-            documentation
-        );
-
-        check!(
-            "102:304:506:708:90a:b0c:d0e:f10",
-            &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
-            global | unicast_global
-        );
-    }
-
-    #[test]
-    fn to_socket_addr_socketaddr() {
-        let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
-        assert_eq!(Ok(vec![a]), tsa(a));
-    }
-
-    #[test]
-    fn test_ipv4_to_int() {
-        let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
-        assert_eq!(u32::from(a), 0x11223344);
-    }
-
-    #[test]
-    fn test_int_to_ipv4() {
-        let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
-        assert_eq!(Ipv4Addr::from(0x11223344), a);
-    }
-
-    #[test]
-    fn test_ipv6_to_int() {
-        let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
-        assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
-    }
-
-    #[test]
-    fn test_int_to_ipv6() {
-        let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
-        assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
-    }
-
-    #[test]
-    fn ipv4_from_constructors() {
-        assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
-        assert!(Ipv4Addr::LOCALHOST.is_loopback());
-        assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
-        assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
-        assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
-        assert!(Ipv4Addr::BROADCAST.is_broadcast());
-    }
-
-    #[test]
-    fn ipv6_from_contructors() {
-        assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-        assert!(Ipv6Addr::LOCALHOST.is_loopback());
-        assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
-        assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
-    }
-
-    #[test]
-    fn ipv4_from_octets() {
-        assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
-    }
-
-    #[test]
-    fn ipv6_from_segments() {
-        let from_u16s =
-            Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
-        let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
-        assert_eq!(new, from_u16s);
-    }
-
-    #[test]
-    fn ipv6_from_octets() {
-        let from_u16s =
-            Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
-        let from_u8s = Ipv6Addr::from([
-            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
-            0xee, 0xff,
-        ]);
-        assert_eq!(from_u16s, from_u8s);
-    }
-
-    #[test]
-    fn cmp() {
-        let v41 = Ipv4Addr::new(100, 64, 3, 3);
-        let v42 = Ipv4Addr::new(192, 0, 2, 2);
-        let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
-        let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
-        assert!(v41 < v42);
-        assert!(v61 < v62);
-
-        assert_eq!(v41, IpAddr::V4(v41));
-        assert_eq!(v61, IpAddr::V6(v61));
-        assert!(v41 != IpAddr::V4(v42));
-        assert!(v61 != IpAddr::V6(v62));
-
-        assert!(v41 < IpAddr::V4(v42));
-        assert!(v61 < IpAddr::V6(v62));
-        assert!(IpAddr::V4(v41) < v42);
-        assert!(IpAddr::V6(v61) < v62);
-
-        assert!(v41 < IpAddr::V6(v61));
-        assert!(IpAddr::V4(v41) < v61);
-    }
-
-    #[test]
-    fn is_v4() {
-        let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
-        assert!(ip.is_ipv4());
-        assert!(!ip.is_ipv6());
-    }
-
-    #[test]
-    fn is_v6() {
-        let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
-        assert!(!ip.is_ipv4());
-        assert!(ip.is_ipv6());
-    }
-}
diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs
new file mode 100644
index 00000000000..a2fba4b4cca
--- /dev/null
+++ b/library/std/src/net/ip/tests.rs
@@ -0,0 +1,811 @@
+use crate::net::test::{sa4, sa6, tsa};
+use crate::net::*;
+use crate::str::FromStr;
+
+#[test]
+fn test_from_str_ipv4() {
+    assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
+    assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
+    assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
+
+    // out of range
+    let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
+    assert_eq!(None, none);
+    // too short
+    let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
+    assert_eq!(None, none);
+    // too long
+    let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
+    assert_eq!(None, none);
+    // no number between dots
+    let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_ipv6() {
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
+
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
+
+    assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), "2a02:6b8::11:11".parse());
+
+    // too long group
+    let none: Option<Ipv6Addr> = "::00000".parse().ok();
+    assert_eq!(None, none);
+    // too short
+    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
+    assert_eq!(None, none);
+    // too long
+    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
+    assert_eq!(None, none);
+    // triple colon
+    let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
+    assert_eq!(None, none);
+    // two double colons
+    let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
+    assert_eq!(None, none);
+    // `::` indicating zero groups of zeros
+    let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_ipv4_in_ipv6() {
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), "::FFFF:192.0.2.33".parse());
+    assert_eq!(
+        Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
+        "64:ff9b::192.0.2.33".parse()
+    );
+    assert_eq!(
+        Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
+        "2001:db8:122:c000:2:2100:192.0.2.33".parse()
+    );
+
+    // colon after v4
+    let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
+    assert_eq!(None, none);
+    // not enough groups
+    let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
+    assert_eq!(None, none);
+    // too many groups
+    let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_socket_addr() {
+    assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
+    assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
+    assert_eq!(
+        Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
+        "[2a02:6b8:0:1::1]:53".parse()
+    );
+    assert_eq!(
+        Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
+        "[2a02:6b8:0:1::1]:53".parse()
+    );
+    assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), "[::127.0.0.1]:22".parse());
+    assert_eq!(
+        Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
+        "[::127.0.0.1]:22".parse()
+    );
+
+    // without port
+    let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
+    assert_eq!(None, none);
+    // without port
+    let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
+    assert_eq!(None, none);
+    // wrong brackets around v4
+    let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
+    assert_eq!(None, none);
+    // port out of range
+    let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn ipv4_addr_to_string() {
+    assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
+    // Short address
+    assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
+    // Long address
+    assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
+
+    // Test padding
+    assert_eq!(&format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1         ");
+    assert_eq!(&format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), "         1.1.1.1");
+}
+
+#[test]
+fn ipv6_addr_to_string() {
+    // ipv4-mapped address
+    let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
+    assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
+
+    // ipv4-compatible address
+    let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
+    assert_eq!(a1.to_string(), "::192.0.2.128");
+
+    // v6 address with no zero segments
+    assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
+
+    // longest possible IPv6 length
+    assert_eq!(
+        Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888).to_string(),
+        "1111:2222:3333:4444:5555:6666:7777:8888"
+    );
+    // padding
+    assert_eq!(&format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8     ");
+    assert_eq!(&format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "     1:2:3:4:5:6:7:8");
+
+    // reduce a single run of zeros
+    assert_eq!(
+        "ae::ffff:102:304",
+        Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
+    );
+
+    // don't reduce just a single zero segment
+    assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
+
+    // 'any' address
+    assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
+
+    // loopback address
+    assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
+
+    // ends in zeros
+    assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
+
+    // two runs of zeros, second one is longer
+    assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
+
+    // two runs of zeros, equal length
+    assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
+}
+
+#[test]
+fn ipv4_to_ipv6() {
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
+        Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
+    );
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
+        Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
+    );
+}
+
+#[test]
+fn ipv6_to_ipv4_mapped() {
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
+        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+    );
+    assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
+}
+
+#[test]
+fn ipv6_to_ipv4() {
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
+        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+    );
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
+        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+    );
+    assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
+}
+
+#[test]
+fn ip_properties() {
+    macro_rules! ip {
+        ($s:expr) => {
+            IpAddr::from_str($s).unwrap()
+        };
+    }
+
+    macro_rules! check {
+        ($s:expr) => {
+            check!($s, 0);
+        };
+
+        ($s:expr, $mask:expr) => {{
+            let unspec: u8 = 1 << 0;
+            let loopback: u8 = 1 << 1;
+            let global: u8 = 1 << 2;
+            let multicast: u8 = 1 << 3;
+            let doc: u8 = 1 << 4;
+
+            if ($mask & unspec) == unspec {
+                assert!(ip!($s).is_unspecified());
+            } else {
+                assert!(!ip!($s).is_unspecified());
+            }
+
+            if ($mask & loopback) == loopback {
+                assert!(ip!($s).is_loopback());
+            } else {
+                assert!(!ip!($s).is_loopback());
+            }
+
+            if ($mask & global) == global {
+                assert!(ip!($s).is_global());
+            } else {
+                assert!(!ip!($s).is_global());
+            }
+
+            if ($mask & multicast) == multicast {
+                assert!(ip!($s).is_multicast());
+            } else {
+                assert!(!ip!($s).is_multicast());
+            }
+
+            if ($mask & doc) == doc {
+                assert!(ip!($s).is_documentation());
+            } else {
+                assert!(!ip!($s).is_documentation());
+            }
+        }};
+    }
+
+    let unspec: u8 = 1 << 0;
+    let loopback: u8 = 1 << 1;
+    let global: u8 = 1 << 2;
+    let multicast: u8 = 1 << 3;
+    let doc: u8 = 1 << 4;
+
+    check!("0.0.0.0", unspec);
+    check!("0.0.0.1");
+    check!("0.1.0.0");
+    check!("10.9.8.7");
+    check!("127.1.2.3", loopback);
+    check!("172.31.254.253");
+    check!("169.254.253.242");
+    check!("192.0.2.183", doc);
+    check!("192.1.2.183", global);
+    check!("192.168.254.253");
+    check!("198.51.100.0", doc);
+    check!("203.0.113.0", doc);
+    check!("203.2.113.0", global);
+    check!("224.0.0.0", global | multicast);
+    check!("239.255.255.255", global | multicast);
+    check!("255.255.255.255");
+    // make sure benchmarking addresses are not global
+    check!("198.18.0.0");
+    check!("198.18.54.2");
+    check!("198.19.255.255");
+    // make sure addresses reserved for protocol assignment are not global
+    check!("192.0.0.0");
+    check!("192.0.0.255");
+    check!("192.0.0.100");
+    // make sure reserved addresses are not global
+    check!("240.0.0.0");
+    check!("251.54.1.76");
+    check!("254.255.255.255");
+    // make sure shared addresses are not global
+    check!("100.64.0.0");
+    check!("100.127.255.255");
+    check!("100.100.100.0");
+
+    check!("::", unspec);
+    check!("::1", loopback);
+    check!("::0.0.0.2", global);
+    check!("1::", global);
+    check!("fc00::");
+    check!("fdff:ffff::");
+    check!("fe80:ffff::");
+    check!("febf:ffff::");
+    check!("fec0::", global);
+    check!("ff01::", multicast);
+    check!("ff02::", multicast);
+    check!("ff03::", multicast);
+    check!("ff04::", multicast);
+    check!("ff05::", multicast);
+    check!("ff08::", multicast);
+    check!("ff0e::", global | multicast);
+    check!("2001:db8:85a3::8a2e:370:7334", doc);
+    check!("102:304:506:708:90a:b0c:d0e:f10", global);
+}
+
+#[test]
+fn ipv4_properties() {
+    macro_rules! ip {
+        ($s:expr) => {
+            Ipv4Addr::from_str($s).unwrap()
+        };
+    }
+
+    macro_rules! check {
+        ($s:expr) => {
+            check!($s, 0);
+        };
+
+        ($s:expr, $mask:expr) => {{
+            let unspec: u16 = 1 << 0;
+            let loopback: u16 = 1 << 1;
+            let private: u16 = 1 << 2;
+            let link_local: u16 = 1 << 3;
+            let global: u16 = 1 << 4;
+            let multicast: u16 = 1 << 5;
+            let broadcast: u16 = 1 << 6;
+            let documentation: u16 = 1 << 7;
+            let benchmarking: u16 = 1 << 8;
+            let ietf_protocol_assignment: u16 = 1 << 9;
+            let reserved: u16 = 1 << 10;
+            let shared: u16 = 1 << 11;
+
+            if ($mask & unspec) == unspec {
+                assert!(ip!($s).is_unspecified());
+            } else {
+                assert!(!ip!($s).is_unspecified());
+            }
+
+            if ($mask & loopback) == loopback {
+                assert!(ip!($s).is_loopback());
+            } else {
+                assert!(!ip!($s).is_loopback());
+            }
+
+            if ($mask & private) == private {
+                assert!(ip!($s).is_private());
+            } else {
+                assert!(!ip!($s).is_private());
+            }
+
+            if ($mask & link_local) == link_local {
+                assert!(ip!($s).is_link_local());
+            } else {
+                assert!(!ip!($s).is_link_local());
+            }
+
+            if ($mask & global) == global {
+                assert!(ip!($s).is_global());
+            } else {
+                assert!(!ip!($s).is_global());
+            }
+
+            if ($mask & multicast) == multicast {
+                assert!(ip!($s).is_multicast());
+            } else {
+                assert!(!ip!($s).is_multicast());
+            }
+
+            if ($mask & broadcast) == broadcast {
+                assert!(ip!($s).is_broadcast());
+            } else {
+                assert!(!ip!($s).is_broadcast());
+            }
+
+            if ($mask & documentation) == documentation {
+                assert!(ip!($s).is_documentation());
+            } else {
+                assert!(!ip!($s).is_documentation());
+            }
+
+            if ($mask & benchmarking) == benchmarking {
+                assert!(ip!($s).is_benchmarking());
+            } else {
+                assert!(!ip!($s).is_benchmarking());
+            }
+
+            if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
+                assert!(ip!($s).is_ietf_protocol_assignment());
+            } else {
+                assert!(!ip!($s).is_ietf_protocol_assignment());
+            }
+
+            if ($mask & reserved) == reserved {
+                assert!(ip!($s).is_reserved());
+            } else {
+                assert!(!ip!($s).is_reserved());
+            }
+
+            if ($mask & shared) == shared {
+                assert!(ip!($s).is_shared());
+            } else {
+                assert!(!ip!($s).is_shared());
+            }
+        }};
+    }
+
+    let unspec: u16 = 1 << 0;
+    let loopback: u16 = 1 << 1;
+    let private: u16 = 1 << 2;
+    let link_local: u16 = 1 << 3;
+    let global: u16 = 1 << 4;
+    let multicast: u16 = 1 << 5;
+    let broadcast: u16 = 1 << 6;
+    let documentation: u16 = 1 << 7;
+    let benchmarking: u16 = 1 << 8;
+    let ietf_protocol_assignment: u16 = 1 << 9;
+    let reserved: u16 = 1 << 10;
+    let shared: u16 = 1 << 11;
+
+    check!("0.0.0.0", unspec);
+    check!("0.0.0.1");
+    check!("0.1.0.0");
+    check!("10.9.8.7", private);
+    check!("127.1.2.3", loopback);
+    check!("172.31.254.253", private);
+    check!("169.254.253.242", link_local);
+    check!("192.0.2.183", documentation);
+    check!("192.1.2.183", global);
+    check!("192.168.254.253", private);
+    check!("198.51.100.0", documentation);
+    check!("203.0.113.0", documentation);
+    check!("203.2.113.0", global);
+    check!("224.0.0.0", global | multicast);
+    check!("239.255.255.255", global | multicast);
+    check!("255.255.255.255", broadcast);
+    check!("198.18.0.0", benchmarking);
+    check!("198.18.54.2", benchmarking);
+    check!("198.19.255.255", benchmarking);
+    check!("192.0.0.0", ietf_protocol_assignment);
+    check!("192.0.0.255", ietf_protocol_assignment);
+    check!("192.0.0.100", ietf_protocol_assignment);
+    check!("240.0.0.0", reserved);
+    check!("251.54.1.76", reserved);
+    check!("254.255.255.255", reserved);
+    check!("100.64.0.0", shared);
+    check!("100.127.255.255", shared);
+    check!("100.100.100.0", shared);
+}
+
+#[test]
+fn ipv6_properties() {
+    macro_rules! ip {
+        ($s:expr) => {
+            Ipv6Addr::from_str($s).unwrap()
+        };
+    }
+
+    macro_rules! check {
+        ($s:expr, &[$($octet:expr),*], $mask:expr) => {
+            assert_eq!($s, ip!($s).to_string());
+            let octets = &[$($octet),*];
+            assert_eq!(&ip!($s).octets(), octets);
+            assert_eq!(Ipv6Addr::from(*octets), ip!($s));
+
+            let unspecified: u16 = 1 << 0;
+            let loopback: u16 = 1 << 1;
+            let unique_local: u16 = 1 << 2;
+            let global: u16 = 1 << 3;
+            let unicast_link_local: u16 = 1 << 4;
+            let unicast_link_local_strict: u16 = 1 << 5;
+            let unicast_site_local: u16 = 1 << 6;
+            let unicast_global: u16 = 1 << 7;
+            let documentation: u16 = 1 << 8;
+            let multicast_interface_local: u16 = 1 << 9;
+            let multicast_link_local: u16 = 1 << 10;
+            let multicast_realm_local: u16 = 1 << 11;
+            let multicast_admin_local: u16 = 1 << 12;
+            let multicast_site_local: u16 = 1 << 13;
+            let multicast_organization_local: u16 = 1 << 14;
+            let multicast_global: u16 = 1 << 15;
+            let multicast: u16 = multicast_interface_local
+                | multicast_admin_local
+                | multicast_global
+                | multicast_link_local
+                | multicast_realm_local
+                | multicast_site_local
+                | multicast_organization_local;
+
+            if ($mask & unspecified) == unspecified {
+                assert!(ip!($s).is_unspecified());
+            } else {
+                assert!(!ip!($s).is_unspecified());
+            }
+            if ($mask & loopback) == loopback {
+                assert!(ip!($s).is_loopback());
+            } else {
+                assert!(!ip!($s).is_loopback());
+            }
+            if ($mask & unique_local) == unique_local {
+                assert!(ip!($s).is_unique_local());
+            } else {
+                assert!(!ip!($s).is_unique_local());
+            }
+            if ($mask & global) == global {
+                assert!(ip!($s).is_global());
+            } else {
+                assert!(!ip!($s).is_global());
+            }
+            if ($mask & unicast_link_local) == unicast_link_local {
+                assert!(ip!($s).is_unicast_link_local());
+            } else {
+                assert!(!ip!($s).is_unicast_link_local());
+            }
+            if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
+                assert!(ip!($s).is_unicast_link_local_strict());
+            } else {
+                assert!(!ip!($s).is_unicast_link_local_strict());
+            }
+            if ($mask & unicast_site_local) == unicast_site_local {
+                assert!(ip!($s).is_unicast_site_local());
+            } else {
+                assert!(!ip!($s).is_unicast_site_local());
+            }
+            if ($mask & unicast_global) == unicast_global {
+                assert!(ip!($s).is_unicast_global());
+            } else {
+                assert!(!ip!($s).is_unicast_global());
+            }
+            if ($mask & documentation) == documentation {
+                assert!(ip!($s).is_documentation());
+            } else {
+                assert!(!ip!($s).is_documentation());
+            }
+            if ($mask & multicast) != 0 {
+                assert!(ip!($s).multicast_scope().is_some());
+                assert!(ip!($s).is_multicast());
+            } else {
+                assert!(ip!($s).multicast_scope().is_none());
+                assert!(!ip!($s).is_multicast());
+            }
+            if ($mask & multicast_interface_local) == multicast_interface_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::InterfaceLocal);
+            }
+            if ($mask & multicast_link_local) == multicast_link_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::LinkLocal);
+            }
+            if ($mask & multicast_realm_local) == multicast_realm_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::RealmLocal);
+            }
+            if ($mask & multicast_admin_local) == multicast_admin_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::AdminLocal);
+            }
+            if ($mask & multicast_site_local) == multicast_site_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::SiteLocal);
+            }
+            if ($mask & multicast_organization_local) == multicast_organization_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::OrganizationLocal);
+            }
+            if ($mask & multicast_global) == multicast_global {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::Global);
+            }
+        }
+    }
+
+    let unspecified: u16 = 1 << 0;
+    let loopback: u16 = 1 << 1;
+    let unique_local: u16 = 1 << 2;
+    let global: u16 = 1 << 3;
+    let unicast_link_local: u16 = 1 << 4;
+    let unicast_link_local_strict: u16 = 1 << 5;
+    let unicast_site_local: u16 = 1 << 6;
+    let unicast_global: u16 = 1 << 7;
+    let documentation: u16 = 1 << 8;
+    let multicast_interface_local: u16 = 1 << 9;
+    let multicast_link_local: u16 = 1 << 10;
+    let multicast_realm_local: u16 = 1 << 11;
+    let multicast_admin_local: u16 = 1 << 12;
+    let multicast_site_local: u16 = 1 << 13;
+    let multicast_organization_local: u16 = 1 << 14;
+    let multicast_global: u16 = 1 << 15;
+
+    check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
+
+    check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
+
+    check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global);
+
+    check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
+
+    check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
+
+    check!(
+        "fdff:ffff::",
+        &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unique_local
+    );
+
+    check!(
+        "fe80:ffff::",
+        &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_link_local
+    );
+
+    check!(
+        "fe80::",
+        &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_link_local | unicast_link_local_strict
+    );
+
+    check!(
+        "febf:ffff::",
+        &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_link_local
+    );
+
+    check!("febf::", &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
+
+    check!(
+        "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+        &[
+            0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff
+        ],
+        unicast_link_local
+    );
+
+    check!(
+        "fe80::ffff:ffff:ffff:ffff",
+        &[
+            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff
+        ],
+        unicast_link_local | unicast_link_local_strict
+    );
+
+    check!(
+        "fe80:0:0:1::",
+        &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_link_local
+    );
+
+    check!(
+        "fec0::",
+        &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_site_local | unicast_global | global
+    );
+
+    check!(
+        "ff01::",
+        &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_interface_local
+    );
+
+    check!("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_link_local);
+
+    check!("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_realm_local);
+
+    check!("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_admin_local);
+
+    check!("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_site_local);
+
+    check!(
+        "ff08::",
+        &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_organization_local
+    );
+
+    check!(
+        "ff0e::",
+        &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_global | global
+    );
+
+    check!(
+        "2001:db8:85a3::8a2e:370:7334",
+        &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
+        documentation
+    );
+
+    check!(
+        "102:304:506:708:90a:b0c:d0e:f10",
+        &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+        global | unicast_global
+    );
+}
+
+#[test]
+fn to_socket_addr_socketaddr() {
+    let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
+    assert_eq!(Ok(vec![a]), tsa(a));
+}
+
+#[test]
+fn test_ipv4_to_int() {
+    let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+    assert_eq!(u32::from(a), 0x11223344);
+}
+
+#[test]
+fn test_int_to_ipv4() {
+    let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+    assert_eq!(Ipv4Addr::from(0x11223344), a);
+}
+
+#[test]
+fn test_ipv6_to_int() {
+    let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+    assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
+}
+
+#[test]
+fn test_int_to_ipv6() {
+    let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+    assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
+}
+
+#[test]
+fn ipv4_from_constructors() {
+    assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
+    assert!(Ipv4Addr::LOCALHOST.is_loopback());
+    assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
+    assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
+    assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
+    assert!(Ipv4Addr::BROADCAST.is_broadcast());
+}
+
+#[test]
+fn ipv6_from_contructors() {
+    assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+    assert!(Ipv6Addr::LOCALHOST.is_loopback());
+    assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+    assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
+}
+
+#[test]
+fn ipv4_from_octets() {
+    assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
+}
+
+#[test]
+fn ipv6_from_segments() {
+    let from_u16s =
+        Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
+    let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
+    assert_eq!(new, from_u16s);
+}
+
+#[test]
+fn ipv6_from_octets() {
+    let from_u16s =
+        Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
+    let from_u8s = Ipv6Addr::from([
+        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
+        0xff,
+    ]);
+    assert_eq!(from_u16s, from_u8s);
+}
+
+#[test]
+fn cmp() {
+    let v41 = Ipv4Addr::new(100, 64, 3, 3);
+    let v42 = Ipv4Addr::new(192, 0, 2, 2);
+    let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
+    let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
+    assert!(v41 < v42);
+    assert!(v61 < v62);
+
+    assert_eq!(v41, IpAddr::V4(v41));
+    assert_eq!(v61, IpAddr::V6(v61));
+    assert!(v41 != IpAddr::V4(v42));
+    assert!(v61 != IpAddr::V6(v62));
+
+    assert!(v41 < IpAddr::V4(v42));
+    assert!(v61 < IpAddr::V6(v62));
+    assert!(IpAddr::V4(v41) < v42);
+    assert!(IpAddr::V6(v61) < v62);
+
+    assert!(v41 < IpAddr::V6(v61));
+    assert!(IpAddr::V4(v41) < v61);
+}
+
+#[test]
+fn is_v4() {
+    let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
+    assert!(ip.is_ipv4());
+    assert!(!ip.is_ipv6());
+}
+
+#[test]
+fn is_v6() {
+    let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
+    assert!(!ip.is_ipv4());
+    assert!(ip.is_ipv6());
+}
diff --git a/library/std/src/net/parser.rs b/library/std/src/net/parser.rs
index a425aca5a64..0570a7c41bf 100644
--- a/library/std/src/net/parser.rs
+++ b/library/std/src/net/parser.rs
@@ -3,6 +3,9 @@
 //! This module is "publicly exported" through the `FromStr` implementations
 //! below.
 
+#[cfg(test)]
+mod tests;
+
 use crate::error::Error;
 use crate::fmt;
 use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
@@ -321,146 +324,3 @@ impl Error for AddrParseError {
         "invalid IP address syntax"
     }
 }
-
-#[cfg(test)]
-mod tests {
-    // FIXME: These tests are all excellent candidates for AFL fuzz testing
-    use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
-    use crate::str::FromStr;
-
-    const PORT: u16 = 8080;
-
-    const IPV4: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1);
-    const IPV4_STR: &str = "192.168.0.1";
-    const IPV4_STR_PORT: &str = "192.168.0.1:8080";
-
-    const IPV6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc0a8, 0x1);
-    const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1";
-    const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1";
-    const IPV6_STR_V4: &str = "2001:db8::192.168.0.1";
-    const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080";
-
-    #[test]
-    fn parse_ipv4() {
-        let result: Ipv4Addr = IPV4_STR.parse().unwrap();
-        assert_eq!(result, IPV4);
-
-        assert!(Ipv4Addr::from_str(IPV4_STR_PORT).is_err());
-        assert!(Ipv4Addr::from_str(IPV6_STR_FULL).is_err());
-        assert!(Ipv4Addr::from_str(IPV6_STR_COMPRESS).is_err());
-        assert!(Ipv4Addr::from_str(IPV6_STR_V4).is_err());
-        assert!(Ipv4Addr::from_str(IPV6_STR_PORT).is_err());
-    }
-
-    #[test]
-    fn parse_ipv6() {
-        let result: Ipv6Addr = IPV6_STR_FULL.parse().unwrap();
-        assert_eq!(result, IPV6);
-
-        let result: Ipv6Addr = IPV6_STR_COMPRESS.parse().unwrap();
-        assert_eq!(result, IPV6);
-
-        let result: Ipv6Addr = IPV6_STR_V4.parse().unwrap();
-        assert_eq!(result, IPV6);
-
-        assert!(Ipv6Addr::from_str(IPV4_STR).is_err());
-        assert!(Ipv6Addr::from_str(IPV4_STR_PORT).is_err());
-        assert!(Ipv6Addr::from_str(IPV6_STR_PORT).is_err());
-    }
-
-    #[test]
-    fn parse_ip() {
-        let result: IpAddr = IPV4_STR.parse().unwrap();
-        assert_eq!(result, IpAddr::from(IPV4));
-
-        let result: IpAddr = IPV6_STR_FULL.parse().unwrap();
-        assert_eq!(result, IpAddr::from(IPV6));
-
-        let result: IpAddr = IPV6_STR_COMPRESS.parse().unwrap();
-        assert_eq!(result, IpAddr::from(IPV6));
-
-        let result: IpAddr = IPV6_STR_V4.parse().unwrap();
-        assert_eq!(result, IpAddr::from(IPV6));
-
-        assert!(IpAddr::from_str(IPV4_STR_PORT).is_err());
-        assert!(IpAddr::from_str(IPV6_STR_PORT).is_err());
-    }
-
-    #[test]
-    fn parse_socket_v4() {
-        let result: SocketAddrV4 = IPV4_STR_PORT.parse().unwrap();
-        assert_eq!(result, SocketAddrV4::new(IPV4, PORT));
-
-        assert!(SocketAddrV4::from_str(IPV4_STR).is_err());
-        assert!(SocketAddrV4::from_str(IPV6_STR_FULL).is_err());
-        assert!(SocketAddrV4::from_str(IPV6_STR_COMPRESS).is_err());
-        assert!(SocketAddrV4::from_str(IPV6_STR_V4).is_err());
-        assert!(SocketAddrV4::from_str(IPV6_STR_PORT).is_err());
-    }
-
-    #[test]
-    fn parse_socket_v6() {
-        let result: SocketAddrV6 = IPV6_STR_PORT.parse().unwrap();
-        assert_eq!(result, SocketAddrV6::new(IPV6, PORT, 0, 0));
-
-        assert!(SocketAddrV6::from_str(IPV4_STR).is_err());
-        assert!(SocketAddrV6::from_str(IPV4_STR_PORT).is_err());
-        assert!(SocketAddrV6::from_str(IPV6_STR_FULL).is_err());
-        assert!(SocketAddrV6::from_str(IPV6_STR_COMPRESS).is_err());
-        assert!(SocketAddrV6::from_str(IPV6_STR_V4).is_err());
-    }
-
-    #[test]
-    fn parse_socket() {
-        let result: SocketAddr = IPV4_STR_PORT.parse().unwrap();
-        assert_eq!(result, SocketAddr::from((IPV4, PORT)));
-
-        let result: SocketAddr = IPV6_STR_PORT.parse().unwrap();
-        assert_eq!(result, SocketAddr::from((IPV6, PORT)));
-
-        assert!(SocketAddr::from_str(IPV4_STR).is_err());
-        assert!(SocketAddr::from_str(IPV6_STR_FULL).is_err());
-        assert!(SocketAddr::from_str(IPV6_STR_COMPRESS).is_err());
-        assert!(SocketAddr::from_str(IPV6_STR_V4).is_err());
-    }
-
-    #[test]
-    fn ipv6_corner_cases() {
-        let result: Ipv6Addr = "1::".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0));
-
-        let result: Ipv6Addr = "1:1::".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(1, 1, 0, 0, 0, 0, 0, 0));
-
-        let result: Ipv6Addr = "::1".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-
-        let result: Ipv6Addr = "::1:1".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 1, 1));
-
-        let result: Ipv6Addr = "::".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
-
-        let result: Ipv6Addr = "::192.168.0.1".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc0a8, 0x1));
-
-        let result: Ipv6Addr = "::1:192.168.0.1".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 1, 0xc0a8, 0x1));
-
-        let result: Ipv6Addr = "1:1:1:1:1:1:192.168.0.1".parse().unwrap();
-        assert_eq!(result, Ipv6Addr::new(1, 1, 1, 1, 1, 1, 0xc0a8, 0x1));
-    }
-
-    // Things that might not seem like failures but are
-    #[test]
-    fn ipv6_corner_failures() {
-        // No IP address before the ::
-        assert!(Ipv6Addr::from_str("1:192.168.0.1::").is_err());
-
-        // :: must have at least 1 set of zeroes
-        assert!(Ipv6Addr::from_str("1:1:1:1::1:1:1:1").is_err());
-
-        // Need brackets for a port
-        assert!(SocketAddrV6::from_str("1:1:1:1:1:1:1:1:8080").is_err());
-    }
-}
diff --git a/library/std/src/net/parser/tests.rs b/library/std/src/net/parser/tests.rs
new file mode 100644
index 00000000000..ecf5a782c0c
--- /dev/null
+++ b/library/std/src/net/parser/tests.rs
@@ -0,0 +1,139 @@
+// FIXME: These tests are all excellent candidates for AFL fuzz testing
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::str::FromStr;
+
+const PORT: u16 = 8080;
+
+const IPV4: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1);
+const IPV4_STR: &str = "192.168.0.1";
+const IPV4_STR_PORT: &str = "192.168.0.1:8080";
+
+const IPV6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc0a8, 0x1);
+const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1";
+const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1";
+const IPV6_STR_V4: &str = "2001:db8::192.168.0.1";
+const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080";
+
+#[test]
+fn parse_ipv4() {
+    let result: Ipv4Addr = IPV4_STR.parse().unwrap();
+    assert_eq!(result, IPV4);
+
+    assert!(Ipv4Addr::from_str(IPV4_STR_PORT).is_err());
+    assert!(Ipv4Addr::from_str(IPV6_STR_FULL).is_err());
+    assert!(Ipv4Addr::from_str(IPV6_STR_COMPRESS).is_err());
+    assert!(Ipv4Addr::from_str(IPV6_STR_V4).is_err());
+    assert!(Ipv4Addr::from_str(IPV6_STR_PORT).is_err());
+}
+
+#[test]
+fn parse_ipv6() {
+    let result: Ipv6Addr = IPV6_STR_FULL.parse().unwrap();
+    assert_eq!(result, IPV6);
+
+    let result: Ipv6Addr = IPV6_STR_COMPRESS.parse().unwrap();
+    assert_eq!(result, IPV6);
+
+    let result: Ipv6Addr = IPV6_STR_V4.parse().unwrap();
+    assert_eq!(result, IPV6);
+
+    assert!(Ipv6Addr::from_str(IPV4_STR).is_err());
+    assert!(Ipv6Addr::from_str(IPV4_STR_PORT).is_err());
+    assert!(Ipv6Addr::from_str(IPV6_STR_PORT).is_err());
+}
+
+#[test]
+fn parse_ip() {
+    let result: IpAddr = IPV4_STR.parse().unwrap();
+    assert_eq!(result, IpAddr::from(IPV4));
+
+    let result: IpAddr = IPV6_STR_FULL.parse().unwrap();
+    assert_eq!(result, IpAddr::from(IPV6));
+
+    let result: IpAddr = IPV6_STR_COMPRESS.parse().unwrap();
+    assert_eq!(result, IpAddr::from(IPV6));
+
+    let result: IpAddr = IPV6_STR_V4.parse().unwrap();
+    assert_eq!(result, IpAddr::from(IPV6));
+
+    assert!(IpAddr::from_str(IPV4_STR_PORT).is_err());
+    assert!(IpAddr::from_str(IPV6_STR_PORT).is_err());
+}
+
+#[test]
+fn parse_socket_v4() {
+    let result: SocketAddrV4 = IPV4_STR_PORT.parse().unwrap();
+    assert_eq!(result, SocketAddrV4::new(IPV4, PORT));
+
+    assert!(SocketAddrV4::from_str(IPV4_STR).is_err());
+    assert!(SocketAddrV4::from_str(IPV6_STR_FULL).is_err());
+    assert!(SocketAddrV4::from_str(IPV6_STR_COMPRESS).is_err());
+    assert!(SocketAddrV4::from_str(IPV6_STR_V4).is_err());
+    assert!(SocketAddrV4::from_str(IPV6_STR_PORT).is_err());
+}
+
+#[test]
+fn parse_socket_v6() {
+    let result: SocketAddrV6 = IPV6_STR_PORT.parse().unwrap();
+    assert_eq!(result, SocketAddrV6::new(IPV6, PORT, 0, 0));
+
+    assert!(SocketAddrV6::from_str(IPV4_STR).is_err());
+    assert!(SocketAddrV6::from_str(IPV4_STR_PORT).is_err());
+    assert!(SocketAddrV6::from_str(IPV6_STR_FULL).is_err());
+    assert!(SocketAddrV6::from_str(IPV6_STR_COMPRESS).is_err());
+    assert!(SocketAddrV6::from_str(IPV6_STR_V4).is_err());
+}
+
+#[test]
+fn parse_socket() {
+    let result: SocketAddr = IPV4_STR_PORT.parse().unwrap();
+    assert_eq!(result, SocketAddr::from((IPV4, PORT)));
+
+    let result: SocketAddr = IPV6_STR_PORT.parse().unwrap();
+    assert_eq!(result, SocketAddr::from((IPV6, PORT)));
+
+    assert!(SocketAddr::from_str(IPV4_STR).is_err());
+    assert!(SocketAddr::from_str(IPV6_STR_FULL).is_err());
+    assert!(SocketAddr::from_str(IPV6_STR_COMPRESS).is_err());
+    assert!(SocketAddr::from_str(IPV6_STR_V4).is_err());
+}
+
+#[test]
+fn ipv6_corner_cases() {
+    let result: Ipv6Addr = "1::".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0));
+
+    let result: Ipv6Addr = "1:1::".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(1, 1, 0, 0, 0, 0, 0, 0));
+
+    let result: Ipv6Addr = "::1".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+
+    let result: Ipv6Addr = "::1:1".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 1, 1));
+
+    let result: Ipv6Addr = "::".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+
+    let result: Ipv6Addr = "::192.168.0.1".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc0a8, 0x1));
+
+    let result: Ipv6Addr = "::1:192.168.0.1".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 1, 0xc0a8, 0x1));
+
+    let result: Ipv6Addr = "1:1:1:1:1:1:192.168.0.1".parse().unwrap();
+    assert_eq!(result, Ipv6Addr::new(1, 1, 1, 1, 1, 1, 0xc0a8, 0x1));
+}
+
+// Things that might not seem like failures but are
+#[test]
+fn ipv6_corner_failures() {
+    // No IP address before the ::
+    assert!(Ipv6Addr::from_str("1:192.168.0.1::").is_err());
+
+    // :: must have at least 1 set of zeroes
+    assert!(Ipv6Addr::from_str("1:1:1:1::1:1:1:1").is_err());
+
+    // Need brackets for a port
+    assert!(SocketAddrV6::from_str("1:1:1:1:1:1:1:1:8080").is_err());
+}
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index a76c9c46c05..58c6343ea34 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -1,4 +1,8 @@
 #![deny(unsafe_op_in_unsafe_fn)]
+
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+mod tests;
+
 use crate::io::prelude::*;
 
 use crate::fmt;
@@ -936,869 +940,3 @@ impl fmt::Debug for TcpListener {
         self.0.fmt(f)
     }
 }
-
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
-mod tests {
-    use crate::fmt;
-    use crate::io::prelude::*;
-    use crate::io::{ErrorKind, IoSlice, IoSliceMut};
-    use crate::net::test::{next_test_ip4, next_test_ip6};
-    use crate::net::*;
-    use crate::sync::mpsc::channel;
-    use crate::thread;
-    use crate::time::{Duration, Instant};
-
-    fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
-        f(next_test_ip4());
-        f(next_test_ip6());
-    }
-
-    macro_rules! t {
-        ($e:expr) => {
-            match $e {
-                Ok(t) => t,
-                Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
-            }
-        };
-    }
-
-    #[test]
-    fn bind_error() {
-        match TcpListener::bind("1.1.1.1:9999") {
-            Ok(..) => panic!(),
-            Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
-        }
-    }
-
-    #[test]
-    fn connect_error() {
-        match TcpStream::connect("0.0.0.0:1") {
-            Ok(..) => panic!(),
-            Err(e) => assert!(
-                e.kind() == ErrorKind::ConnectionRefused
-                    || e.kind() == ErrorKind::InvalidInput
-                    || e.kind() == ErrorKind::AddrInUse
-                    || e.kind() == ErrorKind::AddrNotAvailable,
-                "bad error: {} {:?}",
-                e,
-                e.kind()
-            ),
-        }
-    }
-
-    #[test]
-    fn listen_localhost() {
-        let socket_addr = next_test_ip4();
-        let listener = t!(TcpListener::bind(&socket_addr));
-
-        let _t = thread::spawn(move || {
-            let mut stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
-            t!(stream.write(&[144]));
-        });
-
-        let mut stream = t!(listener.accept()).0;
-        let mut buf = [0];
-        t!(stream.read(&mut buf));
-        assert!(buf[0] == 144);
-    }
-
-    #[test]
-    fn connect_loopback() {
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let _t = thread::spawn(move || {
-                let host = match addr {
-                    SocketAddr::V4(..) => "127.0.0.1",
-                    SocketAddr::V6(..) => "::1",
-                };
-                let mut stream = t!(TcpStream::connect(&(host, addr.port())));
-                t!(stream.write(&[66]));
-            });
-
-            let mut stream = t!(acceptor.accept()).0;
-            let mut buf = [0];
-            t!(stream.read(&mut buf));
-            assert!(buf[0] == 66);
-        })
-    }
-
-    #[test]
-    fn smoke_test() {
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let (tx, rx) = channel();
-            let _t = thread::spawn(move || {
-                let mut stream = t!(TcpStream::connect(&addr));
-                t!(stream.write(&[99]));
-                tx.send(t!(stream.local_addr())).unwrap();
-            });
-
-            let (mut stream, addr) = t!(acceptor.accept());
-            let mut buf = [0];
-            t!(stream.read(&mut buf));
-            assert!(buf[0] == 99);
-            assert_eq!(addr, t!(rx.recv()));
-        })
-    }
-
-    #[test]
-    fn read_eof() {
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let _t = thread::spawn(move || {
-                let _stream = t!(TcpStream::connect(&addr));
-                // Close
-            });
-
-            let mut stream = t!(acceptor.accept()).0;
-            let mut buf = [0];
-            let nread = t!(stream.read(&mut buf));
-            assert_eq!(nread, 0);
-            let nread = t!(stream.read(&mut buf));
-            assert_eq!(nread, 0);
-        })
-    }
-
-    #[test]
-    fn write_close() {
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let (tx, rx) = channel();
-            let _t = thread::spawn(move || {
-                drop(t!(TcpStream::connect(&addr)));
-                tx.send(()).unwrap();
-            });
-
-            let mut stream = t!(acceptor.accept()).0;
-            rx.recv().unwrap();
-            let buf = [0];
-            match stream.write(&buf) {
-                Ok(..) => {}
-                Err(e) => {
-                    assert!(
-                        e.kind() == ErrorKind::ConnectionReset
-                            || e.kind() == ErrorKind::BrokenPipe
-                            || e.kind() == ErrorKind::ConnectionAborted,
-                        "unknown error: {}",
-                        e
-                    );
-                }
-            }
-        })
-    }
-
-    #[test]
-    fn multiple_connect_serial() {
-        each_ip(&mut |addr| {
-            let max = 10;
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let _t = thread::spawn(move || {
-                for _ in 0..max {
-                    let mut stream = t!(TcpStream::connect(&addr));
-                    t!(stream.write(&[99]));
-                }
-            });
-
-            for stream in acceptor.incoming().take(max) {
-                let mut stream = t!(stream);
-                let mut buf = [0];
-                t!(stream.read(&mut buf));
-                assert_eq!(buf[0], 99);
-            }
-        })
-    }
-
-    #[test]
-    fn multiple_connect_interleaved_greedy_schedule() {
-        const MAX: usize = 10;
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let _t = thread::spawn(move || {
-                let acceptor = acceptor;
-                for (i, stream) in acceptor.incoming().enumerate().take(MAX) {
-                    // Start another thread to handle the connection
-                    let _t = thread::spawn(move || {
-                        let mut stream = t!(stream);
-                        let mut buf = [0];
-                        t!(stream.read(&mut buf));
-                        assert!(buf[0] == i as u8);
-                    });
-                }
-            });
-
-            connect(0, addr);
-        });
-
-        fn connect(i: usize, addr: SocketAddr) {
-            if i == MAX {
-                return;
-            }
-
-            let t = thread::spawn(move || {
-                let mut stream = t!(TcpStream::connect(&addr));
-                // Connect again before writing
-                connect(i + 1, addr);
-                t!(stream.write(&[i as u8]));
-            });
-            t.join().ok().expect("thread panicked");
-        }
-    }
-
-    #[test]
-    fn multiple_connect_interleaved_lazy_schedule() {
-        const MAX: usize = 10;
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let _t = thread::spawn(move || {
-                for stream in acceptor.incoming().take(MAX) {
-                    // Start another thread to handle the connection
-                    let _t = thread::spawn(move || {
-                        let mut stream = t!(stream);
-                        let mut buf = [0];
-                        t!(stream.read(&mut buf));
-                        assert!(buf[0] == 99);
-                    });
-                }
-            });
-
-            connect(0, addr);
-        });
-
-        fn connect(i: usize, addr: SocketAddr) {
-            if i == MAX {
-                return;
-            }
-
-            let t = thread::spawn(move || {
-                let mut stream = t!(TcpStream::connect(&addr));
-                connect(i + 1, addr);
-                t!(stream.write(&[99]));
-            });
-            t.join().ok().expect("thread panicked");
-        }
-    }
-
-    #[test]
-    fn socket_and_peer_name() {
-        each_ip(&mut |addr| {
-            let listener = t!(TcpListener::bind(&addr));
-            let so_name = t!(listener.local_addr());
-            assert_eq!(addr, so_name);
-            let _t = thread::spawn(move || {
-                t!(listener.accept());
-            });
-
-            let stream = t!(TcpStream::connect(&addr));
-            assert_eq!(addr, t!(stream.peer_addr()));
-        })
-    }
-
-    #[test]
-    fn partial_read() {
-        each_ip(&mut |addr| {
-            let (tx, rx) = channel();
-            let srv = t!(TcpListener::bind(&addr));
-            let _t = thread::spawn(move || {
-                let mut cl = t!(srv.accept()).0;
-                cl.write(&[10]).unwrap();
-                let mut b = [0];
-                t!(cl.read(&mut b));
-                tx.send(()).unwrap();
-            });
-
-            let mut c = t!(TcpStream::connect(&addr));
-            let mut b = [0; 10];
-            assert_eq!(c.read(&mut b).unwrap(), 1);
-            t!(c.write(&[1]));
-            rx.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn read_vectored() {
-        each_ip(&mut |addr| {
-            let srv = t!(TcpListener::bind(&addr));
-            let mut s1 = t!(TcpStream::connect(&addr));
-            let mut s2 = t!(srv.accept()).0;
-
-            let len = s1.write(&[10, 11, 12]).unwrap();
-            assert_eq!(len, 3);
-
-            let mut a = [];
-            let mut b = [0];
-            let mut c = [0; 3];
-            let len = t!(s2.read_vectored(&mut [
-                IoSliceMut::new(&mut a),
-                IoSliceMut::new(&mut b),
-                IoSliceMut::new(&mut c)
-            ],));
-            assert!(len > 0);
-            assert_eq!(b, [10]);
-            // some implementations don't support readv, so we may only fill the first buffer
-            assert!(len == 1 || c == [11, 12, 0]);
-        })
-    }
-
-    #[test]
-    fn write_vectored() {
-        each_ip(&mut |addr| {
-            let srv = t!(TcpListener::bind(&addr));
-            let mut s1 = t!(TcpStream::connect(&addr));
-            let mut s2 = t!(srv.accept()).0;
-
-            let a = [];
-            let b = [10];
-            let c = [11, 12];
-            t!(s1.write_vectored(&[IoSlice::new(&a), IoSlice::new(&b), IoSlice::new(&c)]));
-
-            let mut buf = [0; 4];
-            let len = t!(s2.read(&mut buf));
-            // some implementations don't support writev, so we may only write the first buffer
-            if len == 1 {
-                assert_eq!(buf, [10, 0, 0, 0]);
-            } else {
-                assert_eq!(len, 3);
-                assert_eq!(buf, [10, 11, 12, 0]);
-            }
-        })
-    }
-
-    #[test]
-    fn double_bind() {
-        each_ip(&mut |addr| {
-            let listener1 = t!(TcpListener::bind(&addr));
-            match TcpListener::bind(&addr) {
-                Ok(listener2) => panic!(
-                    "This system (perhaps due to options set by TcpListener::bind) \
-                     permits double binding: {:?} and {:?}",
-                    listener1, listener2
-                ),
-                Err(e) => {
-                    assert!(
-                        e.kind() == ErrorKind::ConnectionRefused
-                            || e.kind() == ErrorKind::Other
-                            || e.kind() == ErrorKind::AddrInUse,
-                        "unknown error: {} {:?}",
-                        e,
-                        e.kind()
-                    );
-                }
-            }
-        })
-    }
-
-    #[test]
-    fn tcp_clone_smoke() {
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let _t = thread::spawn(move || {
-                let mut s = t!(TcpStream::connect(&addr));
-                let mut buf = [0, 0];
-                assert_eq!(s.read(&mut buf).unwrap(), 1);
-                assert_eq!(buf[0], 1);
-                t!(s.write(&[2]));
-            });
-
-            let mut s1 = t!(acceptor.accept()).0;
-            let s2 = t!(s1.try_clone());
-
-            let (tx1, rx1) = channel();
-            let (tx2, rx2) = channel();
-            let _t = thread::spawn(move || {
-                let mut s2 = s2;
-                rx1.recv().unwrap();
-                t!(s2.write(&[1]));
-                tx2.send(()).unwrap();
-            });
-            tx1.send(()).unwrap();
-            let mut buf = [0, 0];
-            assert_eq!(s1.read(&mut buf).unwrap(), 1);
-            rx2.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn tcp_clone_two_read() {
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-            let (tx1, rx) = channel();
-            let tx2 = tx1.clone();
-
-            let _t = thread::spawn(move || {
-                let mut s = t!(TcpStream::connect(&addr));
-                t!(s.write(&[1]));
-                rx.recv().unwrap();
-                t!(s.write(&[2]));
-                rx.recv().unwrap();
-            });
-
-            let mut s1 = t!(acceptor.accept()).0;
-            let s2 = t!(s1.try_clone());
-
-            let (done, rx) = channel();
-            let _t = thread::spawn(move || {
-                let mut s2 = s2;
-                let mut buf = [0, 0];
-                t!(s2.read(&mut buf));
-                tx2.send(()).unwrap();
-                done.send(()).unwrap();
-            });
-            let mut buf = [0, 0];
-            t!(s1.read(&mut buf));
-            tx1.send(()).unwrap();
-
-            rx.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn tcp_clone_two_write() {
-        each_ip(&mut |addr| {
-            let acceptor = t!(TcpListener::bind(&addr));
-
-            let _t = thread::spawn(move || {
-                let mut s = t!(TcpStream::connect(&addr));
-                let mut buf = [0, 1];
-                t!(s.read(&mut buf));
-                t!(s.read(&mut buf));
-            });
-
-            let mut s1 = t!(acceptor.accept()).0;
-            let s2 = t!(s1.try_clone());
-
-            let (done, rx) = channel();
-            let _t = thread::spawn(move || {
-                let mut s2 = s2;
-                t!(s2.write(&[1]));
-                done.send(()).unwrap();
-            });
-            t!(s1.write(&[2]));
-
-            rx.recv().unwrap();
-        })
-    }
-
-    #[test]
-    // FIXME: https://github.com/fortanix/rust-sgx/issues/110
-    #[cfg_attr(target_env = "sgx", ignore)]
-    fn shutdown_smoke() {
-        each_ip(&mut |addr| {
-            let a = t!(TcpListener::bind(&addr));
-            let _t = thread::spawn(move || {
-                let mut c = t!(a.accept()).0;
-                let mut b = [0];
-                assert_eq!(c.read(&mut b).unwrap(), 0);
-                t!(c.write(&[1]));
-            });
-
-            let mut s = t!(TcpStream::connect(&addr));
-            t!(s.shutdown(Shutdown::Write));
-            assert!(s.write(&[1]).is_err());
-            let mut b = [0, 0];
-            assert_eq!(t!(s.read(&mut b)), 1);
-            assert_eq!(b[0], 1);
-        })
-    }
-
-    #[test]
-    // FIXME: https://github.com/fortanix/rust-sgx/issues/110
-    #[cfg_attr(target_env = "sgx", ignore)]
-    fn close_readwrite_smoke() {
-        each_ip(&mut |addr| {
-            let a = t!(TcpListener::bind(&addr));
-            let (tx, rx) = channel::<()>();
-            let _t = thread::spawn(move || {
-                let _s = t!(a.accept());
-                let _ = rx.recv();
-            });
-
-            let mut b = [0];
-            let mut s = t!(TcpStream::connect(&addr));
-            let mut s2 = t!(s.try_clone());
-
-            // closing should prevent reads/writes
-            t!(s.shutdown(Shutdown::Write));
-            assert!(s.write(&[0]).is_err());
-            t!(s.shutdown(Shutdown::Read));
-            assert_eq!(s.read(&mut b).unwrap(), 0);
-
-            // closing should affect previous handles
-            assert!(s2.write(&[0]).is_err());
-            assert_eq!(s2.read(&mut b).unwrap(), 0);
-
-            // closing should affect new handles
-            let mut s3 = t!(s.try_clone());
-            assert!(s3.write(&[0]).is_err());
-            assert_eq!(s3.read(&mut b).unwrap(), 0);
-
-            // make sure these don't die
-            let _ = s2.shutdown(Shutdown::Read);
-            let _ = s2.shutdown(Shutdown::Write);
-            let _ = s3.shutdown(Shutdown::Read);
-            let _ = s3.shutdown(Shutdown::Write);
-            drop(tx);
-        })
-    }
-
-    #[test]
-    #[cfg(unix)] // test doesn't work on Windows, see #31657
-    fn close_read_wakes_up() {
-        each_ip(&mut |addr| {
-            let a = t!(TcpListener::bind(&addr));
-            let (tx1, rx) = channel::<()>();
-            let _t = thread::spawn(move || {
-                let _s = t!(a.accept());
-                let _ = rx.recv();
-            });
-
-            let s = t!(TcpStream::connect(&addr));
-            let s2 = t!(s.try_clone());
-            let (tx, rx) = channel();
-            let _t = thread::spawn(move || {
-                let mut s2 = s2;
-                assert_eq!(t!(s2.read(&mut [0])), 0);
-                tx.send(()).unwrap();
-            });
-            // this should wake up the child thread
-            t!(s.shutdown(Shutdown::Read));
-
-            // this test will never finish if the child doesn't wake up
-            rx.recv().unwrap();
-            drop(tx1);
-        })
-    }
-
-    #[test]
-    fn clone_while_reading() {
-        each_ip(&mut |addr| {
-            let accept = t!(TcpListener::bind(&addr));
-
-            // Enqueue a thread to write to a socket
-            let (tx, rx) = channel();
-            let (txdone, rxdone) = channel();
-            let txdone2 = txdone.clone();
-            let _t = thread::spawn(move || {
-                let mut tcp = t!(TcpStream::connect(&addr));
-                rx.recv().unwrap();
-                t!(tcp.write(&[0]));
-                txdone2.send(()).unwrap();
-            });
-
-            // Spawn off a reading clone
-            let tcp = t!(accept.accept()).0;
-            let tcp2 = t!(tcp.try_clone());
-            let txdone3 = txdone.clone();
-            let _t = thread::spawn(move || {
-                let mut tcp2 = tcp2;
-                t!(tcp2.read(&mut [0]));
-                txdone3.send(()).unwrap();
-            });
-
-            // Try to ensure that the reading clone is indeed reading
-            for _ in 0..50 {
-                thread::yield_now();
-            }
-
-            // clone the handle again while it's reading, then let it finish the
-            // read.
-            let _ = t!(tcp.try_clone());
-            tx.send(()).unwrap();
-            rxdone.recv().unwrap();
-            rxdone.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn clone_accept_smoke() {
-        each_ip(&mut |addr| {
-            let a = t!(TcpListener::bind(&addr));
-            let a2 = t!(a.try_clone());
-
-            let _t = thread::spawn(move || {
-                let _ = TcpStream::connect(&addr);
-            });
-            let _t = thread::spawn(move || {
-                let _ = TcpStream::connect(&addr);
-            });
-
-            t!(a.accept());
-            t!(a2.accept());
-        })
-    }
-
-    #[test]
-    fn clone_accept_concurrent() {
-        each_ip(&mut |addr| {
-            let a = t!(TcpListener::bind(&addr));
-            let a2 = t!(a.try_clone());
-
-            let (tx, rx) = channel();
-            let tx2 = tx.clone();
-
-            let _t = thread::spawn(move || {
-                tx.send(t!(a.accept())).unwrap();
-            });
-            let _t = thread::spawn(move || {
-                tx2.send(t!(a2.accept())).unwrap();
-            });
-
-            let _t = thread::spawn(move || {
-                let _ = TcpStream::connect(&addr);
-            });
-            let _t = thread::spawn(move || {
-                let _ = TcpStream::connect(&addr);
-            });
-
-            rx.recv().unwrap();
-            rx.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn debug() {
-        #[cfg(not(target_env = "sgx"))]
-        fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
-            addr
-        }
-        #[cfg(target_env = "sgx")]
-        fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
-            addr.to_string()
-        }
-
-        #[cfg(target_env = "sgx")]
-        use crate::os::fortanix_sgx::io::AsRawFd;
-        #[cfg(unix)]
-        use crate::os::unix::io::AsRawFd;
-        #[cfg(not(windows))]
-        fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
-            addr.as_raw_fd()
-        }
-        #[cfg(windows)]
-        fn render_inner(addr: &dyn crate::os::windows::io::AsRawSocket) -> impl fmt::Debug {
-            addr.as_raw_socket()
-        }
-
-        let inner_name = if cfg!(windows) { "socket" } else { "fd" };
-        let socket_addr = next_test_ip4();
-
-        let listener = t!(TcpListener::bind(&socket_addr));
-        let compare = format!(
-            "TcpListener {{ addr: {:?}, {}: {:?} }}",
-            render_socket_addr(&socket_addr),
-            inner_name,
-            render_inner(&listener)
-        );
-        assert_eq!(format!("{:?}", listener), compare);
-
-        let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
-        let compare = format!(
-            "TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
-            render_socket_addr(&stream.local_addr().unwrap()),
-            render_socket_addr(&stream.peer_addr().unwrap()),
-            inner_name,
-            render_inner(&stream)
-        );
-        assert_eq!(format!("{:?}", stream), compare);
-    }
-
-    // FIXME: re-enabled openbsd tests once their socket timeout code
-    //        no longer has rounding errors.
-    // VxWorks ignores SO_SNDTIMEO.
-    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
-    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
-    #[test]
-    fn timeouts() {
-        let addr = next_test_ip4();
-        let listener = t!(TcpListener::bind(&addr));
-
-        let stream = t!(TcpStream::connect(&("localhost", addr.port())));
-        let dur = Duration::new(15410, 0);
-
-        assert_eq!(None, t!(stream.read_timeout()));
-
-        t!(stream.set_read_timeout(Some(dur)));
-        assert_eq!(Some(dur), t!(stream.read_timeout()));
-
-        assert_eq!(None, t!(stream.write_timeout()));
-
-        t!(stream.set_write_timeout(Some(dur)));
-        assert_eq!(Some(dur), t!(stream.write_timeout()));
-
-        t!(stream.set_read_timeout(None));
-        assert_eq!(None, t!(stream.read_timeout()));
-
-        t!(stream.set_write_timeout(None));
-        assert_eq!(None, t!(stream.write_timeout()));
-        drop(listener);
-    }
-
-    #[test]
-    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
-    fn test_read_timeout() {
-        let addr = next_test_ip4();
-        let listener = t!(TcpListener::bind(&addr));
-
-        let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
-        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
-
-        let mut buf = [0; 10];
-        let start = Instant::now();
-        let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
-        assert!(
-            kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
-            "unexpected_error: {:?}",
-            kind
-        );
-        assert!(start.elapsed() > Duration::from_millis(400));
-        drop(listener);
-    }
-
-    #[test]
-    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
-    fn test_read_with_timeout() {
-        let addr = next_test_ip4();
-        let listener = t!(TcpListener::bind(&addr));
-
-        let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
-        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
-
-        let mut other_end = t!(listener.accept()).0;
-        t!(other_end.write_all(b"hello world"));
-
-        let mut buf = [0; 11];
-        t!(stream.read(&mut buf));
-        assert_eq!(b"hello world", &buf[..]);
-
-        let start = Instant::now();
-        let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
-        assert!(
-            kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
-            "unexpected_error: {:?}",
-            kind
-        );
-        assert!(start.elapsed() > Duration::from_millis(400));
-        drop(listener);
-    }
-
-    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
-    // when passed zero Durations
-    #[test]
-    fn test_timeout_zero_duration() {
-        let addr = next_test_ip4();
-
-        let listener = t!(TcpListener::bind(&addr));
-        let stream = t!(TcpStream::connect(&addr));
-
-        let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-
-        let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-
-        drop(listener);
-    }
-
-    #[test]
-    #[cfg_attr(target_env = "sgx", ignore)]
-    fn nodelay() {
-        let addr = next_test_ip4();
-        let _listener = t!(TcpListener::bind(&addr));
-
-        let stream = t!(TcpStream::connect(&("localhost", addr.port())));
-
-        assert_eq!(false, t!(stream.nodelay()));
-        t!(stream.set_nodelay(true));
-        assert_eq!(true, t!(stream.nodelay()));
-        t!(stream.set_nodelay(false));
-        assert_eq!(false, t!(stream.nodelay()));
-    }
-
-    #[test]
-    #[cfg_attr(target_env = "sgx", ignore)]
-    fn ttl() {
-        let ttl = 100;
-
-        let addr = next_test_ip4();
-        let listener = t!(TcpListener::bind(&addr));
-
-        t!(listener.set_ttl(ttl));
-        assert_eq!(ttl, t!(listener.ttl()));
-
-        let stream = t!(TcpStream::connect(&("localhost", addr.port())));
-
-        t!(stream.set_ttl(ttl));
-        assert_eq!(ttl, t!(stream.ttl()));
-    }
-
-    #[test]
-    #[cfg_attr(target_env = "sgx", ignore)]
-    fn set_nonblocking() {
-        let addr = next_test_ip4();
-        let listener = t!(TcpListener::bind(&addr));
-
-        t!(listener.set_nonblocking(true));
-        t!(listener.set_nonblocking(false));
-
-        let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
-
-        t!(stream.set_nonblocking(false));
-        t!(stream.set_nonblocking(true));
-
-        let mut buf = [0];
-        match stream.read(&mut buf) {
-            Ok(_) => panic!("expected error"),
-            Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
-            Err(e) => panic!("unexpected error {}", e),
-        }
-    }
-
-    #[test]
-    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
-    fn peek() {
-        each_ip(&mut |addr| {
-            let (txdone, rxdone) = channel();
-
-            let srv = t!(TcpListener::bind(&addr));
-            let _t = thread::spawn(move || {
-                let mut cl = t!(srv.accept()).0;
-                cl.write(&[1, 3, 3, 7]).unwrap();
-                t!(rxdone.recv());
-            });
-
-            let mut c = t!(TcpStream::connect(&addr));
-            let mut b = [0; 10];
-            for _ in 1..3 {
-                let len = c.peek(&mut b).unwrap();
-                assert_eq!(len, 4);
-            }
-            let len = c.read(&mut b).unwrap();
-            assert_eq!(len, 4);
-
-            t!(c.set_nonblocking(true));
-            match c.peek(&mut b) {
-                Ok(_) => panic!("expected error"),
-                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
-                Err(e) => panic!("unexpected error {}", e),
-            }
-            t!(txdone.send(()));
-        })
-    }
-
-    #[test]
-    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
-    fn connect_timeout_valid() {
-        let listener = TcpListener::bind("127.0.0.1:0").unwrap();
-        let addr = listener.local_addr().unwrap();
-        TcpStream::connect_timeout(&addr, Duration::from_secs(2)).unwrap();
-    }
-}
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
new file mode 100644
index 00000000000..abe9bc24cec
--- /dev/null
+++ b/library/std/src/net/tcp/tests.rs
@@ -0,0 +1,862 @@
+use crate::fmt;
+use crate::io::prelude::*;
+use crate::io::{ErrorKind, IoSlice, IoSliceMut};
+use crate::net::test::{next_test_ip4, next_test_ip6};
+use crate::net::*;
+use crate::sync::mpsc::channel;
+use crate::thread;
+use crate::time::{Duration, Instant};
+
+fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
+    f(next_test_ip4());
+    f(next_test_ip6());
+}
+
+macro_rules! t {
+    ($e:expr) => {
+        match $e {
+            Ok(t) => t,
+            Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
+        }
+    };
+}
+
+#[test]
+fn bind_error() {
+    match TcpListener::bind("1.1.1.1:9999") {
+        Ok(..) => panic!(),
+        Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
+    }
+}
+
+#[test]
+fn connect_error() {
+    match TcpStream::connect("0.0.0.0:1") {
+        Ok(..) => panic!(),
+        Err(e) => assert!(
+            e.kind() == ErrorKind::ConnectionRefused
+                || e.kind() == ErrorKind::InvalidInput
+                || e.kind() == ErrorKind::AddrInUse
+                || e.kind() == ErrorKind::AddrNotAvailable,
+            "bad error: {} {:?}",
+            e,
+            e.kind()
+        ),
+    }
+}
+
+#[test]
+fn listen_localhost() {
+    let socket_addr = next_test_ip4();
+    let listener = t!(TcpListener::bind(&socket_addr));
+
+    let _t = thread::spawn(move || {
+        let mut stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
+        t!(stream.write(&[144]));
+    });
+
+    let mut stream = t!(listener.accept()).0;
+    let mut buf = [0];
+    t!(stream.read(&mut buf));
+    assert!(buf[0] == 144);
+}
+
+#[test]
+fn connect_loopback() {
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let _t = thread::spawn(move || {
+            let host = match addr {
+                SocketAddr::V4(..) => "127.0.0.1",
+                SocketAddr::V6(..) => "::1",
+            };
+            let mut stream = t!(TcpStream::connect(&(host, addr.port())));
+            t!(stream.write(&[66]));
+        });
+
+        let mut stream = t!(acceptor.accept()).0;
+        let mut buf = [0];
+        t!(stream.read(&mut buf));
+        assert!(buf[0] == 66);
+    })
+}
+
+#[test]
+fn smoke_test() {
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let (tx, rx) = channel();
+        let _t = thread::spawn(move || {
+            let mut stream = t!(TcpStream::connect(&addr));
+            t!(stream.write(&[99]));
+            tx.send(t!(stream.local_addr())).unwrap();
+        });
+
+        let (mut stream, addr) = t!(acceptor.accept());
+        let mut buf = [0];
+        t!(stream.read(&mut buf));
+        assert!(buf[0] == 99);
+        assert_eq!(addr, t!(rx.recv()));
+    })
+}
+
+#[test]
+fn read_eof() {
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let _t = thread::spawn(move || {
+            let _stream = t!(TcpStream::connect(&addr));
+            // Close
+        });
+
+        let mut stream = t!(acceptor.accept()).0;
+        let mut buf = [0];
+        let nread = t!(stream.read(&mut buf));
+        assert_eq!(nread, 0);
+        let nread = t!(stream.read(&mut buf));
+        assert_eq!(nread, 0);
+    })
+}
+
+#[test]
+fn write_close() {
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let (tx, rx) = channel();
+        let _t = thread::spawn(move || {
+            drop(t!(TcpStream::connect(&addr)));
+            tx.send(()).unwrap();
+        });
+
+        let mut stream = t!(acceptor.accept()).0;
+        rx.recv().unwrap();
+        let buf = [0];
+        match stream.write(&buf) {
+            Ok(..) => {}
+            Err(e) => {
+                assert!(
+                    e.kind() == ErrorKind::ConnectionReset
+                        || e.kind() == ErrorKind::BrokenPipe
+                        || e.kind() == ErrorKind::ConnectionAborted,
+                    "unknown error: {}",
+                    e
+                );
+            }
+        }
+    })
+}
+
+#[test]
+fn multiple_connect_serial() {
+    each_ip(&mut |addr| {
+        let max = 10;
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let _t = thread::spawn(move || {
+            for _ in 0..max {
+                let mut stream = t!(TcpStream::connect(&addr));
+                t!(stream.write(&[99]));
+            }
+        });
+
+        for stream in acceptor.incoming().take(max) {
+            let mut stream = t!(stream);
+            let mut buf = [0];
+            t!(stream.read(&mut buf));
+            assert_eq!(buf[0], 99);
+        }
+    })
+}
+
+#[test]
+fn multiple_connect_interleaved_greedy_schedule() {
+    const MAX: usize = 10;
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let _t = thread::spawn(move || {
+            let acceptor = acceptor;
+            for (i, stream) in acceptor.incoming().enumerate().take(MAX) {
+                // Start another thread to handle the connection
+                let _t = thread::spawn(move || {
+                    let mut stream = t!(stream);
+                    let mut buf = [0];
+                    t!(stream.read(&mut buf));
+                    assert!(buf[0] == i as u8);
+                });
+            }
+        });
+
+        connect(0, addr);
+    });
+
+    fn connect(i: usize, addr: SocketAddr) {
+        if i == MAX {
+            return;
+        }
+
+        let t = thread::spawn(move || {
+            let mut stream = t!(TcpStream::connect(&addr));
+            // Connect again before writing
+            connect(i + 1, addr);
+            t!(stream.write(&[i as u8]));
+        });
+        t.join().ok().expect("thread panicked");
+    }
+}
+
+#[test]
+fn multiple_connect_interleaved_lazy_schedule() {
+    const MAX: usize = 10;
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let _t = thread::spawn(move || {
+            for stream in acceptor.incoming().take(MAX) {
+                // Start another thread to handle the connection
+                let _t = thread::spawn(move || {
+                    let mut stream = t!(stream);
+                    let mut buf = [0];
+                    t!(stream.read(&mut buf));
+                    assert!(buf[0] == 99);
+                });
+            }
+        });
+
+        connect(0, addr);
+    });
+
+    fn connect(i: usize, addr: SocketAddr) {
+        if i == MAX {
+            return;
+        }
+
+        let t = thread::spawn(move || {
+            let mut stream = t!(TcpStream::connect(&addr));
+            connect(i + 1, addr);
+            t!(stream.write(&[99]));
+        });
+        t.join().ok().expect("thread panicked");
+    }
+}
+
+#[test]
+fn socket_and_peer_name() {
+    each_ip(&mut |addr| {
+        let listener = t!(TcpListener::bind(&addr));
+        let so_name = t!(listener.local_addr());
+        assert_eq!(addr, so_name);
+        let _t = thread::spawn(move || {
+            t!(listener.accept());
+        });
+
+        let stream = t!(TcpStream::connect(&addr));
+        assert_eq!(addr, t!(stream.peer_addr()));
+    })
+}
+
+#[test]
+fn partial_read() {
+    each_ip(&mut |addr| {
+        let (tx, rx) = channel();
+        let srv = t!(TcpListener::bind(&addr));
+        let _t = thread::spawn(move || {
+            let mut cl = t!(srv.accept()).0;
+            cl.write(&[10]).unwrap();
+            let mut b = [0];
+            t!(cl.read(&mut b));
+            tx.send(()).unwrap();
+        });
+
+        let mut c = t!(TcpStream::connect(&addr));
+        let mut b = [0; 10];
+        assert_eq!(c.read(&mut b).unwrap(), 1);
+        t!(c.write(&[1]));
+        rx.recv().unwrap();
+    })
+}
+
+#[test]
+fn read_vectored() {
+    each_ip(&mut |addr| {
+        let srv = t!(TcpListener::bind(&addr));
+        let mut s1 = t!(TcpStream::connect(&addr));
+        let mut s2 = t!(srv.accept()).0;
+
+        let len = s1.write(&[10, 11, 12]).unwrap();
+        assert_eq!(len, 3);
+
+        let mut a = [];
+        let mut b = [0];
+        let mut c = [0; 3];
+        let len = t!(s2.read_vectored(&mut [
+            IoSliceMut::new(&mut a),
+            IoSliceMut::new(&mut b),
+            IoSliceMut::new(&mut c)
+        ],));
+        assert!(len > 0);
+        assert_eq!(b, [10]);
+        // some implementations don't support readv, so we may only fill the first buffer
+        assert!(len == 1 || c == [11, 12, 0]);
+    })
+}
+
+#[test]
+fn write_vectored() {
+    each_ip(&mut |addr| {
+        let srv = t!(TcpListener::bind(&addr));
+        let mut s1 = t!(TcpStream::connect(&addr));
+        let mut s2 = t!(srv.accept()).0;
+
+        let a = [];
+        let b = [10];
+        let c = [11, 12];
+        t!(s1.write_vectored(&[IoSlice::new(&a), IoSlice::new(&b), IoSlice::new(&c)]));
+
+        let mut buf = [0; 4];
+        let len = t!(s2.read(&mut buf));
+        // some implementations don't support writev, so we may only write the first buffer
+        if len == 1 {
+            assert_eq!(buf, [10, 0, 0, 0]);
+        } else {
+            assert_eq!(len, 3);
+            assert_eq!(buf, [10, 11, 12, 0]);
+        }
+    })
+}
+
+#[test]
+fn double_bind() {
+    each_ip(&mut |addr| {
+        let listener1 = t!(TcpListener::bind(&addr));
+        match TcpListener::bind(&addr) {
+            Ok(listener2) => panic!(
+                "This system (perhaps due to options set by TcpListener::bind) \
+                 permits double binding: {:?} and {:?}",
+                listener1, listener2
+            ),
+            Err(e) => {
+                assert!(
+                    e.kind() == ErrorKind::ConnectionRefused
+                        || e.kind() == ErrorKind::Other
+                        || e.kind() == ErrorKind::AddrInUse,
+                    "unknown error: {} {:?}",
+                    e,
+                    e.kind()
+                );
+            }
+        }
+    })
+}
+
+#[test]
+fn tcp_clone_smoke() {
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let _t = thread::spawn(move || {
+            let mut s = t!(TcpStream::connect(&addr));
+            let mut buf = [0, 0];
+            assert_eq!(s.read(&mut buf).unwrap(), 1);
+            assert_eq!(buf[0], 1);
+            t!(s.write(&[2]));
+        });
+
+        let mut s1 = t!(acceptor.accept()).0;
+        let s2 = t!(s1.try_clone());
+
+        let (tx1, rx1) = channel();
+        let (tx2, rx2) = channel();
+        let _t = thread::spawn(move || {
+            let mut s2 = s2;
+            rx1.recv().unwrap();
+            t!(s2.write(&[1]));
+            tx2.send(()).unwrap();
+        });
+        tx1.send(()).unwrap();
+        let mut buf = [0, 0];
+        assert_eq!(s1.read(&mut buf).unwrap(), 1);
+        rx2.recv().unwrap();
+    })
+}
+
+#[test]
+fn tcp_clone_two_read() {
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+        let (tx1, rx) = channel();
+        let tx2 = tx1.clone();
+
+        let _t = thread::spawn(move || {
+            let mut s = t!(TcpStream::connect(&addr));
+            t!(s.write(&[1]));
+            rx.recv().unwrap();
+            t!(s.write(&[2]));
+            rx.recv().unwrap();
+        });
+
+        let mut s1 = t!(acceptor.accept()).0;
+        let s2 = t!(s1.try_clone());
+
+        let (done, rx) = channel();
+        let _t = thread::spawn(move || {
+            let mut s2 = s2;
+            let mut buf = [0, 0];
+            t!(s2.read(&mut buf));
+            tx2.send(()).unwrap();
+            done.send(()).unwrap();
+        });
+        let mut buf = [0, 0];
+        t!(s1.read(&mut buf));
+        tx1.send(()).unwrap();
+
+        rx.recv().unwrap();
+    })
+}
+
+#[test]
+fn tcp_clone_two_write() {
+    each_ip(&mut |addr| {
+        let acceptor = t!(TcpListener::bind(&addr));
+
+        let _t = thread::spawn(move || {
+            let mut s = t!(TcpStream::connect(&addr));
+            let mut buf = [0, 1];
+            t!(s.read(&mut buf));
+            t!(s.read(&mut buf));
+        });
+
+        let mut s1 = t!(acceptor.accept()).0;
+        let s2 = t!(s1.try_clone());
+
+        let (done, rx) = channel();
+        let _t = thread::spawn(move || {
+            let mut s2 = s2;
+            t!(s2.write(&[1]));
+            done.send(()).unwrap();
+        });
+        t!(s1.write(&[2]));
+
+        rx.recv().unwrap();
+    })
+}
+
+#[test]
+// FIXME: https://github.com/fortanix/rust-sgx/issues/110
+#[cfg_attr(target_env = "sgx", ignore)]
+fn shutdown_smoke() {
+    each_ip(&mut |addr| {
+        let a = t!(TcpListener::bind(&addr));
+        let _t = thread::spawn(move || {
+            let mut c = t!(a.accept()).0;
+            let mut b = [0];
+            assert_eq!(c.read(&mut b).unwrap(), 0);
+            t!(c.write(&[1]));
+        });
+
+        let mut s = t!(TcpStream::connect(&addr));
+        t!(s.shutdown(Shutdown::Write));
+        assert!(s.write(&[1]).is_err());
+        let mut b = [0, 0];
+        assert_eq!(t!(s.read(&mut b)), 1);
+        assert_eq!(b[0], 1);
+    })
+}
+
+#[test]
+// FIXME: https://github.com/fortanix/rust-sgx/issues/110
+#[cfg_attr(target_env = "sgx", ignore)]
+fn close_readwrite_smoke() {
+    each_ip(&mut |addr| {
+        let a = t!(TcpListener::bind(&addr));
+        let (tx, rx) = channel::<()>();
+        let _t = thread::spawn(move || {
+            let _s = t!(a.accept());
+            let _ = rx.recv();
+        });
+
+        let mut b = [0];
+        let mut s = t!(TcpStream::connect(&addr));
+        let mut s2 = t!(s.try_clone());
+
+        // closing should prevent reads/writes
+        t!(s.shutdown(Shutdown::Write));
+        assert!(s.write(&[0]).is_err());
+        t!(s.shutdown(Shutdown::Read));
+        assert_eq!(s.read(&mut b).unwrap(), 0);
+
+        // closing should affect previous handles
+        assert!(s2.write(&[0]).is_err());
+        assert_eq!(s2.read(&mut b).unwrap(), 0);
+
+        // closing should affect new handles
+        let mut s3 = t!(s.try_clone());
+        assert!(s3.write(&[0]).is_err());
+        assert_eq!(s3.read(&mut b).unwrap(), 0);
+
+        // make sure these don't die
+        let _ = s2.shutdown(Shutdown::Read);
+        let _ = s2.shutdown(Shutdown::Write);
+        let _ = s3.shutdown(Shutdown::Read);
+        let _ = s3.shutdown(Shutdown::Write);
+        drop(tx);
+    })
+}
+
+#[test]
+#[cfg(unix)] // test doesn't work on Windows, see #31657
+fn close_read_wakes_up() {
+    each_ip(&mut |addr| {
+        let a = t!(TcpListener::bind(&addr));
+        let (tx1, rx) = channel::<()>();
+        let _t = thread::spawn(move || {
+            let _s = t!(a.accept());
+            let _ = rx.recv();
+        });
+
+        let s = t!(TcpStream::connect(&addr));
+        let s2 = t!(s.try_clone());
+        let (tx, rx) = channel();
+        let _t = thread::spawn(move || {
+            let mut s2 = s2;
+            assert_eq!(t!(s2.read(&mut [0])), 0);
+            tx.send(()).unwrap();
+        });
+        // this should wake up the child thread
+        t!(s.shutdown(Shutdown::Read));
+
+        // this test will never finish if the child doesn't wake up
+        rx.recv().unwrap();
+        drop(tx1);
+    })
+}
+
+#[test]
+fn clone_while_reading() {
+    each_ip(&mut |addr| {
+        let accept = t!(TcpListener::bind(&addr));
+
+        // Enqueue a thread to write to a socket
+        let (tx, rx) = channel();
+        let (txdone, rxdone) = channel();
+        let txdone2 = txdone.clone();
+        let _t = thread::spawn(move || {
+            let mut tcp = t!(TcpStream::connect(&addr));
+            rx.recv().unwrap();
+            t!(tcp.write(&[0]));
+            txdone2.send(()).unwrap();
+        });
+
+        // Spawn off a reading clone
+        let tcp = t!(accept.accept()).0;
+        let tcp2 = t!(tcp.try_clone());
+        let txdone3 = txdone.clone();
+        let _t = thread::spawn(move || {
+            let mut tcp2 = tcp2;
+            t!(tcp2.read(&mut [0]));
+            txdone3.send(()).unwrap();
+        });
+
+        // Try to ensure that the reading clone is indeed reading
+        for _ in 0..50 {
+            thread::yield_now();
+        }
+
+        // clone the handle again while it's reading, then let it finish the
+        // read.
+        let _ = t!(tcp.try_clone());
+        tx.send(()).unwrap();
+        rxdone.recv().unwrap();
+        rxdone.recv().unwrap();
+    })
+}
+
+#[test]
+fn clone_accept_smoke() {
+    each_ip(&mut |addr| {
+        let a = t!(TcpListener::bind(&addr));
+        let a2 = t!(a.try_clone());
+
+        let _t = thread::spawn(move || {
+            let _ = TcpStream::connect(&addr);
+        });
+        let _t = thread::spawn(move || {
+            let _ = TcpStream::connect(&addr);
+        });
+
+        t!(a.accept());
+        t!(a2.accept());
+    })
+}
+
+#[test]
+fn clone_accept_concurrent() {
+    each_ip(&mut |addr| {
+        let a = t!(TcpListener::bind(&addr));
+        let a2 = t!(a.try_clone());
+
+        let (tx, rx) = channel();
+        let tx2 = tx.clone();
+
+        let _t = thread::spawn(move || {
+            tx.send(t!(a.accept())).unwrap();
+        });
+        let _t = thread::spawn(move || {
+            tx2.send(t!(a2.accept())).unwrap();
+        });
+
+        let _t = thread::spawn(move || {
+            let _ = TcpStream::connect(&addr);
+        });
+        let _t = thread::spawn(move || {
+            let _ = TcpStream::connect(&addr);
+        });
+
+        rx.recv().unwrap();
+        rx.recv().unwrap();
+    })
+}
+
+#[test]
+fn debug() {
+    #[cfg(not(target_env = "sgx"))]
+    fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+        addr
+    }
+    #[cfg(target_env = "sgx")]
+    fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+        addr.to_string()
+    }
+
+    #[cfg(target_env = "sgx")]
+    use crate::os::fortanix_sgx::io::AsRawFd;
+    #[cfg(unix)]
+    use crate::os::unix::io::AsRawFd;
+    #[cfg(not(windows))]
+    fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
+        addr.as_raw_fd()
+    }
+    #[cfg(windows)]
+    fn render_inner(addr: &dyn crate::os::windows::io::AsRawSocket) -> impl fmt::Debug {
+        addr.as_raw_socket()
+    }
+
+    let inner_name = if cfg!(windows) { "socket" } else { "fd" };
+    let socket_addr = next_test_ip4();
+
+    let listener = t!(TcpListener::bind(&socket_addr));
+    let compare = format!(
+        "TcpListener {{ addr: {:?}, {}: {:?} }}",
+        render_socket_addr(&socket_addr),
+        inner_name,
+        render_inner(&listener)
+    );
+    assert_eq!(format!("{:?}", listener), compare);
+
+    let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
+    let compare = format!(
+        "TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
+        render_socket_addr(&stream.local_addr().unwrap()),
+        render_socket_addr(&stream.peer_addr().unwrap()),
+        inner_name,
+        render_inner(&stream)
+    );
+    assert_eq!(format!("{:?}", stream), compare);
+}
+
+// FIXME: re-enabled openbsd tests once their socket timeout code
+//        no longer has rounding errors.
+// VxWorks ignores SO_SNDTIMEO.
+#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
+#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+#[test]
+fn timeouts() {
+    let addr = next_test_ip4();
+    let listener = t!(TcpListener::bind(&addr));
+
+    let stream = t!(TcpStream::connect(&("localhost", addr.port())));
+    let dur = Duration::new(15410, 0);
+
+    assert_eq!(None, t!(stream.read_timeout()));
+
+    t!(stream.set_read_timeout(Some(dur)));
+    assert_eq!(Some(dur), t!(stream.read_timeout()));
+
+    assert_eq!(None, t!(stream.write_timeout()));
+
+    t!(stream.set_write_timeout(Some(dur)));
+    assert_eq!(Some(dur), t!(stream.write_timeout()));
+
+    t!(stream.set_read_timeout(None));
+    assert_eq!(None, t!(stream.read_timeout()));
+
+    t!(stream.set_write_timeout(None));
+    assert_eq!(None, t!(stream.write_timeout()));
+    drop(listener);
+}
+
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+fn test_read_timeout() {
+    let addr = next_test_ip4();
+    let listener = t!(TcpListener::bind(&addr));
+
+    let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
+    t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+    let mut buf = [0; 10];
+    let start = Instant::now();
+    let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
+    assert!(
+        kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
+        "unexpected_error: {:?}",
+        kind
+    );
+    assert!(start.elapsed() > Duration::from_millis(400));
+    drop(listener);
+}
+
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+fn test_read_with_timeout() {
+    let addr = next_test_ip4();
+    let listener = t!(TcpListener::bind(&addr));
+
+    let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
+    t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+    let mut other_end = t!(listener.accept()).0;
+    t!(other_end.write_all(b"hello world"));
+
+    let mut buf = [0; 11];
+    t!(stream.read(&mut buf));
+    assert_eq!(b"hello world", &buf[..]);
+
+    let start = Instant::now();
+    let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
+    assert!(
+        kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
+        "unexpected_error: {:?}",
+        kind
+    );
+    assert!(start.elapsed() > Duration::from_millis(400));
+    drop(listener);
+}
+
+// Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+// when passed zero Durations
+#[test]
+fn test_timeout_zero_duration() {
+    let addr = next_test_ip4();
+
+    let listener = t!(TcpListener::bind(&addr));
+    let stream = t!(TcpStream::connect(&addr));
+
+    let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+    let err = result.unwrap_err();
+    assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+    let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+    let err = result.unwrap_err();
+    assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+    drop(listener);
+}
+
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)]
+fn nodelay() {
+    let addr = next_test_ip4();
+    let _listener = t!(TcpListener::bind(&addr));
+
+    let stream = t!(TcpStream::connect(&("localhost", addr.port())));
+
+    assert_eq!(false, t!(stream.nodelay()));
+    t!(stream.set_nodelay(true));
+    assert_eq!(true, t!(stream.nodelay()));
+    t!(stream.set_nodelay(false));
+    assert_eq!(false, t!(stream.nodelay()));
+}
+
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)]
+fn ttl() {
+    let ttl = 100;
+
+    let addr = next_test_ip4();
+    let listener = t!(TcpListener::bind(&addr));
+
+    t!(listener.set_ttl(ttl));
+    assert_eq!(ttl, t!(listener.ttl()));
+
+    let stream = t!(TcpStream::connect(&("localhost", addr.port())));
+
+    t!(stream.set_ttl(ttl));
+    assert_eq!(ttl, t!(stream.ttl()));
+}
+
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)]
+fn set_nonblocking() {
+    let addr = next_test_ip4();
+    let listener = t!(TcpListener::bind(&addr));
+
+    t!(listener.set_nonblocking(true));
+    t!(listener.set_nonblocking(false));
+
+    let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
+
+    t!(stream.set_nonblocking(false));
+    t!(stream.set_nonblocking(true));
+
+    let mut buf = [0];
+    match stream.read(&mut buf) {
+        Ok(_) => panic!("expected error"),
+        Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
+        Err(e) => panic!("unexpected error {}", e),
+    }
+}
+
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+fn peek() {
+    each_ip(&mut |addr| {
+        let (txdone, rxdone) = channel();
+
+        let srv = t!(TcpListener::bind(&addr));
+        let _t = thread::spawn(move || {
+            let mut cl = t!(srv.accept()).0;
+            cl.write(&[1, 3, 3, 7]).unwrap();
+            t!(rxdone.recv());
+        });
+
+        let mut c = t!(TcpStream::connect(&addr));
+        let mut b = [0; 10];
+        for _ in 1..3 {
+            let len = c.peek(&mut b).unwrap();
+            assert_eq!(len, 4);
+        }
+        let len = c.read(&mut b).unwrap();
+        assert_eq!(len, 4);
+
+        t!(c.set_nonblocking(true));
+        match c.peek(&mut b) {
+            Ok(_) => panic!("expected error"),
+            Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
+            Err(e) => panic!("unexpected error {}", e),
+        }
+        t!(txdone.send(()));
+    })
+}
+
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+fn connect_timeout_valid() {
+    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
+    let addr = listener.local_addr().unwrap();
+    TcpStream::connect_timeout(&addr, Duration::from_secs(2)).unwrap();
+}
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index d730b2b87ac..17e3e4497c4 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -1,3 +1,6 @@
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
+mod tests;
+
 use crate::fmt;
 use crate::io::{self, Error, ErrorKind};
 use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
@@ -798,380 +801,3 @@ impl fmt::Debug for UdpSocket {
         self.0.fmt(f)
     }
 }
-
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
-mod tests {
-    use crate::io::ErrorKind;
-    use crate::net::test::{next_test_ip4, next_test_ip6};
-    use crate::net::*;
-    use crate::sync::mpsc::channel;
-    use crate::sys_common::AsInner;
-    use crate::thread;
-    use crate::time::{Duration, Instant};
-
-    fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
-        f(next_test_ip4(), next_test_ip4());
-        f(next_test_ip6(), next_test_ip6());
-    }
-
-    macro_rules! t {
-        ($e:expr) => {
-            match $e {
-                Ok(t) => t,
-                Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
-            }
-        };
-    }
-
-    #[test]
-    fn bind_error() {
-        match UdpSocket::bind("1.1.1.1:9999") {
-            Ok(..) => panic!(),
-            Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
-        }
-    }
-
-    #[test]
-    fn socket_smoke_test_ip4() {
-        each_ip(&mut |server_ip, client_ip| {
-            let (tx1, rx1) = channel();
-            let (tx2, rx2) = channel();
-
-            let _t = thread::spawn(move || {
-                let client = t!(UdpSocket::bind(&client_ip));
-                rx1.recv().unwrap();
-                t!(client.send_to(&[99], &server_ip));
-                tx2.send(()).unwrap();
-            });
-
-            let server = t!(UdpSocket::bind(&server_ip));
-            tx1.send(()).unwrap();
-            let mut buf = [0];
-            let (nread, src) = t!(server.recv_from(&mut buf));
-            assert_eq!(nread, 1);
-            assert_eq!(buf[0], 99);
-            assert_eq!(src, client_ip);
-            rx2.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn socket_name() {
-        each_ip(&mut |addr, _| {
-            let server = t!(UdpSocket::bind(&addr));
-            assert_eq!(addr, t!(server.local_addr()));
-        })
-    }
-
-    #[test]
-    fn socket_peer() {
-        each_ip(&mut |addr1, addr2| {
-            let server = t!(UdpSocket::bind(&addr1));
-            assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected);
-            t!(server.connect(&addr2));
-            assert_eq!(addr2, t!(server.peer_addr()));
-        })
-    }
-
-    #[test]
-    fn udp_clone_smoke() {
-        each_ip(&mut |addr1, addr2| {
-            let sock1 = t!(UdpSocket::bind(&addr1));
-            let sock2 = t!(UdpSocket::bind(&addr2));
-
-            let _t = thread::spawn(move || {
-                let mut buf = [0, 0];
-                assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
-                assert_eq!(buf[0], 1);
-                t!(sock2.send_to(&[2], &addr1));
-            });
-
-            let sock3 = t!(sock1.try_clone());
-
-            let (tx1, rx1) = channel();
-            let (tx2, rx2) = channel();
-            let _t = thread::spawn(move || {
-                rx1.recv().unwrap();
-                t!(sock3.send_to(&[1], &addr2));
-                tx2.send(()).unwrap();
-            });
-            tx1.send(()).unwrap();
-            let mut buf = [0, 0];
-            assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2));
-            rx2.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn udp_clone_two_read() {
-        each_ip(&mut |addr1, addr2| {
-            let sock1 = t!(UdpSocket::bind(&addr1));
-            let sock2 = t!(UdpSocket::bind(&addr2));
-            let (tx1, rx) = channel();
-            let tx2 = tx1.clone();
-
-            let _t = thread::spawn(move || {
-                t!(sock2.send_to(&[1], &addr1));
-                rx.recv().unwrap();
-                t!(sock2.send_to(&[2], &addr1));
-                rx.recv().unwrap();
-            });
-
-            let sock3 = t!(sock1.try_clone());
-
-            let (done, rx) = channel();
-            let _t = thread::spawn(move || {
-                let mut buf = [0, 0];
-                t!(sock3.recv_from(&mut buf));
-                tx2.send(()).unwrap();
-                done.send(()).unwrap();
-            });
-            let mut buf = [0, 0];
-            t!(sock1.recv_from(&mut buf));
-            tx1.send(()).unwrap();
-
-            rx.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn udp_clone_two_write() {
-        each_ip(&mut |addr1, addr2| {
-            let sock1 = t!(UdpSocket::bind(&addr1));
-            let sock2 = t!(UdpSocket::bind(&addr2));
-
-            let (tx, rx) = channel();
-            let (serv_tx, serv_rx) = channel();
-
-            let _t = thread::spawn(move || {
-                let mut buf = [0, 1];
-                rx.recv().unwrap();
-                t!(sock2.recv_from(&mut buf));
-                serv_tx.send(()).unwrap();
-            });
-
-            let sock3 = t!(sock1.try_clone());
-
-            let (done, rx) = channel();
-            let tx2 = tx.clone();
-            let _t = thread::spawn(move || {
-                match sock3.send_to(&[1], &addr2) {
-                    Ok(..) => {
-                        let _ = tx2.send(());
-                    }
-                    Err(..) => {}
-                }
-                done.send(()).unwrap();
-            });
-            match sock1.send_to(&[2], &addr2) {
-                Ok(..) => {
-                    let _ = tx.send(());
-                }
-                Err(..) => {}
-            }
-            drop(tx);
-
-            rx.recv().unwrap();
-            serv_rx.recv().unwrap();
-        })
-    }
-
-    #[test]
-    fn debug() {
-        let name = if cfg!(windows) { "socket" } else { "fd" };
-        let socket_addr = next_test_ip4();
-
-        let udpsock = t!(UdpSocket::bind(&socket_addr));
-        let udpsock_inner = udpsock.0.socket().as_inner();
-        let compare =
-            format!("UdpSocket {{ addr: {:?}, {}: {:?} }}", socket_addr, name, udpsock_inner);
-        assert_eq!(format!("{:?}", udpsock), compare);
-    }
-
-    // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
-    //        no longer has rounding errors.
-    // VxWorks ignores SO_SNDTIMEO.
-    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
-    #[test]
-    fn timeouts() {
-        let addr = next_test_ip4();
-
-        let stream = t!(UdpSocket::bind(&addr));
-        let dur = Duration::new(15410, 0);
-
-        assert_eq!(None, t!(stream.read_timeout()));
-
-        t!(stream.set_read_timeout(Some(dur)));
-        assert_eq!(Some(dur), t!(stream.read_timeout()));
-
-        assert_eq!(None, t!(stream.write_timeout()));
-
-        t!(stream.set_write_timeout(Some(dur)));
-        assert_eq!(Some(dur), t!(stream.write_timeout()));
-
-        t!(stream.set_read_timeout(None));
-        assert_eq!(None, t!(stream.read_timeout()));
-
-        t!(stream.set_write_timeout(None));
-        assert_eq!(None, t!(stream.write_timeout()));
-    }
-
-    #[test]
-    fn test_read_timeout() {
-        let addr = next_test_ip4();
-
-        let stream = t!(UdpSocket::bind(&addr));
-        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
-
-        let mut buf = [0; 10];
-
-        let start = Instant::now();
-        loop {
-            let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
-            if kind != ErrorKind::Interrupted {
-                assert!(
-                    kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
-                    "unexpected_error: {:?}",
-                    kind
-                );
-                break;
-            }
-        }
-        assert!(start.elapsed() > Duration::from_millis(400));
-    }
-
-    #[test]
-    fn test_read_with_timeout() {
-        let addr = next_test_ip4();
-
-        let stream = t!(UdpSocket::bind(&addr));
-        t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
-
-        t!(stream.send_to(b"hello world", &addr));
-
-        let mut buf = [0; 11];
-        t!(stream.recv_from(&mut buf));
-        assert_eq!(b"hello world", &buf[..]);
-
-        let start = Instant::now();
-        loop {
-            let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
-            if kind != ErrorKind::Interrupted {
-                assert!(
-                    kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
-                    "unexpected_error: {:?}",
-                    kind
-                );
-                break;
-            }
-        }
-        assert!(start.elapsed() > Duration::from_millis(400));
-    }
-
-    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
-    // when passed zero Durations
-    #[test]
-    fn test_timeout_zero_duration() {
-        let addr = next_test_ip4();
-
-        let socket = t!(UdpSocket::bind(&addr));
-
-        let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-
-        let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
-        let err = result.unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::InvalidInput);
-    }
-
-    #[test]
-    fn connect_send_recv() {
-        let addr = next_test_ip4();
-
-        let socket = t!(UdpSocket::bind(&addr));
-        t!(socket.connect(addr));
-
-        t!(socket.send(b"hello world"));
-
-        let mut buf = [0; 11];
-        t!(socket.recv(&mut buf));
-        assert_eq!(b"hello world", &buf[..]);
-    }
-
-    #[test]
-    fn connect_send_peek_recv() {
-        each_ip(&mut |addr, _| {
-            let socket = t!(UdpSocket::bind(&addr));
-            t!(socket.connect(addr));
-
-            t!(socket.send(b"hello world"));
-
-            for _ in 1..3 {
-                let mut buf = [0; 11];
-                let size = t!(socket.peek(&mut buf));
-                assert_eq!(b"hello world", &buf[..]);
-                assert_eq!(size, 11);
-            }
-
-            let mut buf = [0; 11];
-            let size = t!(socket.recv(&mut buf));
-            assert_eq!(b"hello world", &buf[..]);
-            assert_eq!(size, 11);
-        })
-    }
-
-    #[test]
-    fn peek_from() {
-        each_ip(&mut |addr, _| {
-            let socket = t!(UdpSocket::bind(&addr));
-            t!(socket.send_to(b"hello world", &addr));
-
-            for _ in 1..3 {
-                let mut buf = [0; 11];
-                let (size, _) = t!(socket.peek_from(&mut buf));
-                assert_eq!(b"hello world", &buf[..]);
-                assert_eq!(size, 11);
-            }
-
-            let mut buf = [0; 11];
-            let (size, _) = t!(socket.recv_from(&mut buf));
-            assert_eq!(b"hello world", &buf[..]);
-            assert_eq!(size, 11);
-        })
-    }
-
-    #[test]
-    fn ttl() {
-        let ttl = 100;
-
-        let addr = next_test_ip4();
-
-        let stream = t!(UdpSocket::bind(&addr));
-
-        t!(stream.set_ttl(ttl));
-        assert_eq!(ttl, t!(stream.ttl()));
-    }
-
-    #[test]
-    fn set_nonblocking() {
-        each_ip(&mut |addr, _| {
-            let socket = t!(UdpSocket::bind(&addr));
-
-            t!(socket.set_nonblocking(true));
-            t!(socket.set_nonblocking(false));
-
-            t!(socket.connect(addr));
-
-            t!(socket.set_nonblocking(false));
-            t!(socket.set_nonblocking(true));
-
-            let mut buf = [0];
-            match socket.recv(&mut buf) {
-                Ok(_) => panic!("expected error"),
-                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
-                Err(e) => panic!("unexpected error {}", e),
-            }
-        })
-    }
-}
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
new file mode 100644
index 00000000000..658369f79aa
--- /dev/null
+++ b/library/std/src/net/udp/tests.rs
@@ -0,0 +1,372 @@
+use crate::io::ErrorKind;
+use crate::net::test::{next_test_ip4, next_test_ip6};
+use crate::net::*;
+use crate::sync::mpsc::channel;
+use crate::sys_common::AsInner;
+use crate::thread;
+use crate::time::{Duration, Instant};
+
+fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
+    f(next_test_ip4(), next_test_ip4());
+    f(next_test_ip6(), next_test_ip6());
+}
+
+macro_rules! t {
+    ($e:expr) => {
+        match $e {
+            Ok(t) => t,
+            Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
+        }
+    };
+}
+
+#[test]
+fn bind_error() {
+    match UdpSocket::bind("1.1.1.1:9999") {
+        Ok(..) => panic!(),
+        Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
+    }
+}
+
+#[test]
+fn socket_smoke_test_ip4() {
+    each_ip(&mut |server_ip, client_ip| {
+        let (tx1, rx1) = channel();
+        let (tx2, rx2) = channel();
+
+        let _t = thread::spawn(move || {
+            let client = t!(UdpSocket::bind(&client_ip));
+            rx1.recv().unwrap();
+            t!(client.send_to(&[99], &server_ip));
+            tx2.send(()).unwrap();
+        });
+
+        let server = t!(UdpSocket::bind(&server_ip));
+        tx1.send(()).unwrap();
+        let mut buf = [0];
+        let (nread, src) = t!(server.recv_from(&mut buf));
+        assert_eq!(nread, 1);
+        assert_eq!(buf[0], 99);
+        assert_eq!(src, client_ip);
+        rx2.recv().unwrap();
+    })
+}
+
+#[test]
+fn socket_name() {
+    each_ip(&mut |addr, _| {
+        let server = t!(UdpSocket::bind(&addr));
+        assert_eq!(addr, t!(server.local_addr()));
+    })
+}
+
+#[test]
+fn socket_peer() {
+    each_ip(&mut |addr1, addr2| {
+        let server = t!(UdpSocket::bind(&addr1));
+        assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected);
+        t!(server.connect(&addr2));
+        assert_eq!(addr2, t!(server.peer_addr()));
+    })
+}
+
+#[test]
+fn udp_clone_smoke() {
+    each_ip(&mut |addr1, addr2| {
+        let sock1 = t!(UdpSocket::bind(&addr1));
+        let sock2 = t!(UdpSocket::bind(&addr2));
+
+        let _t = thread::spawn(move || {
+            let mut buf = [0, 0];
+            assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
+            assert_eq!(buf[0], 1);
+            t!(sock2.send_to(&[2], &addr1));
+        });
+
+        let sock3 = t!(sock1.try_clone());
+
+        let (tx1, rx1) = channel();
+        let (tx2, rx2) = channel();
+        let _t = thread::spawn(move || {
+            rx1.recv().unwrap();
+            t!(sock3.send_to(&[1], &addr2));
+            tx2.send(()).unwrap();
+        });
+        tx1.send(()).unwrap();
+        let mut buf = [0, 0];
+        assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2));
+        rx2.recv().unwrap();
+    })
+}
+
+#[test]
+fn udp_clone_two_read() {
+    each_ip(&mut |addr1, addr2| {
+        let sock1 = t!(UdpSocket::bind(&addr1));
+        let sock2 = t!(UdpSocket::bind(&addr2));
+        let (tx1, rx) = channel();
+        let tx2 = tx1.clone();
+
+        let _t = thread::spawn(move || {
+            t!(sock2.send_to(&[1], &addr1));
+            rx.recv().unwrap();
+            t!(sock2.send_to(&[2], &addr1));
+            rx.recv().unwrap();
+        });
+
+        let sock3 = t!(sock1.try_clone());
+
+        let (done, rx) = channel();
+        let _t = thread::spawn(move || {
+            let mut buf = [0, 0];
+            t!(sock3.recv_from(&mut buf));
+            tx2.send(()).unwrap();
+            done.send(()).unwrap();
+        });
+        let mut buf = [0, 0];
+        t!(sock1.recv_from(&mut buf));
+        tx1.send(()).unwrap();
+
+        rx.recv().unwrap();
+    })
+}
+
+#[test]
+fn udp_clone_two_write() {
+    each_ip(&mut |addr1, addr2| {
+        let sock1 = t!(UdpSocket::bind(&addr1));
+        let sock2 = t!(UdpSocket::bind(&addr2));
+
+        let (tx, rx) = channel();
+        let (serv_tx, serv_rx) = channel();
+
+        let _t = thread::spawn(move || {
+            let mut buf = [0, 1];
+            rx.recv().unwrap();
+            t!(sock2.recv_from(&mut buf));
+            serv_tx.send(()).unwrap();
+        });
+
+        let sock3 = t!(sock1.try_clone());
+
+        let (done, rx) = channel();
+        let tx2 = tx.clone();
+        let _t = thread::spawn(move || {
+            match sock3.send_to(&[1], &addr2) {
+                Ok(..) => {
+                    let _ = tx2.send(());
+                }
+                Err(..) => {}
+            }
+            done.send(()).unwrap();
+        });
+        match sock1.send_to(&[2], &addr2) {
+            Ok(..) => {
+                let _ = tx.send(());
+            }
+            Err(..) => {}
+        }
+        drop(tx);
+
+        rx.recv().unwrap();
+        serv_rx.recv().unwrap();
+    })
+}
+
+#[test]
+fn debug() {
+    let name = if cfg!(windows) { "socket" } else { "fd" };
+    let socket_addr = next_test_ip4();
+
+    let udpsock = t!(UdpSocket::bind(&socket_addr));
+    let udpsock_inner = udpsock.0.socket().as_inner();
+    let compare = format!("UdpSocket {{ addr: {:?}, {}: {:?} }}", socket_addr, name, udpsock_inner);
+    assert_eq!(format!("{:?}", udpsock), compare);
+}
+
+// FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
+//        no longer has rounding errors.
+// VxWorks ignores SO_SNDTIMEO.
+#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
+#[test]
+fn timeouts() {
+    let addr = next_test_ip4();
+
+    let stream = t!(UdpSocket::bind(&addr));
+    let dur = Duration::new(15410, 0);
+
+    assert_eq!(None, t!(stream.read_timeout()));
+
+    t!(stream.set_read_timeout(Some(dur)));
+    assert_eq!(Some(dur), t!(stream.read_timeout()));
+
+    assert_eq!(None, t!(stream.write_timeout()));
+
+    t!(stream.set_write_timeout(Some(dur)));
+    assert_eq!(Some(dur), t!(stream.write_timeout()));
+
+    t!(stream.set_read_timeout(None));
+    assert_eq!(None, t!(stream.read_timeout()));
+
+    t!(stream.set_write_timeout(None));
+    assert_eq!(None, t!(stream.write_timeout()));
+}
+
+#[test]
+fn test_read_timeout() {
+    let addr = next_test_ip4();
+
+    let stream = t!(UdpSocket::bind(&addr));
+    t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+    let mut buf = [0; 10];
+
+    let start = Instant::now();
+    loop {
+        let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
+        if kind != ErrorKind::Interrupted {
+            assert!(
+                kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
+                "unexpected_error: {:?}",
+                kind
+            );
+            break;
+        }
+    }
+    assert!(start.elapsed() > Duration::from_millis(400));
+}
+
+#[test]
+fn test_read_with_timeout() {
+    let addr = next_test_ip4();
+
+    let stream = t!(UdpSocket::bind(&addr));
+    t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+    t!(stream.send_to(b"hello world", &addr));
+
+    let mut buf = [0; 11];
+    t!(stream.recv_from(&mut buf));
+    assert_eq!(b"hello world", &buf[..]);
+
+    let start = Instant::now();
+    loop {
+        let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
+        if kind != ErrorKind::Interrupted {
+            assert!(
+                kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
+                "unexpected_error: {:?}",
+                kind
+            );
+            break;
+        }
+    }
+    assert!(start.elapsed() > Duration::from_millis(400));
+}
+
+// Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+// when passed zero Durations
+#[test]
+fn test_timeout_zero_duration() {
+    let addr = next_test_ip4();
+
+    let socket = t!(UdpSocket::bind(&addr));
+
+    let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    let err = result.unwrap_err();
+    assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+    let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    let err = result.unwrap_err();
+    assert_eq!(err.kind(), ErrorKind::InvalidInput);
+}
+
+#[test]
+fn connect_send_recv() {
+    let addr = next_test_ip4();
+
+    let socket = t!(UdpSocket::bind(&addr));
+    t!(socket.connect(addr));
+
+    t!(socket.send(b"hello world"));
+
+    let mut buf = [0; 11];
+    t!(socket.recv(&mut buf));
+    assert_eq!(b"hello world", &buf[..]);
+}
+
+#[test]
+fn connect_send_peek_recv() {
+    each_ip(&mut |addr, _| {
+        let socket = t!(UdpSocket::bind(&addr));
+        t!(socket.connect(addr));
+
+        t!(socket.send(b"hello world"));
+
+        for _ in 1..3 {
+            let mut buf = [0; 11];
+            let size = t!(socket.peek(&mut buf));
+            assert_eq!(b"hello world", &buf[..]);
+            assert_eq!(size, 11);
+        }
+
+        let mut buf = [0; 11];
+        let size = t!(socket.recv(&mut buf));
+        assert_eq!(b"hello world", &buf[..]);
+        assert_eq!(size, 11);
+    })
+}
+
+#[test]
+fn peek_from() {
+    each_ip(&mut |addr, _| {
+        let socket = t!(UdpSocket::bind(&addr));
+        t!(socket.send_to(b"hello world", &addr));
+
+        for _ in 1..3 {
+            let mut buf = [0; 11];
+            let (size, _) = t!(socket.peek_from(&mut buf));
+            assert_eq!(b"hello world", &buf[..]);
+            assert_eq!(size, 11);
+        }
+
+        let mut buf = [0; 11];
+        let (size, _) = t!(socket.recv_from(&mut buf));
+        assert_eq!(b"hello world", &buf[..]);
+        assert_eq!(size, 11);
+    })
+}
+
+#[test]
+fn ttl() {
+    let ttl = 100;
+
+    let addr = next_test_ip4();
+
+    let stream = t!(UdpSocket::bind(&addr));
+
+    t!(stream.set_ttl(ttl));
+    assert_eq!(ttl, t!(stream.ttl()));
+}
+
+#[test]
+fn set_nonblocking() {
+    each_ip(&mut |addr, _| {
+        let socket = t!(UdpSocket::bind(&addr));
+
+        t!(socket.set_nonblocking(true));
+        t!(socket.set_nonblocking(false));
+
+        t!(socket.connect(addr));
+
+        t!(socket.set_nonblocking(false));
+        t!(socket.set_nonblocking(true));
+
+        let mut buf = [0];
+        match socket.recv(&mut buf) {
+            Ok(_) => panic!("expected error"),
+            Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
+            Err(e) => panic!("unexpected error {}", e),
+        }
+    })
+}