<commit_before>use std::fmt;
use std::io;
use std::net::{SocketAddr, TcpListener as StdTcpListener};
use std::time::Duration;

use tokio::net::TcpListener;
use tokio::time::Sleep;

use crate::common::{task, Future, Pin, Poll};

#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
pub use self::addr_stream::AddrStream;
use super::accept::Accept;

/// A stream of connections from binding to an address.
#[must_use = "streams do nothing unless polled"]
pub struct AddrIncoming {
    addr: SocketAddr,
    listener: TcpListener,
    sleep_on_errors: bool,
    tcp_keepalive_timeout: Option<Duration>,
    tcp_nodelay: bool,
    timeout: Option<Pin<Box<Sleep>>>,
}

impl AddrIncoming {
    pub(super) fn new(addr: &SocketAddr) -> crate::Result<Self> {
        let std_listener = StdTcpListener::bind(addr).map_err(crate::Error::new_listen)?;

        AddrIncoming::from_std(std_listener)
    }

    pub(super) fn from_std(std_listener: StdTcpListener) -> crate::Result<Self> {
        // TcpListener::from_std doesn't set O_NONBLOCK
        std_listener
            .set_nonblocking(true)
            .map_err(crate::Error::new_listen)?;
        let listener = TcpListener::from_std(std_listener).map_err(crate::Error::new_listen)?;
        let addr = listener.local_addr().map_err(crate::Error::new_listen)?;
        Ok(AddrIncoming {
            listener,
            addr,
            sleep_on_errors: true,
            tcp_keepalive_timeout: None,
            tcp_nodelay: false,
            timeout: None,
        })
    }

    /// Creates a new `AddrIncoming` binding to provided socket address.
    pub fn bind(addr: &SocketAddr) -> crate::Result<Self> {
        AddrIncoming::new(addr)
    }

    /// Get the local address bound to this listener.
    pub fn local_addr(&self) -> SocketAddr {
        self.addr
    }

    /// Set whether TCP keepalive messages are enabled on accepted connections.
    ///
    /// If `None` is specified, keepalive is disabled, otherwise the duration
    /// specified will be the time to remain idle before sending TCP keepalive
    /// probes.
    pub fn set_keepalive(&mut self, keepalive: Option<Duration>) -> &mut Self {
        self.tcp_keepalive_timeout = keepalive;
        self
    }

    /// Set the value of `TCP_NODELAY` option for accepted connections.
    pub fn set_nodelay(&mut self, enabled: bool) -> &mut Self {
        self.tcp_nodelay = enabled;
        self
    }

    /// Set whether to sleep on accept errors.
    ///
    /// A possible scenario is that the process has hit the max open files
    /// allowed, and so trying to accept a new connection will fail with
    /// `EMFILE`. In some cases, it's preferable to just wait for some time, if
    /// the application will likely close some files (or connections), and try
    /// to accept the connection again. If this option is `true`, the error
    /// will be logged at the `error` level, since it is still a big deal,
    /// and then the listener will sleep for 1 second.
    ///
    /// In other cases, hitting the max open files should be treat similarly
    /// to being out-of-memory, and simply error (and shutdown). Setting
    /// this option to `false` will allow that.
    ///
    /// Default is `true`.
    pub fn set_sleep_on_errors(&mut self, val: bool) {
        self.sleep_on_errors = val;
    }

    fn poll_next_(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<AddrStream>> {
        // Check if a previous timeout is active that was set by IO errors.
        if let Some(ref mut to) = self.timeout {
            ready!(Pin::new(to).poll(cx));
        }
        self.timeout = None;

        loop {
            match ready!(self.listener.poll_accept(cx)) {
                Ok((socket, addr)) => {
                    if let Some(dur) = self.tcp_keepalive_timeout {
                        // Convert the Tokio `TcpStream` into a `socket2` socket
                        // so we can call `set_keepalive`.
                        // TODO(eliza): if Tokio's `TcpSocket` API grows a few
                        // more methods in the future, hopefully we shouldn't
                        // have to do the `from_raw_fd` dance any longer...
                        #[cfg(unix)]
                        let socket = unsafe {
                            // Safety: `socket2`'s socket will try to close the
                            // underlying fd when it's dropped. However, we
                            // can't take ownership of the fd from the tokio
                            // TcpStream, so instead we will call `into_raw_fd`
                            // on the socket2 socket before dropping it. This
                            // prevents it from trying to close the fd.
                            use std::os::unix::io::{AsRawFd, FromRawFd};
                            socket2::Socket::from_raw_fd(socket.as_raw_fd())
                        };
                        #[cfg(windows)]
                        let socket = unsafe {
                            // Safety: `socket2`'s socket will try to close the
                            // underlying SOCKET when it's dropped. However, we
                            // can't take ownership of the SOCKET from the tokio
                            // TcpStream, so instead we will call `into_raw_socket`
                            // on the socket2 socket before dropping it. This
                            // prevents it from trying to close the SOCKET.
                            use std::os::windows::io::{AsRawSocket, FromRawSocket};
                            socket2::Socket::from_raw_socket(socket.as_raw_socket())
                        };

                        // Actually set the TCP keepalive timeout.
                        if let Err(e) = socket.set_keepalive(Some(dur)) {
                            trace!("error trying to set TCP keepalive: {}", e);
                        }

                        // Take ownershop of the fd/socket back from the socket2
                        // `Socket`, so that socket2 doesn't try to close it
                        // when it's dropped.
                        #[cfg(unix)]
                        drop(std::os::unix::io::IntoRawFd::into_raw_fd(socket));
                        #[cfg(windows)]
                        drop(std::os::windows::io::IntoRawSocket::into_raw_socket(socket));
                    }
                    if let Err(e) = socket.set_nodelay(self.tcp_nodelay) {
                        trace!("error trying to set TCP nodelay: {}", e);
                    }
                    return Poll::Ready(Ok(AddrStream::new(socket, addr)));
                }
                Err(e) => {
                    // Connection errors can be ignored directly, continue by
                    // accepting the next request.
                    if is_connection_error(&e) {
                        debug!("accepted connection already errored: {}", e);
                        continue;
                    }

                    if self.sleep_on_errors {
                        error!("accept error: {}", e);

                        // Sleep 1s.
                        let mut timeout = Box::pin(tokio::time::sleep(Duration::from_secs(1)));

                        match timeout.as_mut().poll(cx) {
                            Poll::Ready(()) => {
                                // Wow, it's been a second already? Ok then...
                                continue;
                            }
                            Poll::Pending => {
                                self.timeout = Some(timeout);
                                return Poll::Pending;
                            }
                        }
                    } else {
                        return Poll::Ready(Err(e));
                    }
                }
            }
        }
    }
}

impl Accept for AddrIncoming {
    type Conn = AddrStream;
    type Error = io::Error;

    fn poll_accept(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
        let result = ready!(self.poll_next_(cx));
        Poll::Ready(Some(result))
    }
}

/// This function defines errors that are per-connection. Which basically
/// means that if we get this error from `accept()` system call it means
/// next connection might be ready to be accepted.
///
/// All other errors will incur a timeout before next `accept()` is performed.
/// The timeout is useful to handle resource exhaustion errors like ENFILE
/// and EMFILE. Otherwise, could enter into tight loop.
fn is_connection_error(e: &io::Error) -> bool {
    matches!(e.kind(), io::ErrorKind::ConnectionRefused
        | io::ErrorKind::ConnectionAborted
        | io::ErrorKind::ConnectionReset)
}

impl fmt::Debug for AddrIncoming {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AddrIncoming")
            .field("addr", &self.addr)
            .field("sleep_on_errors", &self.sleep_on_errors)
            .field("tcp_keepalive_timeout", &self.tcp_keepalive_timeout)
            .field("tcp_nodelay", &self.tcp_nodelay)
            .finish()
    }
}

mod addr_stream {
    use std::io;
    use std::net::SocketAddr;
    #[cfg(unix)]
    use std::os::unix::io::{AsRawFd, RawFd};
    use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
    use tokio::net::TcpStream;

    use crate::common::{task, Pin, Poll};

    /// A transport returned yieled by `AddrIncoming`.
    #[pin_project::pin_project]
    #[derive(Debug)]
    pub struct AddrStream {
        #[pin]
        inner: TcpStream,
        pub(super) remote_addr: SocketAddr,
    }

    impl AddrStream {
        pub(super) fn new(tcp: TcpStream, addr: SocketAddr) -> AddrStream {
            AddrStream {
                inner: tcp,
                remote_addr: addr,
            }
        }

        /// Returns the remote (peer) address of this connection.
        #[inline]
        pub fn remote_addr(&self) -> SocketAddr {
            self.remote_addr
        }

        /// Consumes the AddrStream and returns the underlying IO object
        #[inline]
        pub fn into_inner(self) -> TcpStream {
            self.inner
        }

        /// Attempt to receive data on the socket, without removing that data
        /// from the queue, registering the current task for wakeup if data is
        /// not yet available.
        pub fn poll_peek(
            &mut self,
            cx: &mut task::Context<'_>,
            buf: &mut tokio::io::ReadBuf<'_>,
        ) -> Poll<io::Result<usize>> {
            self.inner.poll_peek(cx, buf)
        }
    }

    impl AsyncRead for AddrStream {
        #[inline]
        fn poll_read(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &mut ReadBuf<'_>,
        ) -> Poll<io::Result<()>> {
            self.project().inner.poll_read(cx, buf)
        }
    }

    impl AsyncWrite for AddrStream {
        #[inline]
        fn poll_write(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write(cx, buf)
        }

        #[inline]
        fn poll_write_vectored(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            bufs: &[io::IoSlice<'_>],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write_vectored(cx, bufs)
        }

        #[inline]
        fn poll_flush(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            // TCP flush is a noop
            Poll::Ready(Ok(()))
        }

        #[inline]
        fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            self.project().inner.poll_shutdown(cx)
        }

        #[inline]
        fn is_write_vectored(&self) -> bool {
            // Note that since `self.inner` is a `TcpStream`, this could
            // *probably* be hard-coded to return `true`...but it seems more
            // correct to ask it anyway (maybe we're on some platform without
            // scatter-gather IO?)
            self.inner.is_write_vectored()
        }
    }

    #[cfg(unix)]
    impl AsRawFd for AddrStream {
        fn as_raw_fd(&self) -> RawFd {
            self.inner.as_raw_fd()
        }
    }
}
<commit_msg>feat(server): add `AddrIncoming::from_listener` constructor (#2439)<commit_after>use std::fmt;
use std::io;
use std::net::{SocketAddr, TcpListener as StdTcpListener};
use std::time::Duration;

use tokio::net::TcpListener;
use tokio::time::Sleep;

use crate::common::{task, Future, Pin, Poll};

#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
pub use self::addr_stream::AddrStream;
use super::accept::Accept;

/// A stream of connections from binding to an address.
#[must_use = "streams do nothing unless polled"]
pub struct AddrIncoming {
    addr: SocketAddr,
    listener: TcpListener,
    sleep_on_errors: bool,
    tcp_keepalive_timeout: Option<Duration>,
    tcp_nodelay: bool,
    timeout: Option<Pin<Box<Sleep>>>,
}

impl AddrIncoming {
    pub(super) fn new(addr: &SocketAddr) -> crate::Result<Self> {
        let std_listener = StdTcpListener::bind(addr).map_err(crate::Error::new_listen)?;

        AddrIncoming::from_std(std_listener)
    }

    pub(super) fn from_std(std_listener: StdTcpListener) -> crate::Result<Self> {
        // TcpListener::from_std doesn't set O_NONBLOCK
        std_listener
            .set_nonblocking(true)
            .map_err(crate::Error::new_listen)?;
        let listener = TcpListener::from_std(std_listener).map_err(crate::Error::new_listen)?;
        AddrIncoming::from_listener(listener)
    }

    /// Creates a new `AddrIncoming` binding to provided socket address.
    pub fn bind(addr: &SocketAddr) -> crate::Result<Self> {
        AddrIncoming::new(addr)
    }

    /// Creates a new `AddrIncoming` from an existing `tokio::net::TcpListener`.
    pub fn from_listener(listener: TcpListener) -> crate::Result<Self> {
        let addr = listener.local_addr().map_err(crate::Error::new_listen)?;
        Ok(AddrIncoming {
            listener,
            addr,
            sleep_on_errors: true,
            tcp_keepalive_timeout: None,
            tcp_nodelay: false,
            timeout: None,
        })
    }

    /// Get the local address bound to this listener.
    pub fn local_addr(&self) -> SocketAddr {
        self.addr
    }

    /// Set whether TCP keepalive messages are enabled on accepted connections.
    ///
    /// If `None` is specified, keepalive is disabled, otherwise the duration
    /// specified will be the time to remain idle before sending TCP keepalive
    /// probes.
    pub fn set_keepalive(&mut self, keepalive: Option<Duration>) -> &mut Self {
        self.tcp_keepalive_timeout = keepalive;
        self
    }

    /// Set the value of `TCP_NODELAY` option for accepted connections.
    pub fn set_nodelay(&mut self, enabled: bool) -> &mut Self {
        self.tcp_nodelay = enabled;
        self
    }

    /// Set whether to sleep on accept errors.
    ///
    /// A possible scenario is that the process has hit the max open files
    /// allowed, and so trying to accept a new connection will fail with
    /// `EMFILE`. In some cases, it's preferable to just wait for some time, if
    /// the application will likely close some files (or connections), and try
    /// to accept the connection again. If this option is `true`, the error
    /// will be logged at the `error` level, since it is still a big deal,
    /// and then the listener will sleep for 1 second.
    ///
    /// In other cases, hitting the max open files should be treat similarly
    /// to being out-of-memory, and simply error (and shutdown). Setting
    /// this option to `false` will allow that.
    ///
    /// Default is `true`.
    pub fn set_sleep_on_errors(&mut self, val: bool) {
        self.sleep_on_errors = val;
    }

    fn poll_next_(&mut self, cx: &mut task::Context<'_>) -> Poll<io::Result<AddrStream>> {
        // Check if a previous timeout is active that was set by IO errors.
        if let Some(ref mut to) = self.timeout {
            ready!(Pin::new(to).poll(cx));
        }
        self.timeout = None;

        loop {
            match ready!(self.listener.poll_accept(cx)) {
                Ok((socket, addr)) => {
                    if let Some(dur) = self.tcp_keepalive_timeout {
                        // Convert the Tokio `TcpStream` into a `socket2` socket
                        // so we can call `set_keepalive`.
                        // TODO(eliza): if Tokio's `TcpSocket` API grows a few
                        // more methods in the future, hopefully we shouldn't
                        // have to do the `from_raw_fd` dance any longer...
                        #[cfg(unix)]
                        let socket = unsafe {
                            // Safety: `socket2`'s socket will try to close the
                            // underlying fd when it's dropped. However, we
                            // can't take ownership of the fd from the tokio
                            // TcpStream, so instead we will call `into_raw_fd`
                            // on the socket2 socket before dropping it. This
                            // prevents it from trying to close the fd.
                            use std::os::unix::io::{AsRawFd, FromRawFd};
                            socket2::Socket::from_raw_fd(socket.as_raw_fd())
                        };
                        #[cfg(windows)]
                        let socket = unsafe {
                            // Safety: `socket2`'s socket will try to close the
                            // underlying SOCKET when it's dropped. However, we
                            // can't take ownership of the SOCKET from the tokio
                            // TcpStream, so instead we will call `into_raw_socket`
                            // on the socket2 socket before dropping it. This
                            // prevents it from trying to close the SOCKET.
                            use std::os::windows::io::{AsRawSocket, FromRawSocket};
                            socket2::Socket::from_raw_socket(socket.as_raw_socket())
                        };

                        // Actually set the TCP keepalive timeout.
                        if let Err(e) = socket.set_keepalive(Some(dur)) {
                            trace!("error trying to set TCP keepalive: {}", e);
                        }

                        // Take ownershop of the fd/socket back from the socket2
                        // `Socket`, so that socket2 doesn't try to close it
                        // when it's dropped.
                        #[cfg(unix)]
                        drop(std::os::unix::io::IntoRawFd::into_raw_fd(socket));
                        #[cfg(windows)]
                        drop(std::os::windows::io::IntoRawSocket::into_raw_socket(socket));
                    }
                    if let Err(e) = socket.set_nodelay(self.tcp_nodelay) {
                        trace!("error trying to set TCP nodelay: {}", e);
                    }
                    return Poll::Ready(Ok(AddrStream::new(socket, addr)));
                }
                Err(e) => {
                    // Connection errors can be ignored directly, continue by
                    // accepting the next request.
                    if is_connection_error(&e) {
                        debug!("accepted connection already errored: {}", e);
                        continue;
                    }

                    if self.sleep_on_errors {
                        error!("accept error: {}", e);

                        // Sleep 1s.
                        let mut timeout = Box::pin(tokio::time::sleep(Duration::from_secs(1)));

                        match timeout.as_mut().poll(cx) {
                            Poll::Ready(()) => {
                                // Wow, it's been a second already? Ok then...
                                continue;
                            }
                            Poll::Pending => {
                                self.timeout = Some(timeout);
                                return Poll::Pending;
                            }
                        }
                    } else {
                        return Poll::Ready(Err(e));
                    }
                }
            }
        }
    }
}

impl Accept for AddrIncoming {
    type Conn = AddrStream;
    type Error = io::Error;

    fn poll_accept(
        mut self: Pin<&mut Self>,
        cx: &mut task::Context<'_>,
    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
        let result = ready!(self.poll_next_(cx));
        Poll::Ready(Some(result))
    }
}

/// This function defines errors that are per-connection. Which basically
/// means that if we get this error from `accept()` system call it means
/// next connection might be ready to be accepted.
///
/// All other errors will incur a timeout before next `accept()` is performed.
/// The timeout is useful to handle resource exhaustion errors like ENFILE
/// and EMFILE. Otherwise, could enter into tight loop.
fn is_connection_error(e: &io::Error) -> bool {
    matches!(e.kind(), io::ErrorKind::ConnectionRefused
        | io::ErrorKind::ConnectionAborted
        | io::ErrorKind::ConnectionReset)
}

impl fmt::Debug for AddrIncoming {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AddrIncoming")
            .field("addr", &self.addr)
            .field("sleep_on_errors", &self.sleep_on_errors)
            .field("tcp_keepalive_timeout", &self.tcp_keepalive_timeout)
            .field("tcp_nodelay", &self.tcp_nodelay)
            .finish()
    }
}

mod addr_stream {
    use std::io;
    use std::net::SocketAddr;
    #[cfg(unix)]
    use std::os::unix::io::{AsRawFd, RawFd};
    use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
    use tokio::net::TcpStream;

    use crate::common::{task, Pin, Poll};

    /// A transport returned yieled by `AddrIncoming`.
    #[pin_project::pin_project]
    #[derive(Debug)]
    pub struct AddrStream {
        #[pin]
        inner: TcpStream,
        pub(super) remote_addr: SocketAddr,
    }

    impl AddrStream {
        pub(super) fn new(tcp: TcpStream, addr: SocketAddr) -> AddrStream {
            AddrStream {
                inner: tcp,
                remote_addr: addr,
            }
        }

        /// Returns the remote (peer) address of this connection.
        #[inline]
        pub fn remote_addr(&self) -> SocketAddr {
            self.remote_addr
        }

        /// Consumes the AddrStream and returns the underlying IO object
        #[inline]
        pub fn into_inner(self) -> TcpStream {
            self.inner
        }

        /// Attempt to receive data on the socket, without removing that data
        /// from the queue, registering the current task for wakeup if data is
        /// not yet available.
        pub fn poll_peek(
            &mut self,
            cx: &mut task::Context<'_>,
            buf: &mut tokio::io::ReadBuf<'_>,
        ) -> Poll<io::Result<usize>> {
            self.inner.poll_peek(cx, buf)
        }
    }

    impl AsyncRead for AddrStream {
        #[inline]
        fn poll_read(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &mut ReadBuf<'_>,
        ) -> Poll<io::Result<()>> {
            self.project().inner.poll_read(cx, buf)
        }
    }

    impl AsyncWrite for AddrStream {
        #[inline]
        fn poll_write(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write(cx, buf)
        }

        #[inline]
        fn poll_write_vectored(
            self: Pin<&mut Self>,
            cx: &mut task::Context<'_>,
            bufs: &[io::IoSlice<'_>],
        ) -> Poll<io::Result<usize>> {
            self.project().inner.poll_write_vectored(cx, bufs)
        }

        #[inline]
        fn poll_flush(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            // TCP flush is a noop
            Poll::Ready(Ok(()))
        }

        #[inline]
        fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
            self.project().inner.poll_shutdown(cx)
        }

        #[inline]
        fn is_write_vectored(&self) -> bool {
            // Note that since `self.inner` is a `TcpStream`, this could
            // *probably* be hard-coded to return `true`...but it seems more
            // correct to ask it anyway (maybe we're on some platform without
            // scatter-gather IO?)
            self.inner.is_write_vectored()
        }
    }

    #[cfg(unix)]
    impl AsRawFd for AddrStream {
        fn as_raw_fd(&self) -> RawFd {
            self.inner.as_raw_fd()
        }
    }
}
<|endoftext|>


<commit_before>use std::time::{Duration, SystemTime, Instant};
use std::convert::TryFrom;

use crate::stacked_borrows::Tag;
use crate::*;
use helpers::{immty_from_int_checked, immty_from_uint_checked};

use rustc_middle::ty::layout::LayoutOf;

/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
    time.duration_since(SystemTime::UNIX_EPOCH)
        .map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn clock_gettime(
        &mut self,
        clk_id_op: OpTy<'tcx, Tag>,
        tp_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("linux", "clock_gettime");
        this.check_no_isolation("clock_gettime")?;

        let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
        let tp = this.deref_operand(tp_op)?;

        let duration = if clk_id == this.eval_libc_i32("CLOCK_REALTIME")? {
            system_time_to_duration(&SystemTime::now())?
        } else if clk_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
            // Absolute time does not matter, only relative time does, so we can just
            // use our own time anchor here.
            Instant::now().duration_since(this.machine.time_anchor)
        } else {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        };

        let tv_sec = duration.as_secs();
        let tv_nsec = duration.subsec_nanos();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_nsec, this.libc_ty_layout("c_long")?)?,
        ];

        this.write_packed_immediates(tp, &imms)?;

        Ok(0)
    }

    fn gettimeofday(
        &mut self,
        tv_op: OpTy<'tcx, Tag>,
        tz_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("macos", "gettimeofday");
        this.check_no_isolation("gettimeofday")?;

        // Using tz is obsolete and should always be null
        let tz = this.read_scalar(tz_op)?.not_undef()?;
        if !this.is_null(tz)? {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        }

        let tv = this.deref_operand(tv_op)?;

        let duration = system_time_to_duration(&SystemTime::now())?;
        let tv_sec = duration.as_secs();
        let tv_usec = duration.subsec_micros();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_usec, this.libc_ty_layout("suseconds_t")?)?,
        ];

        this.write_packed_immediates(tv, &imms)?;

        Ok(0)
    }

    #[allow(non_snake_case)]
    fn GetSystemTimeAsFileTime(&mut self, LPFILETIME_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "GetSystemTimeAsFileTime");
        this.check_no_isolation("GetSystemTimeAsFileTime")?;

        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?;
        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?;
        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?;
        let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC;
        let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC;

        let duration = system_time_to_duration(&SystemTime::now())?
            .checked_add(Duration::from_secs(SECONDS_TO_UNIX_EPOCH))
            .unwrap();
        let duration_ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL))
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 ticks are not supported"))?;

        let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap();
        let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap();
        let DWORD_tylayout = this.layout_of(this.tcx.types.u32)?;
        let imms = [
            immty_from_uint_checked(dwLowDateTime, DWORD_tylayout)?,
            immty_from_uint_checked(dwHighDateTime, DWORD_tylayout)?,
        ];
        this.write_packed_immediates(this.deref_operand(LPFILETIME_op)?, &imms)?;
        Ok(())
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceCounter(&mut self, lpPerformanceCount_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceCounter");
        this.check_no_isolation("QueryPerformanceCounter")?;

        // QueryPerformanceCounter uses a hardware counter as its basis.
        // Miri will emulate a counter with a resolution of 1 nanosecond.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        let qpc = i64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported"))?;
        this.write_scalar(Scalar::from_i64(qpc), this.deref_operand(lpPerformanceCount_op)?.into())?;
        Ok(-1) // return non-zero on success
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceFrequency(&mut self, lpFrequency_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceFrequency");
        this.check_no_isolation("QueryPerformanceFrequency")?;

        // Retrieves the frequency of the hardware performance counter.
        // The frequency of the performance counter is fixed at system boot and
        // is consistent across all processors.
        // Miri will assume that the frequency of
        // the machine's hardware performance counter is 1 GHz ( = 1 x 10^9 Hz).
        this.write_scalar(Scalar::from_i64(1_000_000_000), this.deref_operand(lpFrequency_op)?.into())?;
        Ok(-1) // Return non-zero on success
    }

    fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
        let this = self.eval_context_ref();

        this.assert_target_os("macos", "mach_absolute_time");
        this.check_no_isolation("mach_absolute_time")?;

        // This returns a u64, with time units determined dynamically by `mach_timebase_info`.
        // We return plain nanoseconds.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        u64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported").into())
    }
}
<commit_msg>Update comments in src/shims/time.rs<commit_after>use std::time::{Duration, SystemTime, Instant};
use std::convert::TryFrom;

use crate::stacked_borrows::Tag;
use crate::*;
use helpers::{immty_from_int_checked, immty_from_uint_checked};

use rustc_middle::ty::layout::LayoutOf;

/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
    time.duration_since(SystemTime::UNIX_EPOCH)
        .map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn clock_gettime(
        &mut self,
        clk_id_op: OpTy<'tcx, Tag>,
        tp_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("linux", "clock_gettime");
        this.check_no_isolation("clock_gettime")?;

        let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
        let tp = this.deref_operand(tp_op)?;

        let duration = if clk_id == this.eval_libc_i32("CLOCK_REALTIME")? {
            system_time_to_duration(&SystemTime::now())?
        } else if clk_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
            // Absolute time does not matter, only relative time does, so we can just
            // use our own time anchor here.
            Instant::now().duration_since(this.machine.time_anchor)
        } else {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        };

        let tv_sec = duration.as_secs();
        let tv_nsec = duration.subsec_nanos();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_nsec, this.libc_ty_layout("c_long")?)?,
        ];

        this.write_packed_immediates(tp, &imms)?;

        Ok(0)
    }

    fn gettimeofday(
        &mut self,
        tv_op: OpTy<'tcx, Tag>,
        tz_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("macos", "gettimeofday");
        this.check_no_isolation("gettimeofday")?;

        // Using tz is obsolete and should always be null
        let tz = this.read_scalar(tz_op)?.not_undef()?;
        if !this.is_null(tz)? {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        }

        let tv = this.deref_operand(tv_op)?;

        let duration = system_time_to_duration(&SystemTime::now())?;
        let tv_sec = duration.as_secs();
        let tv_usec = duration.subsec_micros();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_usec, this.libc_ty_layout("suseconds_t")?)?,
        ];

        this.write_packed_immediates(tv, &imms)?;

        Ok(0)
    }

    #[allow(non_snake_case)]
    fn GetSystemTimeAsFileTime(&mut self, LPFILETIME_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "GetSystemTimeAsFileTime");
        this.check_no_isolation("GetSystemTimeAsFileTime")?;

        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?;
        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?;
        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?;
        let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC;
        let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC;

        let duration = system_time_to_duration(&SystemTime::now())?
            .checked_add(Duration::from_secs(SECONDS_TO_UNIX_EPOCH))
            .unwrap();
        let duration_ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL))
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 ticks are not supported"))?;

        let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap();
        let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap();
        let DWORD_tylayout = this.layout_of(this.tcx.types.u32)?;
        let imms = [
            immty_from_uint_checked(dwLowDateTime, DWORD_tylayout)?,
            immty_from_uint_checked(dwHighDateTime, DWORD_tylayout)?,
        ];
        this.write_packed_immediates(this.deref_operand(LPFILETIME_op)?, &imms)?;
        Ok(())
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceCounter(&mut self, lpPerformanceCount_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceCounter");
        this.check_no_isolation("QueryPerformanceCounter")?;

        // QueryPerformanceCounter uses a hardware counter as its basis.
        // Miri will emulate a counter with a resolution of 1 nanosecond.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        let qpc = i64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported"))?;
        this.write_scalar(Scalar::from_i64(qpc), this.deref_operand(lpPerformanceCount_op)?.into())?;
        Ok(-1) // return non-zero on success
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceFrequency(&mut self, lpFrequency_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceFrequency");
        this.check_no_isolation("QueryPerformanceFrequency")?;

        // Retrieves the frequency of the hardware performance counter.
        // The frequency of the performance counter is fixed at system boot and
        // is consistent across all processors.
        // Miri emulates a "hardware" performance counter with a resolution of 1ns,
        // and thus 10^9 counts per second.
        this.write_scalar(Scalar::from_i64(1_000_000_000), this.deref_operand(lpFrequency_op)?.into())?;
        Ok(-1) // Return non-zero on success
    }

    fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
        let this = self.eval_context_ref();

        this.assert_target_os("macos", "mach_absolute_time");
        this.check_no_isolation("mach_absolute_time")?;

        // This returns a u64, with time units determined dynamically by `mach_timebase_info`.
        // We return plain nanoseconds.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        u64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported").into())
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::path::Path;
use std::collections::BTreeMap;
use types::StratisResult;
use engine::Engine;
use pool::StratisPool;
use blockdev::BlockDevs;

pub struct SimEngine {
    pub pools: BTreeMap<String, Box<StratisPool>>,
}

impl SimEngine {
    pub fn new() -> SimEngine {
        SimEngine { pools: BTreeMap::new() }
    }
}

impl Engine for SimEngine {
    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   raid_level: u16)
                   -> StratisResult<()> {

        let pool = SimPool::new_pool(name, blockdev_paths, raid_level);

        self.pools.insert(name.to_owned(), pool);

        Ok(())
    }

    fn destroy_pool(&mut self, name: &str) -> StratisResult<()> {

        let deleted_pool = self.pools.remove(name);

        Ok(())
    }

    fn list_pools(&self) -> StratisResult<BTreeMap<String, Box<StratisPool>>> {

        let mut stratis_pools = BTreeMap::new();

        for (name, pool) in &self.pools {

            stratis_pools.insert(name.clone(), pool.copy());
        }

        Ok(stratis_pools)
    }
}

pub struct SimPool {
    pub name: String,
    pub block_devs: BlockDevs,
    pub raid_level: u16,
    pub online: bool,
    pub checking: bool,
}

impl SimPool {
    pub fn new_pool(name: &str, blockdev_paths: &[&Path], raid_level: u16) -> Box<StratisPool> {

        let status = BlockDevs::new(blockdev_paths);

        let block_devs = status.unwrap();

        let new_pool = SimPool {
            name: name.to_owned(),
            block_devs: block_devs.to_owned(),
            raid_level: raid_level,
            online: true,
            checking: false,
        };

        Box::new(new_pool)
    }
}

impl StratisPool for SimPool {
    fn add_blockdev(&mut self, path: &str) -> StratisResult<()> {
        println!("sim: pool::add_blockdev");
        Ok(())
    }

    fn add_cachedev(&mut self, path: &str) -> StratisResult<()> {
        println!("sim: pool::add_cachedev");
        Ok(())
    }

    fn destroy(&mut self) -> StratisResult<()> {
        println!("sim: pool::destroy");
        Ok(())
    }

    fn get_name(&mut self) -> String {
        self.name.clone()
    }
    fn copy(&self) -> Box<StratisPool> {
        let pool_copy = SimPool {
            name: self.name.clone(),
            block_devs: self.block_devs.clone(),
            raid_level: self.raid_level.clone(),
            online: true,
            checking: false,
        };
        Box::new(pool_copy)
    }
}
<commit_msg>Alphabetize "use" directives.<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use blockdev::BlockDevs;

use engine::Engine;

use pool::StratisPool;

use std::path::Path;
use std::collections::BTreeMap;

use types::StratisResult;

pub struct SimEngine {
    pub pools: BTreeMap<String, Box<StratisPool>>,
}

impl SimEngine {
    pub fn new() -> SimEngine {
        SimEngine { pools: BTreeMap::new() }
    }
}

impl Engine for SimEngine {
    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   raid_level: u16)
                   -> StratisResult<()> {

        let pool = SimPool::new_pool(name, blockdev_paths, raid_level);

        self.pools.insert(name.to_owned(), pool);

        Ok(())
    }

    fn destroy_pool(&mut self, name: &str) -> StratisResult<()> {

        let deleted_pool = self.pools.remove(name);

        Ok(())
    }

    fn list_pools(&self) -> StratisResult<BTreeMap<String, Box<StratisPool>>> {

        let mut stratis_pools = BTreeMap::new();

        for (name, pool) in &self.pools {

            stratis_pools.insert(name.clone(), pool.copy());
        }

        Ok(stratis_pools)
    }
}

pub struct SimPool {
    pub name: String,
    pub block_devs: BlockDevs,
    pub raid_level: u16,
    pub online: bool,
    pub checking: bool,
}

impl SimPool {
    pub fn new_pool(name: &str, blockdev_paths: &[&Path], raid_level: u16) -> Box<StratisPool> {

        let status = BlockDevs::new(blockdev_paths);

        let block_devs = status.unwrap();

        let new_pool = SimPool {
            name: name.to_owned(),
            block_devs: block_devs.to_owned(),
            raid_level: raid_level,
            online: true,
            checking: false,
        };

        Box::new(new_pool)
    }
}

impl StratisPool for SimPool {
    fn add_blockdev(&mut self, path: &str) -> StratisResult<()> {
        println!("sim: pool::add_blockdev");
        Ok(())
    }

    fn add_cachedev(&mut self, path: &str) -> StratisResult<()> {
        println!("sim: pool::add_cachedev");
        Ok(())
    }

    fn destroy(&mut self) -> StratisResult<()> {
        println!("sim: pool::destroy");
        Ok(())
    }

    fn get_name(&mut self) -> String {
        self.name.clone()
    }
    fn copy(&self) -> Box<StratisPool> {
        let pool_copy = SimPool {
            name: self.name.clone(),
            block_devs: self.block_devs.clone(),
            raid_level: self.raid_level.clone(),
            online: true,
            checking: false,
        };
        Box::new(pool_copy)
    }
}
<|endoftext|>


<commit_before>//! Module providing the TermLogger Implementation

use log::{LogLevel, LogLevelFilter, LogMetadata, LogRecord, SetLoggerError, set_logger, Log};
use time;
use term;
use term::{StderrTerminal, color};
use std::sync::Mutex;
use std::io::Error;
use super::SharedLogger;

/// The TermLogger struct. Provides a stderr based Logger implementation
pub struct TermLogger {
    level: LogLevelFilter,
    stderr: Mutex<Box<StderrTerminal>>,
}

impl TermLogger {

    /// init function. Globally initializes the TermLogger as the one and only used log facility.
    ///
    /// Takes the desired LogLevel as argument. It cannot be changed later on.
    /// Fails if another Logger was already initialized.
    ///
    /// # Examples
    /// '''
    /// let _ = TermLogger::init(LogLevelFilter::Info);
    /// '''
    #[allow(dead_code)]
    pub fn init(log_level: LogLevelFilter) -> Result<(), SetLoggerError> {
        set_logger(|max_log_level| {
            max_log_level.set(log_level.clone());
            TermLogger::new(log_level)
        })
    }

    /// allows to create a new logger, that can be independently used, no matter whats globally set.
    ///
    /// no macros are provided for easy logging in this case and you probably
    /// dont want to use this function, but init().
    ///
    /// Takes the desired LogLevel as argument. It cannot be changed later on.
    ///
    /// # Examples
    /// '''
    /// let term_logger = TermLogger::new(LogLevelFilter::Info);
    /// '''
    #[allow(dead_code)]
    pub fn new(log_level: LogLevelFilter) -> Box<TermLogger> {
        Box::new(TermLogger { level: log_level, stderr: Mutex::new(term::stderr().unwrap()) })
    }

    fn try_log(&self, record: &LogRecord) -> Result<(), Error> {

        if self.enabled(record.metadata()) {
            let mut stderr_lock = self.stderr.lock().unwrap();

            let cur_time = time::now();

            let color = match record.level() {
                LogLevel::Error => color::RED,
                LogLevel::Warn => color::YELLOW,
                LogLevel::Info => color::BLUE,
                LogLevel::Debug => color::CYAN,
                LogLevel::Trace => color::WHITE
            };

            if self.level() <= LogLevel::Warn {
                try!(write!(stderr_lock, "["));
                try!(stderr_lock.fg(color));
                try!(write!(stderr_lock, "{}", record.level()));
                try!(stderr_lock.reset());
                try!(writeln!(stderr_lock,
                    "] {}",
                        record.args()
                ));
            } else {
                try!(write!(stderr_lock, "{:02}:{:02}:{:02} [",
                            cur_time.tm_hour,
                            cur_time.tm_min,
                            cur_time.tm_sec));

                match record.level() {
                    LogLevel::Error |
                    LogLevel::Warn  |
                    LogLevel::Info  |
                    LogLevel::Debug => {
                        try!(stderr_lock.fg(color));
                        try!(write!(stderr_lock, "{}", record.level()));
                        try!(stderr_lock.reset());
                        try!(writeln!(stderr_lock,
                            "] {}: {}",
                                record.target(),
                                record.args()
                        ));
                    },
                    LogLevel::Trace => {
                        try!(writeln!(stderr_lock,
                            "[{}] {}: [{}:{}] - {}",
                                record.level(),
                                record.target(),
                                record.location().file(),
                                record.location().line(),
                                record.args()
                        ));
                    },
                };
            }

            try!(stderr_lock.flush());
        };

        Ok(())
    }
}

impl Log for TermLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &LogRecord) {
        let _ = self.try_log(record);
    }
}

impl SharedLogger for TermLogger {

    fn level(&self) -> LogLevelFilter {
        self.level
    }

    fn as_log(self: Box<Self>) -> Box<Log> {
        Box::new(*self)
    }

}
<commit_msg>Fix termlog display. TRACE displayed as [[TRACE], not [TRACE].<commit_after>//! Module providing the TermLogger Implementation

use log::{LogLevel, LogLevelFilter, LogMetadata, LogRecord, SetLoggerError, set_logger, Log};
use time;
use term;
use term::{StderrTerminal, color};
use std::sync::Mutex;
use std::io::Error;
use super::SharedLogger;

/// The TermLogger struct. Provides a stderr based Logger implementation
pub struct TermLogger {
    level: LogLevelFilter,
    stderr: Mutex<Box<StderrTerminal>>,
}

impl TermLogger {

    /// init function. Globally initializes the TermLogger as the one and only used log facility.
    ///
    /// Takes the desired LogLevel as argument. It cannot be changed later on.
    /// Fails if another Logger was already initialized.
    ///
    /// # Examples
    /// '''
    /// let _ = TermLogger::init(LogLevelFilter::Info);
    /// '''
    #[allow(dead_code)]
    pub fn init(log_level: LogLevelFilter) -> Result<(), SetLoggerError> {
        set_logger(|max_log_level| {
            max_log_level.set(log_level.clone());
            TermLogger::new(log_level)
        })
    }

    /// allows to create a new logger, that can be independently used, no matter whats globally set.
    ///
    /// no macros are provided for easy logging in this case and you probably
    /// dont want to use this function, but init().
    ///
    /// Takes the desired LogLevel as argument. It cannot be changed later on.
    ///
    /// # Examples
    /// '''
    /// let term_logger = TermLogger::new(LogLevelFilter::Info);
    /// '''
    #[allow(dead_code)]
    pub fn new(log_level: LogLevelFilter) -> Box<TermLogger> {
        Box::new(TermLogger { level: log_level, stderr: Mutex::new(term::stderr().unwrap()) })
    }

    fn try_log(&self, record: &LogRecord) -> Result<(), Error> {

        if self.enabled(record.metadata()) {
            let mut stderr_lock = self.stderr.lock().unwrap();

            let cur_time = time::now();

            let color = match record.level() {
                LogLevel::Error => color::RED,
                LogLevel::Warn => color::YELLOW,
                LogLevel::Info => color::BLUE,
                LogLevel::Debug => color::CYAN,
                LogLevel::Trace => color::WHITE
            };

            if self.level() <= LogLevel::Warn {
                try!(write!(stderr_lock, "["));
                try!(stderr_lock.fg(color));
                try!(write!(stderr_lock, "{}", record.level()));
                try!(stderr_lock.reset());
                try!(writeln!(stderr_lock,
                    "] {}",
                        record.args()
                ));
            } else {
                try!(write!(stderr_lock, "{:02}:{:02}:{:02} [",
                            cur_time.tm_hour,
                            cur_time.tm_min,
                            cur_time.tm_sec));
                try!(stderr_lock.fg(color));
                try!(write!(stderr_lock, "{}", record.level()));
                try!(stderr_lock.reset());
                try!(write!(stderr_lock, "] "));

                match record.level() {
                    LogLevel::Error |
                    LogLevel::Warn  |
                    LogLevel::Info  |
                    LogLevel::Debug => {
                        try!(writeln!(stderr_lock,
                            "{}: {}",
                                record.target(),
                                record.args()
                        ));
                    },
                    LogLevel::Trace => {
                        try!(writeln!(stderr_lock,
                            "{}: [{}:{}] - {}",
                                record.target(),
                                record.location().file(),
                                record.location().line(),
                                record.args()
                        ));
                    },
                };
            }

            try!(stderr_lock.flush());
        };

        Ok(())
    }
}

impl Log for TermLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &LogRecord) {
        let _ = self.try_log(record);
    }
}

impl SharedLogger for TermLogger {

    fn level(&self) -> LogLevelFilter {
        self.level
    }

    fn as_log(self: Box<Self>) -> Box<Log> {
        Box::new(*self)
    }

}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;

use crate::fdt::{begin_node, end_node, property_string, Error, Result};

fn parse_fstab_line(line: &str) -> Result<Vec<String>> {
    let vec: Vec<&str> = line.split_whitespace().collect();
    if vec.len() != 5 {
        return Err(Error::FdtFileParseError);
    }
    Ok(vec.iter().map(|s| s.to_string()).collect())
}

/// Creates a flattened device tree containing all of the parameters used
/// by Android.
///
/// # Arguments
///
/// * `fdt` - The DTB to modify. The top-most node should be open.
/// * `android-fstab` - A text file of Android fstab entries to add to the DTB
pub fn create_android_fdt(fdt: &mut Vec<u8>, fstab: File) -> Result<()> {
    let vecs = BufReader::new(fstab)
        .lines()
        .map(|l| parse_fstab_line(&l.map_err(Error::FdtIoError)?))
        .collect::<Result<Vec<Vec<String>>>>()?;
    begin_node(fdt, "firmware")?;
    begin_node(fdt, "android")?;
    property_string(fdt, "compatible", "android,firmware")?;
    begin_node(fdt, "fstab")?;
    property_string(fdt, "compatible", "android,fstab")?;
    for vec in vecs {
        let partition = &vec[1][1..];
        begin_node(fdt, partition)?;
        property_string(fdt, "compatible", &("android,".to_owned() + partition))?;
        property_string(fdt, "dev", &vec[0])?;
        property_string(fdt, "type", &vec[2])?;
        property_string(fdt, "mnt_flags", &vec[3])?;
        property_string(fdt, "fsmgr_flags", &vec[4])?;
        end_node(fdt)?;
    }
    end_node(fdt)?; // fstab
    end_node(fdt)?; // android
    end_node(fdt)?; // firmware
    Ok(())
}
<commit_msg>Put files in device tree for Android<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;

use crate::fdt::{begin_node, end_node, property_string, Error, Result};

fn parse_fstab_line(line: &str) -> Result<Vec<String>> {
    let vec: Vec<&str> = line.split_whitespace().collect();
    if vec.len() != 5 {
        return Err(Error::FdtFileParseError);
    }
    Ok(vec.iter().map(|s| s.to_string()).collect())
}

/// Creates a flattened device tree containing all of the parameters used
/// by Android.
///
/// # Arguments
///
/// * `fdt` - The DTB to modify. The top-most node should be open.
/// * `android-fstab` - A text file of Android fstab entries to add to the DTB
pub fn create_android_fdt(fdt: &mut Vec<u8>, fstab: File) -> Result<()> {
    let vecs = BufReader::new(fstab)
        .lines()
        .map(|l| parse_fstab_line(&l.map_err(Error::FdtIoError)?))
        .collect::<Result<Vec<Vec<String>>>>()?;
    begin_node(fdt, "firmware")?;
    begin_node(fdt, "android")?;
    property_string(fdt, "compatible", "android,firmware")?;

    let (dtprop, fstab): (_, Vec<_>) = vecs.into_iter().partition(|x| x[0] == "#dt-vendor");
    begin_node(fdt, "vendor")?;
    for vec in dtprop {
        let content = std::fs::read_to_string(&vec[2]).map_err(Error::FdtIoError)?;
        property_string(fdt, &vec[1], &content);
    }
    end_node(fdt)?; // vendor
    begin_node(fdt, "fstab")?;
    property_string(fdt, "compatible", "android,fstab")?;
    for vec in fstab {
        let partition = &vec[1][1..];
        begin_node(fdt, partition)?;
        property_string(fdt, "compatible", &("android,".to_owned() + partition))?;
        property_string(fdt, "dev", &vec[0])?;
        property_string(fdt, "type", &vec[2])?;
        property_string(fdt, "mnt_flags", &vec[3])?;
        property_string(fdt, "fsmgr_flags", &vec[4])?;
        end_node(fdt)?;
    }
    end_node(fdt)?; // fstab
    end_node(fdt)?; // android
    end_node(fdt)?; // firmware
    Ok(())
}
<|endoftext|>


<commit_before>use core::convert::TryInto;

use crate::syscall::io::{Io, Pio, Mmio, ReadOnly};

bitflags! {
    /// Interrupt enable flags
    struct IntEnFlags: u8 {
        const RECEIVED = 1;
        const SENT = 1 << 1;
        const ERRORED = 1 << 2;
        const STATUS_CHANGE = 1 << 3;
        // 4 to 7 are unused
    }
}

bitflags! {
    /// Line status flags
    struct LineStsFlags: u8 {
        const INPUT_FULL = 1;
        // 1 to 4 unknown
        const OUTPUT_EMPTY = 1 << 5;
        // 6 and 7 unknown
    }
}

#[allow(dead_code)]
#[repr(packed)]
pub struct SerialPort<T: Io> {
    /// Data register, read to receive, write to send
    data: T,
    /// Interrupt enable
    int_en: T,
    /// FIFO control
    fifo_ctrl: T,
    /// Line control
    line_ctrl: T,
    /// Modem control
    modem_ctrl: T,
    /// Line status
    line_sts: ReadOnly<T>,
    /// Modem status
    modem_sts: ReadOnly<T>,
}

impl SerialPort<Pio<u8>> {
    pub const fn new(base: u16) -> SerialPort<Pio<u8>> {
        SerialPort {
            data: Pio::new(base),
            int_en: Pio::new(base + 1),
            fifo_ctrl: Pio::new(base + 2),
            line_ctrl: Pio::new(base + 3),
            modem_ctrl: Pio::new(base + 4),
            line_sts: ReadOnly::new(Pio::new(base + 5)),
            modem_sts: ReadOnly::new(Pio::new(base + 6))
        }
    }
}

impl SerialPort<Mmio<u32>> {
    pub unsafe fn new(base: usize) -> &'static mut SerialPort<Mmio<u32>> {
        &mut *(base as *mut Self)
    }
}

impl<T: Io> SerialPort<T>
    where T::Value: From<u8> + TryInto<u8>
{
    pub fn init(&mut self) {
        //TODO: Cleanup
        self.int_en.write(0x00.into());
        self.line_ctrl.write(0x80.into());
        self.data.write(0x01.into());
        self.int_en.write(0x00.into());
        self.line_ctrl.write(0x03.into());
        self.fifo_ctrl.write(0xC7.into());
        self.modem_ctrl.write(0x0B.into());
        self.int_en.write(0x01.into());
    }

    fn line_sts(&self) -> LineStsFlags {
        LineStsFlags::from_bits_truncate(
            (self.line_sts.read() & 0xFF.into()).try_into().unwrap_or(0)
        )
    }

    pub fn receive(&mut self) -> Option<u8> {
        if self.line_sts().contains(LineStsFlags::INPUT_FULL) {
            Some(
                (self.data.read() & 0xFF.into()).try_into().unwrap_or(0)
            )
        } else {
            None
        }
    }

    pub fn send(&mut self, data: u8) {
        while ! self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY) {}
        self.data.write(data.into());
    }

    pub fn write(&mut self, buf: &[u8]) {
        for &b in buf {
            match b {
                8 | 0x7F => {
                    self.send(8);
                    self.send(b' ');
                    self.send(8);
                },
                b'\n' => {
                    self.send(b'\r');
                    self.send(b'\n');
                },
                _ => {
                    self.send(b);
                }
            }
        }
    }
}
<commit_msg>Fix borrow of packed field<commit_after>use core::convert::TryInto;

use crate::syscall::io::{Io, Pio, Mmio, ReadOnly};

bitflags! {
    /// Interrupt enable flags
    struct IntEnFlags: u8 {
        const RECEIVED = 1;
        const SENT = 1 << 1;
        const ERRORED = 1 << 2;
        const STATUS_CHANGE = 1 << 3;
        // 4 to 7 are unused
    }
}

bitflags! {
    /// Line status flags
    struct LineStsFlags: u8 {
        const INPUT_FULL = 1;
        // 1 to 4 unknown
        const OUTPUT_EMPTY = 1 << 5;
        // 6 and 7 unknown
    }
}

#[allow(dead_code)]
#[repr(packed)]
pub struct SerialPort<T: Io> {
    /// Data register, read to receive, write to send
    data: T,
    /// Interrupt enable
    int_en: T,
    /// FIFO control
    fifo_ctrl: T,
    /// Line control
    line_ctrl: T,
    /// Modem control
    modem_ctrl: T,
    /// Line status
    line_sts: ReadOnly<T>,
    /// Modem status
    modem_sts: ReadOnly<T>,
}

impl SerialPort<Pio<u8>> {
    pub const fn new(base: u16) -> SerialPort<Pio<u8>> {
        SerialPort {
            data: Pio::new(base),
            int_en: Pio::new(base + 1),
            fifo_ctrl: Pio::new(base + 2),
            line_ctrl: Pio::new(base + 3),
            modem_ctrl: Pio::new(base + 4),
            line_sts: ReadOnly::new(Pio::new(base + 5)),
            modem_sts: ReadOnly::new(Pio::new(base + 6))
        }
    }
}

impl SerialPort<Mmio<u32>> {
    pub unsafe fn new(base: usize) -> &'static mut SerialPort<Mmio<u32>> {
        &mut *(base as *mut Self)
    }
}

impl<T: Io> SerialPort<T>
    where T::Value: From<u8> + TryInto<u8>
{
    pub fn init(&mut self) {
        //TODO: Cleanup
        unsafe {
        self.int_en.write(0x00.into());
        self.line_ctrl.write(0x80.into());
        self.data.write(0x01.into());
        self.int_en.write(0x00.into());
        self.line_ctrl.write(0x03.into());
        self.fifo_ctrl.write(0xC7.into());
        self.modem_ctrl.write(0x0B.into());
        self.int_en.write(0x01.into());
        }
    }

    fn line_sts(&self) -> LineStsFlags {
        LineStsFlags::from_bits_truncate(
            (unsafe {self.line_sts.read()} & 0xFF.into()).try_into().unwrap_or(0)
        )
    }

    pub fn receive(&mut self) -> Option<u8> {
        if self.line_sts().contains(LineStsFlags::INPUT_FULL) {
            Some(
                (unsafe {self.data.read()} & 0xFF.into()).try_into().unwrap_or(0)
            )
        } else {
            None
        }
    }

    pub fn send(&mut self, data: u8) {
        while ! self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY) {}
        unsafe {self.data.write(data.into())}
    }

    pub fn write(&mut self, buf: &[u8]) {
        for &b in buf {
            match b {
                8 | 0x7F => {
                    self.send(8);
                    self.send(b' ');
                    self.send(8);
                },
                b'\n' => {
                    self.send(b'\r');
                    self.send(b'\n');
                },
                _ => {
                    self.send(b);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::iter::Peekable;
use std::iter::Enumerate;

use ::syntax::lexer::{Token, Lexer};
use ::syntax::next_is;

pub struct PythonSyntax;

impl Lexer for PythonSyntax {
    fn handle_char(&self, ch: char, mut iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize, idx: usize) -> Option<Token> {
        match ch {
            '#' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("#");
                while let Some(&(e, c)) = iter.peek() {
                    if c == '\n' { break }
                    end = e;
                    s.push(iter.next().unwrap().1)
                }
                return Some(Token::SingleLineComment(s));
            }

            '@' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("@");
                while let Some(&(e, c)) = iter.peek() {
                    if c == '\n' { break }
                    end = e;
                    s.push(iter.next().unwrap().1)
                }
                return Some(Token::Attribute(s));
            }

            ch if ch == '"' || ch == '\'' => {
                let st = idx;
                let mut end = idx;
                let mut s= format!("{}", ch);
                while let Some(&(e, c)) = iter.peek() {
                    end = e;
                    s.push(iter.next().unwrap().1);
                    if c == ch {
                        break;
                    }
                }
                return Some(Token::String(s));
            }

            _ => None,
        }

    }

    fn handle_ident(&self, ch: char, iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize) -> Token {
        let mut ident = String::new();
        ident.push(ch);
        let start = iter.peek().unwrap().0 - 1;

        while self.is_ident(iter.peek()) {
            ident.push(iter.next().unwrap().1)
        }

        Token::Ident(ident)
    }
}

<commit_msg>Highlight python function calls / defs<commit_after>use std::str::Chars;
use std::iter::Peekable;
use std::iter::Enumerate;

use ::syntax::lexer::{Token, Lexer};
use ::syntax::next_is;

pub struct PythonSyntax;

impl Lexer for PythonSyntax {
    fn handle_char(&self, ch: char, mut iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize, idx: usize) -> Option<Token> {
        match ch {
            '#' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("#");
                while let Some(&(e, c)) = iter.peek() {
                    if c == '\n' { break }
                    end = e;
                    s.push(iter.next().unwrap().1)
                }
                return Some(Token::SingleLineComment(s));
            }

            '@' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("@");
                while let Some(&(e, c)) = iter.peek() {
                    if c == '\n' { break }
                    end = e;
                    s.push(iter.next().unwrap().1)
                }
                return Some(Token::Attribute(s));
            }

            ch if ch == '"' || ch == '\'' => {
                let st = idx;
                let mut end = idx;
                let mut s= format!("{}", ch);
                while let Some(&(e, c)) = iter.peek() {
                    end = e;
                    s.push(iter.next().unwrap().1);
                    if c == ch {
                        break;
                    }
                }
                return Some(Token::String(s));
            }

            _ => None,
        }

    }

    fn handle_ident(&self, ch: char, mut iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize) -> Token {
        let mut ident = String::new();
        ident.push(ch);
        let start = iter.peek().unwrap().0 - 1;

        while self.is_ident(iter.peek()) {
            ident.push(iter.next().unwrap().1)
        }

        let token;
        if next_is(&mut iter, '(') {
            // function calls or definitions
            token = Token::FunctionCallDef(ident);
        } else {
            // regular idents
            token = Token::Ident(ident);
        }

        token
    }
}

<|endoftext|>


<commit_before>import std::io;
import std::ioivec;
import std::str;
import std::option;
import std::vec;
import std::fs;
import std::os;
import std::ivec;
import std::test;

import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::cx;
import common::config;
import header::load_props;
import header::test_props;
import util::logv;

export run;

fn run(cx: &cx, testfile: &str) {
    test::configure_test_task();
    if (cx.config.verbose) {
        // We're going to be dumping a lot of info. Start on a new line.
        io::stdout().write_str("\n\n");
    }
    log #fmt("running %s", testfile);
    let props = load_props(testfile);
    alt cx.config.mode {
      mode_compile_fail. { run_cfail_test(cx, props, testfile); }
      mode_run_fail. { run_rfail_test(cx, props, testfile); }
      mode_run_pass. { run_rpass_test(cx, props, testfile); }
      mode_pretty. { run_pretty_test(cx, props, testfile); }
    }
}

fn run_cfail_test(cx: &cx, props: &test_props, testfile: &str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status == 0 {
        fatal_procres("compile-fail test compiled successfully!",
                      procres);
    }

    check_error_patterns(props, testfile, procres);
}

fn run_rfail_test(cx: &cx, props: &test_props, testfile: &str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 {
        fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, testfile);

    if procres.status == 0 {
        fatal_procres("run-fail test didn't produce an error!",
                      procres);
    }

    check_error_patterns(props, testfile, procres);
}

fn run_rpass_test(cx: &cx, props: &test_props, testfile: &str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 {
        fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, testfile);

    if procres.status != 0 { fatal_procres("test run failed!", procres); }
}

fn run_pretty_test(cx: &cx, props: &test_props, testfile: &str) {
    if option::is_some(props.pp_exact) {
        logv(cx.config, "testing for exact pretty-printing");
    } else {
        logv(cx.config, "testing for converging pretty-printing");
    }

    let rounds = alt props.pp_exact {
      option::some(_) { 1 }
      option::none. { 2 }
    };

    let srcs = ~[ioivec::read_whole_file_str(testfile)];

    let round = 0;
    while round < rounds {
        logv(cx.config, #fmt("pretty-printing round %d", round));
        let procres = print_source(cx, testfile, srcs.(round));

        if procres.status != 0 {
            fatal_procres(#fmt("pretty-printing failed in round %d", round),
                          procres);
        }

        srcs += ~[procres.stdout];
        round += 1;
    }

    let expected = alt props.pp_exact {
      option::some(file) {
        let filepath = fs::connect(fs::dirname(testfile), file);
        ioivec::read_whole_file_str(filepath)
      }
      option::none. {
        srcs.(ivec::len(srcs) - 2u)
      }
    };
    let actual = srcs.(ivec::len(srcs) - 1u);

    compare_source(expected, actual);

    // Finally, let's make sure it actually appears to remain valid code
    let procres = typecheck_source(cx, testfile, actual);

    if procres.status != 0 {
        fatal_procres("pretty-printed source does not typecheck",
                      procres);
    }

    ret;

    fn print_source(cx: &cx, testfile: &str, src: &str) -> procres {
        compose_and_run(cx, testfile, make_pp_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_pp_args(config: &config, testfile: &str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--pretty", "normal"];
        ret {prog: prog, args: args};
    }

    fn compare_source(expected: &str, actual: &str) {
        if expected != actual {
            error("pretty-printed source does match expected source");
            let msg = #fmt("\n\
expected:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
actual:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
                          expected, actual);
            io::stdout().write_str(msg);
            fail;
        }
    }

    fn typecheck_source(cx: &cx, testfile: &str, src: &str) -> procres {
        compose_and_run(cx, testfile, make_typecheck_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_typecheck_args(config: &config, testfile: &str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--no-trans", "--lib"];
        ret {prog: prog, args: args};
    }
}

fn check_error_patterns(props: &test_props, testfile: &str,
                        procres: &procres) {
    if ivec::is_empty(props.error_patterns) {
        fatal("no error pattern specified in " + testfile);
    }

    let next_err_idx = 0u;
    let next_err_pat = props.error_patterns.(next_err_idx);
    for line: str  in str::split(procres.stdout, '\n' as u8) {
        if str::find(line, next_err_pat) > 0 {
            log #fmt("found error pattern %s", next_err_pat);
            next_err_idx += 1u;
            if next_err_idx == ivec::len(props.error_patterns) {
                log "found all error patterns";
                ret;
            }
            next_err_pat = props.error_patterns.(next_err_idx);
        }
    }

    let missing_patterns =
        ivec::slice(props.error_patterns, next_err_idx,
                    ivec::len(props.error_patterns));
    if ivec::len(missing_patterns) == 1u {
        fatal_procres(#fmt("error pattern '%s' not found!",
                           missing_patterns.(0)), procres);
    } else {
        for pattern: str  in missing_patterns {
            error(#fmt("error pattern '%s' not found!", pattern));
        }
        fatal_procres("multiple error patterns not found", procres);
    }
}

type procargs = {prog: str, args: vec[str]};

type procres = {status: int, stdout: str, stderr: str, cmdline: str};

fn compile_test(cx: &cx, props: &test_props, testfile: &str) -> procres {
    compose_and_run(cx, testfile, bind make_compile_args(_, props, _),
                    cx.config.compile_lib_path, option::none)
}

fn exec_compiled_test(cx: &cx, testfile: &str) -> procres {
    compose_and_run(cx, testfile, make_run_args,
                    cx.config.run_lib_path, option::none)
}

fn compose_and_run(cx: &cx, testfile: &str,
                   make_args: fn(&config, &str) -> procargs ,
                   lib_path: &str,
                   input: option::t[str]) -> procres {
    let procargs = make_args(cx.config, testfile);
    ret program_output(cx, testfile, lib_path,
                       procargs.prog, procargs.args,
                       input);
}

fn make_compile_args(config: &config,
                     props: &test_props, testfile: &str) ->
    procargs {
    let prog = config.rustc_path;
    let args = [testfile, "-o", make_exe_name(config, testfile)];
    args += split_maybe_args(config.rustcflags);
    args += split_maybe_args(props.compile_flags);
    ret {prog: prog, args: args};
}

fn make_exe_name(config: &config, testfile: &str) -> str {
    output_base_name(config, testfile) + os::exec_suffix()
}

fn make_run_args(config: &config, testfile: &str) -> procargs {
    // If we've got another tool to run under (valgrind),
    // then split apart its command
    let args =
        split_maybe_args(config.runtool)
        + [make_exe_name(config, testfile)];
    ret {prog: args.(0), args: vec::slice(args, 1u, vec::len(args))};
}

fn split_maybe_args(argstr: &option::t[str]) -> vec[str] {
    fn rm_whitespace(v: vec[str]) -> vec[str] {
        fn flt(s: &str) -> option::t[str] {
            if !is_whitespace(s) {
                option::some(s)
            } else {
                option::none
            }
        }

        // FIXME: This should be in std
        fn is_whitespace(s: str) -> bool {
            for c: u8 in s {
                if c != (' ' as u8) { ret false; }
            }
            ret true;
        }
        vec::filter_map(flt, v)
    }

    alt argstr {
      option::some(s) { rm_whitespace(str::split(s, ' ' as u8)) }
      option::none. { [] }
    }
}

fn program_output(cx: &cx, testfile: &str, lib_path: &str, prog: &str,
                  args: &vec[str], input: option::t[str]) -> procres {
    let cmdline =
    {
        let cmdline = make_cmdline(lib_path, prog, args);
        logv(cx.config, #fmt("executing %s", cmdline));
        cmdline
    };
    let res = procsrv::run(cx.procsrv, lib_path,
                           prog, args, input);
    dump_output(cx.config, testfile, res.out, res.err);
    ret {status: res.status, stdout: res.out,
         stderr: res.err, cmdline: cmdline};
}

fn make_cmdline(libpath: &str, prog: &str, args: &vec[str]) -> str {
    #fmt("%s %s %s", lib_path_cmd_prefix(libpath), prog,
         str::connect(args, " "))
}

// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
// for diagnostic purposes
fn lib_path_cmd_prefix(path: &str) -> str {
    #fmt("%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path))
}

fn dump_output(config: &config, testfile: &str,
               out: &str, err: &str) {
    dump_output_file(config, testfile, out, "out");
    dump_output_file(config, testfile, err, "err");
    maybe_dump_to_stdout(config, out, err);
}

#[cfg(target_os = "win32")]
#[cfg(target_os = "linux")]
fn dump_output_file(config: &config, testfile: &str,
                    out: &str, extension: &str) {
    let outfile = make_out_name(config, testfile, extension);
    let writer = io::file_writer(outfile, [io::create, io::truncate]);
    writer.write_str(out);
}

// FIXME (726): Can't use file_writer on mac
#[cfg(target_os = "macos")]
fn dump_output_file(config: &config, testfile: &str,
                    out: &str, extension: &str) {
}

fn make_out_name(config: &config, testfile: &str,
                 extension: &str) -> str {
    output_base_name(config, testfile) + "." + extension
}

fn output_base_name(config: &config, testfile: &str) -> str {
    let base = config.build_base;
    let filename =
        {
            let parts = str::split(fs::basename(testfile), '.' as u8);
            parts = vec::slice(parts, 0u, vec::len(parts) - 1u);
            str::connect(parts, ".")
        };
    #fmt("%s%s.%s", base, filename, config.stage_id)
}

fn maybe_dump_to_stdout(config: &config,
                        out: &str, err: &str) {
    if config.verbose {
        let sep1 = #fmt("------%s------------------------------",
                        "stdout");
        let sep2 = #fmt("------%s------------------------------",
                        "stderr");
        let sep3 = "------------------------------------------";
        io::stdout().write_line(sep1);
        io::stdout().write_line(out);
        io::stdout().write_line(sep2);
        io::stdout().write_line(err);
        io::stdout().write_line(sep3);
    }
}

fn error(err: &str) { io::stdout().write_line(#fmt("\nerror: %s", err)); }

fn fatal(err: &str) -> ! { error(err); fail; }

fn fatal_procres(err: &str, procres: procres) -> ! {
    let msg =
        #fmt("\n\
error: %s\n\
command: %s\n\
stdout:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
stderr:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
             err, procres.cmdline, procres.stdout, procres.stderr);
    io::stdout().write_str(msg);
    fail;
}
<commit_msg>Convert line endings when doing exact pretty-print testing<commit_after>import std::io;
import std::ioivec;
import std::str;
import std::option;
import std::vec;
import std::fs;
import std::os;
import std::ivec;
import std::test;

import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::cx;
import common::config;
import header::load_props;
import header::test_props;
import util::logv;

export run;

fn run(cx: &cx, testfile: &str) {
    test::configure_test_task();
    if (cx.config.verbose) {
        // We're going to be dumping a lot of info. Start on a new line.
        io::stdout().write_str("\n\n");
    }
    log #fmt("running %s", testfile);
    let props = load_props(testfile);
    alt cx.config.mode {
      mode_compile_fail. { run_cfail_test(cx, props, testfile); }
      mode_run_fail. { run_rfail_test(cx, props, testfile); }
      mode_run_pass. { run_rpass_test(cx, props, testfile); }
      mode_pretty. { run_pretty_test(cx, props, testfile); }
    }
}

fn run_cfail_test(cx: &cx, props: &test_props, testfile: &str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status == 0 {
        fatal_procres("compile-fail test compiled successfully!",
                      procres);
    }

    check_error_patterns(props, testfile, procres);
}

fn run_rfail_test(cx: &cx, props: &test_props, testfile: &str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 {
        fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, testfile);

    if procres.status == 0 {
        fatal_procres("run-fail test didn't produce an error!",
                      procres);
    }

    check_error_patterns(props, testfile, procres);
}

fn run_rpass_test(cx: &cx, props: &test_props, testfile: &str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 {
        fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, testfile);

    if procres.status != 0 { fatal_procres("test run failed!", procres); }
}

fn run_pretty_test(cx: &cx, props: &test_props, testfile: &str) {
    if option::is_some(props.pp_exact) {
        logv(cx.config, "testing for exact pretty-printing");
    } else {
        logv(cx.config, "testing for converging pretty-printing");
    }

    let rounds = alt props.pp_exact {
      option::some(_) { 1 }
      option::none. { 2 }
    };

    let srcs = ~[ioivec::read_whole_file_str(testfile)];

    let round = 0;
    while round < rounds {
        logv(cx.config, #fmt("pretty-printing round %d", round));
        let procres = print_source(cx, testfile, srcs.(round));

        if procres.status != 0 {
            fatal_procres(#fmt("pretty-printing failed in round %d", round),
                          procres);
        }

        srcs += ~[procres.stdout];
        round += 1;
    }

    let expected = alt props.pp_exact {
      option::some(file) {
        let filepath = fs::connect(fs::dirname(testfile), file);
        ioivec::read_whole_file_str(filepath)
      }
      option::none. {
        srcs.(ivec::len(srcs) - 2u)
      }
    };
    let actual = srcs.(ivec::len(srcs) - 1u);

    if option::is_some(props.pp_exact) {
        // Now we have to care about line endings
        let cr = "\r";
        check str::is_not_empty(cr);
        actual = str::replace(actual, cr, "");
        expected = str::replace(expected, cr, "");
    }

    compare_source(expected, actual);

    // Finally, let's make sure it actually appears to remain valid code
    let procres = typecheck_source(cx, testfile, actual);

    if procres.status != 0 {
        fatal_procres("pretty-printed source does not typecheck",
                      procres);
    }

    ret;

    fn print_source(cx: &cx, testfile: &str, src: &str) -> procres {
        compose_and_run(cx, testfile, make_pp_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_pp_args(config: &config, testfile: &str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--pretty", "normal"];
        ret {prog: prog, args: args};
    }

    fn compare_source(expected: &str, actual: &str) {
        if expected != actual {
            error("pretty-printed source does match expected source");
            let msg = #fmt("\n\
expected:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
actual:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
                          expected, actual);
            io::stdout().write_str(msg);
            fail;
        }
    }

    fn typecheck_source(cx: &cx, testfile: &str, src: &str) -> procres {
        compose_and_run(cx, testfile, make_typecheck_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_typecheck_args(config: &config, testfile: &str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--no-trans", "--lib"];
        ret {prog: prog, args: args};
    }
}

fn check_error_patterns(props: &test_props, testfile: &str,
                        procres: &procres) {
    if ivec::is_empty(props.error_patterns) {
        fatal("no error pattern specified in " + testfile);
    }

    let next_err_idx = 0u;
    let next_err_pat = props.error_patterns.(next_err_idx);
    for line: str  in str::split(procres.stdout, '\n' as u8) {
        if str::find(line, next_err_pat) > 0 {
            log #fmt("found error pattern %s", next_err_pat);
            next_err_idx += 1u;
            if next_err_idx == ivec::len(props.error_patterns) {
                log "found all error patterns";
                ret;
            }
            next_err_pat = props.error_patterns.(next_err_idx);
        }
    }

    let missing_patterns =
        ivec::slice(props.error_patterns, next_err_idx,
                    ivec::len(props.error_patterns));
    if ivec::len(missing_patterns) == 1u {
        fatal_procres(#fmt("error pattern '%s' not found!",
                           missing_patterns.(0)), procres);
    } else {
        for pattern: str  in missing_patterns {
            error(#fmt("error pattern '%s' not found!", pattern));
        }
        fatal_procres("multiple error patterns not found", procres);
    }
}

type procargs = {prog: str, args: vec[str]};

type procres = {status: int, stdout: str, stderr: str, cmdline: str};

fn compile_test(cx: &cx, props: &test_props, testfile: &str) -> procres {
    compose_and_run(cx, testfile, bind make_compile_args(_, props, _),
                    cx.config.compile_lib_path, option::none)
}

fn exec_compiled_test(cx: &cx, testfile: &str) -> procres {
    compose_and_run(cx, testfile, make_run_args,
                    cx.config.run_lib_path, option::none)
}

fn compose_and_run(cx: &cx, testfile: &str,
                   make_args: fn(&config, &str) -> procargs ,
                   lib_path: &str,
                   input: option::t[str]) -> procres {
    let procargs = make_args(cx.config, testfile);
    ret program_output(cx, testfile, lib_path,
                       procargs.prog, procargs.args,
                       input);
}

fn make_compile_args(config: &config,
                     props: &test_props, testfile: &str) ->
    procargs {
    let prog = config.rustc_path;
    let args = [testfile, "-o", make_exe_name(config, testfile)];
    args += split_maybe_args(config.rustcflags);
    args += split_maybe_args(props.compile_flags);
    ret {prog: prog, args: args};
}

fn make_exe_name(config: &config, testfile: &str) -> str {
    output_base_name(config, testfile) + os::exec_suffix()
}

fn make_run_args(config: &config, testfile: &str) -> procargs {
    // If we've got another tool to run under (valgrind),
    // then split apart its command
    let args =
        split_maybe_args(config.runtool)
        + [make_exe_name(config, testfile)];
    ret {prog: args.(0), args: vec::slice(args, 1u, vec::len(args))};
}

fn split_maybe_args(argstr: &option::t[str]) -> vec[str] {
    fn rm_whitespace(v: vec[str]) -> vec[str] {
        fn flt(s: &str) -> option::t[str] {
            if !is_whitespace(s) {
                option::some(s)
            } else {
                option::none
            }
        }

        // FIXME: This should be in std
        fn is_whitespace(s: str) -> bool {
            for c: u8 in s {
                if c != (' ' as u8) { ret false; }
            }
            ret true;
        }
        vec::filter_map(flt, v)
    }

    alt argstr {
      option::some(s) { rm_whitespace(str::split(s, ' ' as u8)) }
      option::none. { [] }
    }
}

fn program_output(cx: &cx, testfile: &str, lib_path: &str, prog: &str,
                  args: &vec[str], input: option::t[str]) -> procres {
    let cmdline =
    {
        let cmdline = make_cmdline(lib_path, prog, args);
        logv(cx.config, #fmt("executing %s", cmdline));
        cmdline
    };
    let res = procsrv::run(cx.procsrv, lib_path,
                           prog, args, input);
    dump_output(cx.config, testfile, res.out, res.err);
    ret {status: res.status, stdout: res.out,
         stderr: res.err, cmdline: cmdline};
}

fn make_cmdline(libpath: &str, prog: &str, args: &vec[str]) -> str {
    #fmt("%s %s %s", lib_path_cmd_prefix(libpath), prog,
         str::connect(args, " "))
}

// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
// for diagnostic purposes
fn lib_path_cmd_prefix(path: &str) -> str {
    #fmt("%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path))
}

fn dump_output(config: &config, testfile: &str,
               out: &str, err: &str) {
    dump_output_file(config, testfile, out, "out");
    dump_output_file(config, testfile, err, "err");
    maybe_dump_to_stdout(config, out, err);
}

#[cfg(target_os = "win32")]
#[cfg(target_os = "linux")]
fn dump_output_file(config: &config, testfile: &str,
                    out: &str, extension: &str) {
    let outfile = make_out_name(config, testfile, extension);
    let writer = io::file_writer(outfile, [io::create, io::truncate]);
    writer.write_str(out);
}

// FIXME (726): Can't use file_writer on mac
#[cfg(target_os = "macos")]
fn dump_output_file(config: &config, testfile: &str,
                    out: &str, extension: &str) {
}

fn make_out_name(config: &config, testfile: &str,
                 extension: &str) -> str {
    output_base_name(config, testfile) + "." + extension
}

fn output_base_name(config: &config, testfile: &str) -> str {
    let base = config.build_base;
    let filename =
        {
            let parts = str::split(fs::basename(testfile), '.' as u8);
            parts = vec::slice(parts, 0u, vec::len(parts) - 1u);
            str::connect(parts, ".")
        };
    #fmt("%s%s.%s", base, filename, config.stage_id)
}

fn maybe_dump_to_stdout(config: &config,
                        out: &str, err: &str) {
    if config.verbose {
        let sep1 = #fmt("------%s------------------------------",
                        "stdout");
        let sep2 = #fmt("------%s------------------------------",
                        "stderr");
        let sep3 = "------------------------------------------";
        io::stdout().write_line(sep1);
        io::stdout().write_line(out);
        io::stdout().write_line(sep2);
        io::stdout().write_line(err);
        io::stdout().write_line(sep3);
    }
}

fn error(err: &str) { io::stdout().write_line(#fmt("\nerror: %s", err)); }

fn fatal(err: &str) -> ! { error(err); fail; }

fn fatal_procres(err: &str, procres: procres) -> ! {
    let msg =
        #fmt("\n\
error: %s\n\
command: %s\n\
stdout:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
stderr:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
             err, procres.cmdline, procres.stdout, procres.stderr);
    io::stdout().write_str(msg);
    fail;
}
<|endoftext|>


<commit_before>// XFAIL-stage0
use std;

fn main() {
  auto x = std.option.some[int](10);
}
<commit_msg>"xfail-stage0", not "XFAIL-stage0"<commit_after>// xfail-stage0
use std;

fn main() {
  auto x = std.option.some[int](10);
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// GetLastError doesn't seem to work with stack switching

// pretty-expanded FIXME #23616

#[cfg(windows)]
mod kernel32 {
  extern "system" {
    pub fn SetLastError(err: uint);
    pub fn GetLastError() -> uint;
  }
}

#[cfg(windows)]
pub fn main() {
    unsafe {
        let expected = 1234;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        println!("actual = {}", actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(any(target_os = "macos",
          target_os = "linux",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "openbsd",
          target_os = "android"))]
pub fn main() { }
<commit_msg>Test fixes and rebase conflicts, round 4<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// GetLastError doesn't seem to work with stack switching

#[cfg(windows)]
mod kernel32 {
  extern "system" {
    pub fn SetLastError(err: uint);
    pub fn GetLastError() -> uint;
  }
}

#[cfg(windows)]
pub fn main() {
    unsafe {
        let expected = 1234;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        println!("actual = {}", actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(any(target_os = "macos",
          target_os = "linux",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "openbsd",
          target_os = "android"))]
pub fn main() { }
<|endoftext|>