]> git.lizzy.rs Git - rust.git/commitdiff
SGX target: fix std unit tests
authorJethro Beekman <jethro@fortanix.com>
Tue, 12 Mar 2019 17:58:30 +0000 (10:58 -0700)
committerJethro Beekman <jethro@fortanix.com>
Mon, 25 Mar 2019 18:31:19 +0000 (11:31 -0700)
27 files changed:
src/libstd/Cargo.toml
src/libstd/env.rs
src/libstd/fs.rs
src/libstd/net/addr.rs
src/libstd/net/tcp.rs
src/libstd/net/test.rs
src/libstd/net/udp.rs
src/libstd/path.rs
src/libstd/process.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sys/sgx/abi/mod.rs
src/libstd/sys/sgx/abi/panic.rs
src/libstd/sys/sgx/abi/tls.rs
src/libstd/sys/sgx/abi/usercalls/alloc.rs
src/libstd/sys/sgx/alloc.rs
src/libstd/sys/sgx/args.rs
src/libstd/sys/sgx/condvar.rs
src/libstd/sys/sgx/net.rs
src/libstd/sys/sgx/os.rs
src/libstd/sys/sgx/rwlock.rs
src/libstd/sys/sgx/stack_overflow.rs
src/libstd/sys/sgx/thread.rs
src/libstd/sys/sgx/waitqueue.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/tools/tidy/src/pal.rs

index 1a6b58f35b398c30047935133a59816534760925..b2eaf956d0e2d5b66dfc2ee8ab77ed3a38a656a8 100644 (file)
@@ -72,3 +72,7 @@ wasm-bindgen-threads = []
 # https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/std_detect/Cargo.toml
 std_detect_file_io = []
 std_detect_dlsym_getauxval = []
+
+[package.metadata.fortanix-sgx]
+# Maximum possible number of threads when testing
+threads = 125
index 97c67f562a7dfac171052b854ec03ce49b91219f..f723a2b0bb281eeab9677338cc2cefb40df7ac44 100644 (file)
@@ -975,7 +975,7 @@ mod tests {
     use crate::path::Path;
 
     #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
     fn test_self_exe_path() {
         let path = current_exe();
         assert!(path.is_ok());
@@ -989,6 +989,7 @@ fn test_self_exe_path() {
     fn test() {
         assert!((!Path::new("test-path").is_absolute()));
 
+        #[cfg(not(target_env = "sgx"))]
         current_dir().unwrap();
     }
 
index 8c3d0da0a7e405836a723ff096c7b5aa2b9560c3..dfff44b88ea784e3598285ca9555f18db0d5255c 100644 (file)
@@ -2095,7 +2095,7 @@ fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::prelude::*;
 
index f5a87cc3ea67a057759d62e562b8e9b3927fca08..eaa6a070154f7ed684401b0424c13d92159ffcf3 100644 (file)
@@ -941,7 +941,10 @@ fn to_socket_addr_str_u16() {
         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]
@@ -953,7 +956,10 @@ fn to_socket_addr_str() {
         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]
index ce0c5c0bb0dc7d25dad48eaf0c3e83e763dc49fc..7e14de7cc4f4a8b0b49eb8c2b77a7ba5a43d50db 100644 (file)
@@ -929,12 +929,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
+    use crate::fmt;
     use crate::io::{ErrorKind, IoVec, IoVecMut};
     use crate::io::prelude::*;
     use crate::net::*;
     use crate::net::test::{next_test_ip4, next_test_ip6};
     use crate::sync::mpsc::channel;
-    use crate::sys_common::AsInner;
     use crate::time::{Instant, Duration};
     use crate::thread;
 
@@ -1129,7 +1129,7 @@ fn connect(i: usize, addr: SocketAddr) {
                 connect(i + 1, addr);
                 t!(stream.write(&[i as u8]));
             });
-            t.join().ok().unwrap();
+            t.join().ok().expect("thread panicked");
         }
     }
 
@@ -1162,7 +1162,7 @@ fn connect(i: usize, addr: SocketAddr) {
                 connect(i + 1, addr);
                 t!(stream.write(&[99]));
             });
-            t.join().ok().unwrap();
+            t.join().ok().expect("thread panicked");
         }
     }
 
@@ -1377,6 +1377,8 @@ fn tcp_clone_two_write() {
     }
 
     #[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));
@@ -1397,6 +1399,8 @@ fn shutdown_smoke() {
     }
 
     #[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));
@@ -1550,30 +1554,51 @@ fn clone_accept_concurrent() {
 
     #[test]
     fn debug() {
-        let name = if cfg!(windows) {"socket"} else {"fd"};
+        #[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(unix)]
+        use crate::os::unix::io::AsRawFd;
+        #[cfg(target_env = "sgx")]
+        use crate::os::fortanix_sgx::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 listener_inner = listener.0.socket().as_inner();
         let compare = format!("TcpListener {{ addr: {:?}, {}: {:?} }}",
-                              socket_addr, name, listener_inner);
+                              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 stream_inner = stream.0.socket().as_inner();
-        let compare = format!("TcpStream {{ addr: {:?}, \
-                              peer: {:?}, {}: {:?} }}",
-                              stream.local_addr().unwrap(),
-                              stream.peer_addr().unwrap(),
-                              name,
-                              stream_inner);
+        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 bitrig/openbsd tests once their socket timeout code
     //        no longer has rounding errors.
     #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     #[test]
     fn timeouts() {
         let addr = next_test_ip4();
@@ -1601,6 +1626,7 @@ fn timeouts() {
     }
 
     #[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));
@@ -1618,6 +1644,7 @@ fn test_read_timeout() {
     }
 
     #[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));
@@ -1661,6 +1688,7 @@ fn test_timeout_zero_duration() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn nodelay() {
         let addr = next_test_ip4();
         let _listener = t!(TcpListener::bind(&addr));
@@ -1675,6 +1703,7 @@ fn nodelay() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn ttl() {
         let ttl = 100;
 
@@ -1691,6 +1720,7 @@ fn ttl() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn set_nonblocking() {
         let addr = next_test_ip4();
         let listener = t!(TcpListener::bind(&addr));
@@ -1712,6 +1742,7 @@ fn set_nonblocking() {
     }
 
     #[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();
@@ -1743,6 +1774,7 @@ fn peek() {
     }
 
     #[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();
index 89fefd9d1d5e069f8bd3a58398b6b4782b1cf5f5..e2991cbdd88226c3abf6ba2cbf7b08ca82f71678 100644 (file)
@@ -36,12 +36,16 @@ pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
 // all want to use ports. This function figures out which workspace
 // it is running in and assigns a port range based on it.
 fn base_port() -> u16 {
-    let cwd = env::current_dir().unwrap();
+    let cwd = if cfg!(target_env = "sgx") {
+        String::from("sgx")
+    } else {
+        env::current_dir().unwrap().into_os_string().into_string().unwrap()
+    };
     let dirs = ["32-opt", "32-nopt",
                 "musl-64-opt", "cross-opt",
                 "64-opt", "64-nopt", "64-opt-vg", "64-debug-opt",
-                "all-opt", "snap3", "dist"];
+                "all-opt", "snap3", "dist", "sgx"];
     dirs.iter().enumerate().find(|&(_, dir)| {
-        cwd.to_str().unwrap().contains(dir)
+        cwd.contains(dir)
     }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600
 }
index edc9d665444a035ebe396fe1c08bf40f5f6f627f..951f385fb3ea52c9da4952185d73f8330d15cb81 100644 (file)
@@ -806,7 +806,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::ErrorKind;
     use crate::net::*;
index ea3fcd8ce28597df108ef63dd077a81c4245240f..4048bc4da2557f0434c33bd9ef8aca9c90a972b1 100644 (file)
@@ -3801,7 +3801,7 @@ macro_rules! tp(
             });
         );
 
-        if cfg!(unix) {
+        if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
             tp!("", "foo", "foo");
             tp!("foo", "bar", "foo/bar");
             tp!("foo/", "bar", "foo/bar");
@@ -3960,7 +3960,7 @@ macro_rules! tfn(
         tfn!("foo", "bar", "bar");
         tfn!("foo", "", "");
         tfn!("", "foo", "foo");
-        if cfg!(unix) {
+        if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
             tfn!(".", "foo", "./foo");
             tfn!("foo/", "bar", "bar");
             tfn!("foo/.", "bar", "bar");
index ad86acbb47de420c6ed67365fd2cf118c81a18f1..054b398b01f26a414bef98dae648e2458c3d883b 100644 (file)
@@ -1621,7 +1621,7 @@ fn report(self) -> i32 {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::prelude::*;
 
index c383f21dcd752ae327a13ad9289977d2387467a2..2e8182671dd6f4d84299e39c8559b4073a06f5a8 100644 (file)
@@ -705,6 +705,7 @@ fn wait_until() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
@@ -724,6 +725,7 @@ fn wait_timeout_wait() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_until_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
@@ -748,6 +750,7 @@ fn wait_timeout_until_instant_satisfy() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_until_wake() {
         let pair = Arc::new((Mutex::new(false), Condvar::new()));
         let pair_copy = pair.clone();
@@ -771,6 +774,7 @@ fn wait_timeout_until_wake() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_wake() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
index 90c5c50c23b9cc3304d78e434be7aba27f9191db..4ed2bfb175a464da1bcb1ba0a3d46810dd3ac3a2 100644 (file)
@@ -1951,7 +1951,7 @@ fn stress() {
         for _ in 0..10000 {
             assert_eq!(rx.recv().unwrap(), 1);
         }
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1977,7 +1977,7 @@ fn stress_shared() {
             });
         }
         drop(tx);
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1996,8 +1996,8 @@ fn send_from_outside_runtime() {
                 tx2.send(1).unwrap();
             }
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        t1.join().ok().expect("thread panicked");
+        t2.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2011,7 +2011,7 @@ fn recv_from_outside_runtime() {
         for _ in 0..40 {
             tx.send(1).unwrap();
         }
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2026,8 +2026,8 @@ fn no_runtime() {
             tx1.send(1).unwrap();
             assert_eq!(rx2.recv().unwrap(), 2);
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        t1.join().ok().expect("thread panicked");
+        t2.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2225,6 +2225,7 @@ fn recv(rx: Receiver<Box<i32>>, i: i32) {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn oneshot_single_thread_recv_timeout() {
         let (tx, rx) = channel();
         tx.send(()).unwrap();
@@ -2235,6 +2236,7 @@ fn oneshot_single_thread_recv_timeout() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_two_threads() {
         let (tx, rx) = channel();
         let stress = stress_factor() + 100;
@@ -2265,6 +2267,7 @@ fn stress_recv_timeout_two_threads() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn recv_timeout_upgrade() {
         let (tx, rx) = channel::<()>();
         let timeout = Duration::from_millis(1);
@@ -2276,6 +2279,7 @@ fn recv_timeout_upgrade() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_shared() {
         let (tx, rx) = channel();
         let stress = stress_factor() + 100;
@@ -2306,6 +2310,7 @@ fn stress_recv_timeout_shared() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn very_long_recv_timeout_wont_panic() {
         let (tx, rx) = channel::<()>();
         let join_handle = thread::spawn(move || {
@@ -2325,6 +2330,7 @@ fn recv_a_lot() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn shared_recv_timeout() {
         let (tx, rx) = channel();
         let total = 5;
@@ -2550,6 +2556,7 @@ fn smoke_shared() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn recv_timeout() {
         let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout));
@@ -2639,6 +2646,7 @@ fn stress() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_two_threads() {
         let (tx, rx) = sync_channel::<i32>(0);
 
@@ -2662,6 +2670,7 @@ fn stress_recv_timeout_two_threads() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_shared() {
         const AMT: u32 = 1000;
         const NTHREADS: u32 = 8;
index 7426f7be9e9615063e4fc419883c78e046451e5f..85ec8be4aae69bf157b89a7e6c86209279a20dc6 100644 (file)
@@ -1,3 +1,5 @@
+#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
+
 use core::sync::atomic::{AtomicUsize, Ordering};
 use crate::io::Write;
 
 #[macro_use]
 pub mod usercalls;
 
+#[cfg(not(test))]
 global_asm!(include_str!("entry.S"));
 
+#[cfg(not(test))]
 #[no_mangle]
 unsafe extern "C" fn tcs_init(secondary: bool) {
     // Be very careful when changing this code: it runs before the binary has been
@@ -48,6 +52,7 @@
 // FIXME: this item should only exist if this is linked into an executable
 // (main function exists). If this is a library, the crate author should be
 // able to specify this
+#[cfg(not(test))]
 #[no_mangle]
 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) {
     // FIXME: how to support TLS in library mode?
index 83411cb5b4c26fd9e58672510b2093c9f7f88be0..de86394b4b88cdfd8013b57b089988f60567df04 100644 (file)
@@ -49,7 +49,7 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-#[no_mangle]
+#[cfg_attr(not(test), no_mangle)]
 pub extern "C" fn panic_msg(msg: &str) -> ! {
     let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
     usercalls::exit(true)
index b2a812c7231da4159a88462b82e18e63151f532c..6b9ab7e383c01565f27fc18664ae768f1af6d5c8 100644 (file)
 const TLS_KEYS: usize = 128; // Same as POSIX minimum
 const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"]
 static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
 macro_rules! dup {
     ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
     (() $($val:tt)*) => ([$($val),*])
 }
-static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = [
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-];
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"]
+static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
 
 extern "C" {
     fn get_tls_ptr() -> *const u8;
index b787bd1a5abac44b088bc00fe8b8dea2d3f006ab..449a5fe5ae3082a837e1f5d7c744e1bb7228c8a3 100644 (file)
@@ -188,8 +188,13 @@ impl<T: ?Sized> User<T> where T: UserSafe {
     // from outside as obtained by `super::alloc`.
     fn new_uninit_bytes(size: usize) -> Self {
         unsafe {
-            let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed");
-            User(NonNull::new_userref(T::from_raw_sized(ptr as _, size)))
+            // Mustn't call alloc with size 0.
+            let ptr = if size > 0 {
+                super::alloc(size, T::align_of()).expect("User memory allocation failed") as _
+            } else {
+                T::align_of() as _ // dangling pointer ok for size 0
+            };
+            User(NonNull::new_userref(T::from_raw_sized(ptr, size)))
         }
     }
 
index 94dc8ec25b5872e5f9339c0c6260388740944b02..98eb8397436bfeb98b06852cea90c6e541c5e5ed 100644 (file)
@@ -4,6 +4,8 @@
 
 // Using a SpinMutex because we never want to exit the enclave waiting for the
 // allocator.
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE"]
 static DLMALLOC: SpinMutex<dlmalloc::Dlmalloc> = SpinMutex::new(dlmalloc::DLMALLOC_INIT);
 
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
index b73bf9213b7727ec677bebff4af9618db050a990..a84ab4138761ef6fd672e59c3c9e5aabe045eeea 100644 (file)
@@ -5,9 +5,12 @@
 use crate::sys_common::FromInner;
 use crate::slice;
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
 static ARGS: AtomicUsize = AtomicUsize::new(0);
 type ArgsStore = Vec<OsString>;
 
+#[cfg_attr(test, allow(dead_code))]
 pub unsafe fn init(argc: isize, argv: *const *const u8) {
     if argc != 0 {
         let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _);
index e9a7684f74d00f3b6b26568799bf8695c3ffa3a3..f9a76f0baf51a383ef5c18ce02b3c01befd17b55 100644 (file)
@@ -32,7 +32,8 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
         mutex.lock()
     }
 
-    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, _dur: Duration) -> bool {
+        mutex.unlock(); // don't hold the lock while panicking
         panic!("timeout not supported in SGX");
     }
 
index e167e917957f3f652b9dce3735f802c868bcb9fd..592b300ac667c0a3f99e401550e40ad4a5535778 100644 (file)
@@ -41,12 +41,29 @@ fn from_inner(inner: FileDesc) -> Socket {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct TcpStream {
     inner: Socket,
     peer_addr: Option<String>,
 }
 
+impl fmt::Debug for TcpStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut res = f.debug_struct("TcpStream");
+
+        if let Some(ref addr) = self.inner.local_addr {
+            res.field("addr", addr);
+        }
+
+        if let Some(ref peer) = self.peer_addr {
+            res.field("peer", peer);
+        }
+
+        res.field("fd", &self.inner.inner.as_inner())
+            .finish()
+    }
+}
+
 fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
     match result {
         Ok(saddr) => Ok(saddr.to_string()),
@@ -75,16 +92,32 @@ pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
         Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
     }
 
-    pub fn connect_timeout(addr: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+    pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
+        if dur == Duration::default() {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                      "cannot set a 0 duration timeout"));
+        }
         Self::connect(Ok(addr)) // FIXME: ignoring timeout
     }
 
-    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        sgx_ineffective(())
+    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        match dur {
+            Some(dur) if dur == Duration::default() => {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
+            _ => sgx_ineffective(())
+        }
     }
 
-    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        sgx_ineffective(())
+    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        match dur {
+            Some(dur) if dur == Duration::default() => {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
+            _ => sgx_ineffective(())
+        }
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
@@ -174,11 +207,24 @@ fn from_inner((inner, peer_addr): (Socket, Option<String>)) -> TcpStream {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct TcpListener {
     inner: Socket,
 }
 
+impl fmt::Debug for TcpListener {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut res = f.debug_struct("TcpListener");
+
+        if let Some(ref addr) = self.inner.local_addr {
+            res.field("addr", addr);
+        }
+
+        res.field("fd", &self.inner.inner.as_inner())
+            .finish()
+    }
+}
+
 impl TcpListener {
     pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
         let addr = io_err_to_addr(addr)?;
index 2725e66ce5de4001d43489e1e517b8264e0118fd..0bb7b897058db08878ca2e28df709d6384deb398 100644 (file)
@@ -73,7 +73,11 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE"]
 static ENV: AtomicUsize = AtomicUsize::new(0);
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE"]
 static ENV_INIT: Once = Once::new();
 type EnvStore = Mutex<HashMap<OsString, OsString>>;
 
index 372760bbf26b4221959e1f7a243932d630785c5e..7b113267865b6cde073e02309fdeb9a99459a19b 100644 (file)
@@ -1,6 +1,9 @@
+#[cfg(not(test))]
 use crate::alloc::{self, Layout};
 use crate::num::NonZeroUsize;
+#[cfg(not(test))]
 use crate::slice;
+#[cfg(not(test))]
 use crate::str;
 
 use super::waitqueue::{
@@ -147,6 +150,7 @@ pub unsafe fn write_unlock(&self) {
 
     // only used by __rust_rwlock_unlock below
     #[inline]
+    #[cfg_attr(test, allow(dead_code))]
     unsafe fn unlock(&self) {
         let rguard = self.readers.lock();
         let wguard = self.writer.lock();
@@ -161,9 +165,11 @@ unsafe fn unlock(&self) {
     pub unsafe fn destroy(&self) {}
 }
 
+#[cfg(not(test))]
 const EINVAL: i32 = 22;
 
 // used by libunwind port
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -173,6 +179,7 @@ pub unsafe fn destroy(&self) {}
     return 0;
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -181,6 +188,7 @@ pub unsafe fn destroy(&self) {}
     (*p).write();
     return 0;
 }
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -192,6 +200,7 @@ pub unsafe fn destroy(&self) {}
 
 // the following functions are also used by the libunwind port. They're
 // included here to make sure parallel codegen and LTO don't mess things up.
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
     if s < 0 {
@@ -203,17 +212,20 @@ pub unsafe fn destroy(&self) {}
     }
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 // NB. used by both libunwind and libpanic_abort
 pub unsafe extern "C" fn __rust_abort() {
     crate::sys::abort_internal();
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
     alloc::alloc(Layout::from_size_align_unchecked(size, align))
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
     alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
@@ -221,15 +233,13 @@ pub unsafe fn destroy(&self) {}
 
 #[cfg(test)]
 mod tests {
-
     use super::*;
     use core::array::FixedSizeArray;
-    use crate::mem::MaybeUninit;
-    use crate::{mem, ptr};
+    use crate::mem::{self, MaybeUninit};
 
-    // The below test verifies that the bytes of initialized RWLock are the ones
-    // we use in libunwind.
-    // If they change we need to update src/UnwindRustSgx.h in libunwind.
+    // Verify that the bytes of initialized RWLock are the same as in
+    // libunwind. If they change, `src/UnwindRustSgx.h` in libunwind needs to
+    // be changed too.
     #[test]
     fn test_c_rwlock_initializer() {
         const RWLOCK_INIT: &[u8] = &[
@@ -251,11 +261,28 @@ fn test_c_rwlock_initializer() {
             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
         ];
 
-        let mut init = MaybeUninit::<RWLock>::zeroed();
-        init.set(RWLock::new());
-        assert_eq!(
-            mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(),
-            RWLOCK_INIT
-        );
+        #[inline(never)]
+        fn zero_stack() {
+            test::black_box(MaybeUninit::<[RWLock; 16]>::zeroed());
+        }
+
+        #[inline(never)]
+        unsafe fn rwlock_new(init: &mut MaybeUninit<RWLock>) {
+            init.set(RWLock::new());
+        }
+
+        unsafe {
+            // try hard to make sure that the padding/unused bytes in RWLock
+            // get initialized as 0. If the assertion below fails, that might
+            // just be an issue with the test code and not with the value of
+            // RWLOCK_INIT.
+            zero_stack();
+            let mut init = MaybeUninit::<RWLock>::zeroed();
+            rwlock_new(&mut init);
+            assert_eq!(
+                mem::transmute::<_, [u8; 128]>(init.into_initialized()).as_slice(),
+                RWLOCK_INIT
+            )
+        };
     }
 }
index c0e7c824615c88a824c84005fbfcf42b6ced8fe4..e63fa2bed65d56700f5a67447f5bc134602bf205 100644 (file)
@@ -6,6 +6,7 @@ pub unsafe fn new() -> Handler {
     }
 }
 
+#[cfg_attr(test, allow(dead_code))]
 pub unsafe fn init() {
 }
 
index 13569062ac184cfd99675c800c0c0bb9d33de149..a3637723ba1bd05611daf419248562941587fce7 100644 (file)
@@ -1,3 +1,4 @@
+#![cfg_attr(test, allow(dead_code))] // why is this necessary?
 use crate::boxed::FnBox;
 use crate::ffi::CStr;
 use crate::io;
@@ -33,7 +34,11 @@ pub(super) fn run(self) {
         }
     }
 
+    #[cfg_attr(test, linkage = "available_externally")]
+    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"]
     static TASK_QUEUE_INIT: Once = Once::new();
+    #[cfg_attr(test, linkage = "available_externally")]
+    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
     static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
 
     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
index 1dbf2afbf4987e7b47368d7ecca303b69200922f..3f5e03ddad69eee59068aa76735f8a98ba1cc1a0 100644 (file)
@@ -498,6 +498,7 @@ mod tests {
         use super::*;
         use crate::sync::Arc;
         use crate::thread;
+        use crate::time::{SystemTime, Duration};
 
         #[test]
         fn sleep() {
@@ -507,7 +508,13 @@ fn sleep() {
             let t1 = thread::spawn(move || {
                 *mutex2.lock() = 1;
             });
-            thread::sleep_ms(50);
+
+            // "sleep" for 50ms
+            // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+            let start = SystemTime::now();
+            let max = Duration::from_millis(50);
+            while start.elapsed().unwrap() < max {}
+
             assert_eq!(*guard, 0);
             drop(guard);
             t1.join().unwrap();
@@ -530,7 +537,8 @@ fn queue() {
         let locked = wq.lock();
 
         let t1 = thread::spawn(move || {
-            assert!(WaitQueue::notify_one(wq2.lock()).is_none())
+            // if we obtain the lock, the main thread should be waiting
+            assert!(WaitQueue::notify_one(wq2.lock()).is_ok());
         });
 
         WaitQueue::wait(locked);
index 7ad6b124e3a384c1f57543d2230e4b0f513421de..b73c5856b8805bdd91cee0c7a9363734694ac081 100644 (file)
@@ -530,7 +530,7 @@ fn drop(&mut self) {
 
         thread::spawn(|| {
             assert!(FOO.try_with(|_| ()).is_ok());
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -584,7 +584,7 @@ fn drop(&mut self) {
 
         thread::spawn(move|| {
             drop(S1);
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -600,7 +600,7 @@ fn drop(&mut self) {
 
         thread::spawn(move|| unsafe {
             K1.with(|s| *s.get() = Some(S1));
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     // Note that this test will deadlock if TLS destructors aren't run (this
index 08f0aa2f0d2065d403bc27bee0df2ca8fd0eeaa8..8f323b59bf8e1af7950af7fa9d57e115d3a7c686 100644 (file)
@@ -1497,7 +1497,7 @@ mod tests {
     fn test_unnamed_thread() {
         thread::spawn(move|| {
             assert!(thread::current().name().is_none());
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1691,6 +1691,7 @@ fn test_park_timeout_unpark_before() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_park_timeout_unpark_not_called() {
         for _ in 0..10 {
             thread::park_timeout(Duration::from_millis(10));
@@ -1698,6 +1699,7 @@ fn test_park_timeout_unpark_not_called() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_park_timeout_unpark_called_other_thread() {
         for _ in 0..10 {
             let th = thread::current();
@@ -1712,6 +1714,7 @@ fn test_park_timeout_unpark_called_other_thread() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn sleep_ms_smoke() {
         thread::sleep(Duration::from_millis(2));
     }
index ed2218f09d26b3ad12c58681e94245a65cef42d5..0be3ec839e9a2c9c1d9795414832388fd3368c6f 100644 (file)
@@ -54,6 +54,7 @@
     "src/libstd/f64.rs",
     // Integration test for platform-specific run-time feature detection:
     "src/libstd/tests/run-time-detect.rs" ,
+    "src/libstd/net/test.rs",
     "src/libstd/sys_common/mod.rs",
     "src/libstd/sys_common/net.rs",
     "src/libterm", // Not sure how to make this crate portable, but test crate needs it.