<commit_before>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc;
use {Errno, Result};
use std::mem;
use std::ptr;

pub use libc::{
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGKILL,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

pub const NSIG: libc::c_int = 32;

bitflags!{
    flags SaFlag: libc::c_int {
        const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
        const SA_NOCLDWAIT = libc::SA_NOCLDWAIT,
        const SA_NODEFER   = libc::SA_NODEFER,
        const SA_ONSTACK   = libc::SA_ONSTACK,
        const SA_RESETHAND = libc::SA_RESETHAND,
        const SA_RESTART   = libc::SA_RESTART,
        const SA_SIGINFO   = libc::SA_SIGINFO,
    }
}

bitflags!{
    flags SigFlag: libc::c_int {
        const SIG_BLOCK   = libc::SIG_BLOCK,
        const SIG_UNBLOCK = libc::SIG_UNBLOCK,
        const SIG_SETMASK = libc::SIG_SETMASK,
    }
}

mod ffi {
    use libc;
    extern {
        pub fn sigwait(set: *const libc::sigset_t, sig: *mut libc::c_int) -> libc::c_int;
    }
}

#[derive(Clone, Copy)]
pub struct SigSet {
    sigset: libc::sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn all() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn empty() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn remove(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn contains(&self, signum: SigNum) -> Result<bool> {
        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };

        match try!(Errno::result(res)) {
            1 => Ok(true),
            0 => Ok(false),
            _ => unreachable!("unexpected value from sigismember"),
        }
    }

    /// Gets the currently blocked (masked) set of signals for the calling thread.
    pub fn thread_get_mask() -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(SigFlag::empty(), None, Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Sets the set of signals as the signal mask for the calling thread.
    pub fn thread_set_mask(&self) -> Result<()> {
        pthread_sigmask(SIG_SETMASK, Some(self), None)
    }

    /// Adds the set of signals to the signal mask for the calling thread.
    pub fn thread_block(&self) -> Result<()> {
        pthread_sigmask(SIG_BLOCK, Some(self), None)
    }

    /// Removes the set of signals from the signal mask for the calling thread.
    pub fn thread_unblock(&self) -> Result<()> {
        pthread_sigmask(SIG_UNBLOCK, Some(self), None)
    }

    /// Sets the set of signals as the signal mask, and returns the old mask.
    pub fn thread_swap_mask(&self, how: SigFlag) -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(how, Some(self), Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Suspends execution of the calling thread until one of the signals in the
    /// signal mask becomes pending, and returns the accepted signal.
    pub fn wait(&self) -> Result<SigNum> {
        let mut signum: SigNum = unsafe { mem::uninitialized() };
        let res = unsafe { ffi::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };

        Errno::result(res).map(|_| signum)
    }
}

impl AsRef<libc::sigset_t> for SigSet {
    fn as_ref(&self) -> &libc::sigset_t {
        &self.sigset
    }
}

#[allow(unknown_lints)]
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy, PartialEq)]
pub enum SigHandler {
    SigDfl,
    SigIgn,
    Handler(extern fn(SigNum)),
    SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
}

pub struct SigAction {
    sigaction: libc::sigaction
}

impl SigAction {
    /// This function will set or unset the flag `SA_SIGINFO` depending on the
    /// type of the `handler` argument.
    pub fn new(handler: SigHandler, flags: SaFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
        s.sa_sigaction = match handler {
            SigHandler::SigDfl => unsafe { mem::transmute(libc::SIG_DFL) },
            SigHandler::SigIgn => unsafe { mem::transmute(libc::SIG_IGN) },
            SigHandler::Handler(f) => unsafe { mem::transmute(f) },
            SigHandler::SigAction(f) => unsafe { mem::transmute(f) },
        };
        s.sa_flags = match handler {
            SigHandler::SigAction(_) => (flags | SA_SIGINFO).bits(),
            _ => (flags - SA_SIGINFO).bits(),
        };
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
    let mut oldact = mem::uninitialized::<libc::sigaction>();

    let res =
        libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);

    Errno::result(res).map(|_| SigAction { sigaction: oldact })
}

/// Manages the signal mask (set of blocked signals) for the calling thread.
///
/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
/// and no modification will take place.
///
/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
///
/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
/// and then it will be updated with `set`.
///
/// If both `set` and `oldset` is None, this function is a no-op.
///
/// For more information, visit the [pthread_sigmask](http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html),
/// or [sigprocmask](http://man7.org/linux/man-pages/man2/sigprocmask.2.html) man pages.
pub fn pthread_sigmask(how: SigFlag,
                       set: Option<&SigSet>,
                       oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }

    let res = unsafe {
        // if set or oldset is None, pass in null pointers instead
        libc::pthread_sigmask(how.bits(),
                             set.map_or_else(|| ptr::null::<libc::sigset_t>(),
                                             |s| &s.sigset as *const libc::sigset_t),
                             oldset.map_or_else(|| ptr::null_mut::<libc::sigset_t>(),
                                                |os| &mut os.sigset as *mut libc::sigset_t))
    };

    Errno::result(res).map(drop)
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
    let res = unsafe { libc::kill(pid, signum) };

    Errno::result(res).map(drop)
}

pub fn raise(signum: SigNum) -> Result<()> {
    let res = unsafe { libc::raise(signum) };

    Errno::result(res).map(drop)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_contains() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert_eq!(mask.contains(SIGUSR1), Ok(true));
        assert_eq!(mask.contains(SIGUSR2), Ok(false));

        let all = SigSet::all();
        assert_eq!(all.contains(SIGUSR1), Ok(true));
        assert_eq!(all.contains(SIGUSR2), Ok(true));
    }

    #[test]
    fn test_thread_signal_block() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert!(mask.thread_block().is_ok());
    }

    #[test]
    fn test_thread_signal_swap() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.thread_block().unwrap();

        assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());

        let mask2 = SigSet::empty();
        mask.add(SIGUSR2).unwrap();

        let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();

        assert!(oldmask.contains(SIGUSR1).unwrap());
        assert!(!oldmask.contains(SIGUSR2).unwrap());
    }

    // TODO(#251): Re-enable after figuring out flakiness.
    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    #[test]
    fn test_sigwait() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.add(SIGUSR2).unwrap();
        mask.thread_block().unwrap();

        raise(SIGUSR1).unwrap();
        assert_eq!(mask.wait().unwrap(), SIGUSR1);
    }
}
<commit_msg>Auto merge of #310 - fiveop:noffi, r=utkarshkukreti<commit_after>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc;
use {Errno, Result};
use std::mem;
use std::ptr;

pub use libc::{
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGKILL,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

pub const NSIG: libc::c_int = 32;

bitflags!{
    flags SaFlag: libc::c_int {
        const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
        const SA_NOCLDWAIT = libc::SA_NOCLDWAIT,
        const SA_NODEFER   = libc::SA_NODEFER,
        const SA_ONSTACK   = libc::SA_ONSTACK,
        const SA_RESETHAND = libc::SA_RESETHAND,
        const SA_RESTART   = libc::SA_RESTART,
        const SA_SIGINFO   = libc::SA_SIGINFO,
    }
}

bitflags!{
    flags SigFlag: libc::c_int {
        const SIG_BLOCK   = libc::SIG_BLOCK,
        const SIG_UNBLOCK = libc::SIG_UNBLOCK,
        const SIG_SETMASK = libc::SIG_SETMASK,
    }
}

#[derive(Clone, Copy)]
pub struct SigSet {
    sigset: libc::sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn all() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn empty() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn remove(&mut self, signum: SigNum) -> Result<()> {
        let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };

        Errno::result(res).map(drop)
    }

    pub fn contains(&self, signum: SigNum) -> Result<bool> {
        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };

        match try!(Errno::result(res)) {
            1 => Ok(true),
            0 => Ok(false),
            _ => unreachable!("unexpected value from sigismember"),
        }
    }

    /// Gets the currently blocked (masked) set of signals for the calling thread.
    pub fn thread_get_mask() -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(SigFlag::empty(), None, Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Sets the set of signals as the signal mask for the calling thread.
    pub fn thread_set_mask(&self) -> Result<()> {
        pthread_sigmask(SIG_SETMASK, Some(self), None)
    }

    /// Adds the set of signals to the signal mask for the calling thread.
    pub fn thread_block(&self) -> Result<()> {
        pthread_sigmask(SIG_BLOCK, Some(self), None)
    }

    /// Removes the set of signals from the signal mask for the calling thread.
    pub fn thread_unblock(&self) -> Result<()> {
        pthread_sigmask(SIG_UNBLOCK, Some(self), None)
    }

    /// Sets the set of signals as the signal mask, and returns the old mask.
    pub fn thread_swap_mask(&self, how: SigFlag) -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        try!(pthread_sigmask(how, Some(self), Some(&mut oldmask)));
        Ok(oldmask)
    }

    /// Suspends execution of the calling thread until one of the signals in the
    /// signal mask becomes pending, and returns the accepted signal.
    pub fn wait(&self) -> Result<SigNum> {
        let mut signum: SigNum = unsafe { mem::uninitialized() };
        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };

        Errno::result(res).map(|_| signum)
    }
}

impl AsRef<libc::sigset_t> for SigSet {
    fn as_ref(&self) -> &libc::sigset_t {
        &self.sigset
    }
}

#[allow(unknown_lints)]
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy, PartialEq)]
pub enum SigHandler {
    SigDfl,
    SigIgn,
    Handler(extern fn(SigNum)),
    SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
}

pub struct SigAction {
    sigaction: libc::sigaction
}

impl SigAction {
    /// This function will set or unset the flag `SA_SIGINFO` depending on the
    /// type of the `handler` argument.
    pub fn new(handler: SigHandler, flags: SaFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
        s.sa_sigaction = match handler {
            SigHandler::SigDfl => unsafe { mem::transmute(libc::SIG_DFL) },
            SigHandler::SigIgn => unsafe { mem::transmute(libc::SIG_IGN) },
            SigHandler::Handler(f) => unsafe { mem::transmute(f) },
            SigHandler::SigAction(f) => unsafe { mem::transmute(f) },
        };
        s.sa_flags = match handler {
            SigHandler::SigAction(_) => (flags | SA_SIGINFO).bits(),
            _ => (flags - SA_SIGINFO).bits(),
        };
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
    let mut oldact = mem::uninitialized::<libc::sigaction>();

    let res =
        libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);

    Errno::result(res).map(|_| SigAction { sigaction: oldact })
}

/// Manages the signal mask (set of blocked signals) for the calling thread.
///
/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
/// and no modification will take place.
///
/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
///
/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
/// and then it will be updated with `set`.
///
/// If both `set` and `oldset` is None, this function is a no-op.
///
/// For more information, visit the [pthread_sigmask](http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html),
/// or [sigprocmask](http://man7.org/linux/man-pages/man2/sigprocmask.2.html) man pages.
pub fn pthread_sigmask(how: SigFlag,
                       set: Option<&SigSet>,
                       oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }

    let res = unsafe {
        // if set or oldset is None, pass in null pointers instead
        libc::pthread_sigmask(how.bits(),
                             set.map_or_else(|| ptr::null::<libc::sigset_t>(),
                                             |s| &s.sigset as *const libc::sigset_t),
                             oldset.map_or_else(|| ptr::null_mut::<libc::sigset_t>(),
                                                |os| &mut os.sigset as *mut libc::sigset_t))
    };

    Errno::result(res).map(drop)
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
    let res = unsafe { libc::kill(pid, signum) };

    Errno::result(res).map(drop)
}

pub fn raise(signum: SigNum) -> Result<()> {
    let res = unsafe { libc::raise(signum) };

    Errno::result(res).map(drop)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_contains() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert_eq!(mask.contains(SIGUSR1), Ok(true));
        assert_eq!(mask.contains(SIGUSR2), Ok(false));

        let all = SigSet::all();
        assert_eq!(all.contains(SIGUSR1), Ok(true));
        assert_eq!(all.contains(SIGUSR2), Ok(true));
    }

    #[test]
    fn test_thread_signal_block() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();

        assert!(mask.thread_block().is_ok());
    }

    #[test]
    fn test_thread_signal_swap() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.thread_block().unwrap();

        assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());

        let mask2 = SigSet::empty();
        mask.add(SIGUSR2).unwrap();

        let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();

        assert!(oldmask.contains(SIGUSR1).unwrap());
        assert!(!oldmask.contains(SIGUSR2).unwrap());
    }

    // TODO(#251): Re-enable after figuring out flakiness.
    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    #[test]
    fn test_sigwait() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1).unwrap();
        mask.add(SIGUSR2).unwrap();
        mask.thread_block().unwrap();

        raise(SIGUSR1).unwrap();
        assert_eq!(mask.wait().unwrap(), SIGUSR1);
    }
}
<|endoftext|>


<commit_before>#![allow(unsafe_code)]

use std::convert::TryFrom;

#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::io;
#[cfg(any(target_os = "linux"))]
use {std::fs::File, std::io::Read};

/// See the Kernel's documentation for more information about this subsystem,
/// found at:  [Documentation/cgroup-v1/memory.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt)
///
/// If there's no memory limit specified on the container this may return
/// 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to 4k which is a common page size).
/// So we know we are not running in a memory restricted environment.
#[cfg(target_os = "linux")]
fn get_cgroup_memory_limit() -> io::Result<u64> {
    File::open("/sys/fs/cgroup/memory/memory.limit_in_bytes")
        .and_then(read_u64_from)
}

#[cfg(target_os = "linux")]
fn read_u64_from(mut file: File) -> io::Result<u64> {
    let mut s = String::new();
    file.read_to_string(&mut s).and_then(|_| {
        s.trim()
            .parse()
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    })
}

/// Returns the maximum size of total available memory of the process, in bytes.
/// If this limit is exceeded, the malloc() and mmap() functions shall fail with
/// errno set to [ENOMEM].
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn get_rlimit_as() -> io::Result<libc::rlimit> {
    let mut limit = std::mem::MaybeUninit::<libc::rlimit>::uninit();

    let ret = unsafe { libc::getrlimit(libc::RLIMIT_AS, limit.as_mut_ptr()) };

    if ret == 0 {
        Ok(unsafe { limit.assume_init() })
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub fn get_available_memory() -> io::Result<u64> {
    let pages = unsafe { libc::sysconf(libc::_SC_PHYS_PAGES) };
    if pages == -1 {
        return Err(io::Error::last_os_error());
    }

    let page_size = unsafe { libc::sysconf(libc::_SC_PAGE_SIZE) };
    if page_size == -1 {
        return Err(io::Error::last_os_error());
    }

    Ok(u64::try_from(pages).unwrap() * u64::try_from(page_size).unwrap())
}

pub fn get_memory_limit() -> u64 {
    // Maximum addressable memory space limit in u64
    static MAX_USIZE: u64 = usize::max_value() as u64;

    let mut max: u64 = 0;

    #[cfg(target_os = "linux")]
    {
        if let Ok(mem) = get_cgroup_memory_limit() {
            max = mem;
        }

        // If there's no memory limit specified on the container this
        // actually returns 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to
        // 4k which is a common page size). So we know we are not
        // running in a memory restricted environment.
        // src: https://github.com/dotnet/coreclr/blob/master/src/pal/src/misc/cgroup.cpp#L385-L428
        if max > 0x7FFF_FFFF_0000_0000 {
            return 0;
        }
    }

    #[cfg(any(target_os = "linux", target_os = "macos"))]
    {
        if let Ok(rlim) = get_rlimit_as() {
            let rlim_cur = Into::<u64>::into(rlim.rlim_cur);
            if rlim_cur < max || max == 0 {
                max = rlim_cur;
            }
        }

        if let Ok(available) = get_available_memory() {
            if available < max || max == 0 {
                max = available;
            }
        }
    }

    if max > MAX_USIZE {
        // It is observed in practice when the memory is unrestricted, Linux
        // control group returns a physical limit that is bigger than
        // the address space
        max = MAX_USIZE;
    }

    max
}
<commit_msg>fix windows build<commit_after>#![allow(unsafe_code)]

#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::io;
#[cfg(any(target_os = "linux"))]
use {std::fs::File, std::io::Read};

/// See the Kernel's documentation for more information about this subsystem,
/// found at:  [Documentation/cgroup-v1/memory.txt](https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt)
///
/// If there's no memory limit specified on the container this may return
/// 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to 4k which is a common page size).
/// So we know we are not running in a memory restricted environment.
#[cfg(target_os = "linux")]
fn get_cgroup_memory_limit() -> io::Result<u64> {
    File::open("/sys/fs/cgroup/memory/memory.limit_in_bytes")
        .and_then(read_u64_from)
}

#[cfg(target_os = "linux")]
fn read_u64_from(mut file: File) -> io::Result<u64> {
    let mut s = String::new();
    file.read_to_string(&mut s).and_then(|_| {
        s.trim()
            .parse()
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    })
}

/// Returns the maximum size of total available memory of the process, in bytes.
/// If this limit is exceeded, the malloc() and mmap() functions shall fail with
/// errno set to [ENOMEM].
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn get_rlimit_as() -> io::Result<libc::rlimit> {
    let mut limit = std::mem::MaybeUninit::<libc::rlimit>::uninit();

    let ret = unsafe { libc::getrlimit(libc::RLIMIT_AS, limit.as_mut_ptr()) };

    if ret == 0 {
        Ok(unsafe { limit.assume_init() })
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub fn get_available_memory() -> io::Result<u64> {
    use std::convert::TryFrom;

    let pages = unsafe { libc::sysconf(libc::_SC_PHYS_PAGES) };
    if pages == -1 {
        return Err(io::Error::last_os_error());
    }

    let page_size = unsafe { libc::sysconf(libc::_SC_PAGE_SIZE) };
    if page_size == -1 {
        return Err(io::Error::last_os_error());
    }

    Ok(u64::try_from(pages).unwrap() * u64::try_from(page_size).unwrap())
}

pub fn get_memory_limit() -> u64 {
    // Maximum addressable memory space limit in u64
    static MAX_USIZE: u64 = usize::max_value() as u64;

    let mut max: u64 = 0;

    #[cfg(target_os = "linux")]
    {
        if let Ok(mem) = get_cgroup_memory_limit() {
            max = mem;
        }

        // If there's no memory limit specified on the container this
        // actually returns 0x7FFFFFFFFFFFF000 (2^63-1 rounded down to
        // 4k which is a common page size). So we know we are not
        // running in a memory restricted environment.
        // src: https://github.com/dotnet/coreclr/blob/master/src/pal/src/misc/cgroup.cpp#L385-L428
        if max > 0x7FFF_FFFF_0000_0000 {
            return 0;
        }
    }

    #[cfg(any(target_os = "linux", target_os = "macos"))]
    {
        if let Ok(rlim) = get_rlimit_as() {
            let rlim_cur = Into::<u64>::into(rlim.rlim_cur);
            if rlim_cur < max || max == 0 {
                max = rlim_cur;
            }
        }

        if let Ok(available) = get_available_memory() {
            if available < max || max == 0 {
                max = available;
            }
        }
    }

    if max > MAX_USIZE {
        // It is observed in practice when the memory is unrestricted, Linux
        // control group returns a physical limit that is bigger than
        // the address space
        max = MAX_USIZE;
    }

    max
}
<|endoftext|>


<commit_before>
extern crate rs6502;

#[test]
fn INTEGRATION_CPU_can_add_basic_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #$10    ; A register should equal 48
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x30, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_binary_coded_decimal_numbers_in_accumulator() {
    let asm = "
        SED
        LDA #$20
        ADC #$05    ; A register should equal 0x25
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(3);

    assert_eq!(0x25, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_mixed_mode_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #10    ; A register should equal 0x2A
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x2A, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_store_bytes_in_memory() {
    let asm = "
        LDA #$20
        STA $2000
        LDA #10
        STA $2001
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x20, cpu.memory[0x2000]);
    assert_eq!(0x0A, cpu.memory[0x2001]);
    assert_eq!(0x00, cpu.memory[0x2002]);
}

#[test]
fn INTEGRATION_CPU_can_overwrite_own_memory() {
    let asm = "
        LDA #$20
        STA $C006
        LDA #10
        STA $2000
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x20, cpu.memory[0x2000]);
}

#[test]
fn INTEGRATION_CPU_can_load_byte_into_memory_and_logical_AND_it_with_A_register() {
    let asm = "
        LDA #$0F
        STA $2000   ; Load the mask 0x0F into $2000
        LDA #$FF    ; Load 0xFF into A
        AND $2000   ; AND it with 0x0F
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x0F, cpu.memory[0x2000]);
}<commit_msg>Add more Integration tests<commit_after>
extern crate rs6502;

#[test]
fn INTEGRATION_CPU_can_add_basic_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #$10    ; A register should equal 48
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x30, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_binary_coded_decimal_numbers_in_accumulator() {
    let asm = "
        SED
        LDA #$20
        ADC #$05    ; A register should equal 0x25
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(3);

    assert_eq!(0x25, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_mixed_mode_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #10    ; A register should equal 0x2A
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x2A, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_store_bytes_in_memory() {
    let asm = "
        LDA #$20
        STA $2000
        LDA #10
        STA $2001
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x20, cpu.memory[0x2000]);
    assert_eq!(0x0A, cpu.memory[0x2001]);
    assert_eq!(0x00, cpu.memory[0x2002]);
}

#[test]
fn INTEGRATION_CPU_can_overwrite_own_memory() {
    let asm = "
        LDA #$20
        STA $C006
        LDA #10
        STA $2000
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x20, cpu.memory[0x2000]);
}

#[test]
fn INTEGRATION_CPU_can_load_byte_into_memory_and_logical_AND_it_with_A_register() {
    let asm = "
        LDA #$0F
        STA $2000   ; Load the mask 0x0F into $2000
        LDA #$FF    ; Load 0xFF into A
        AND $2000   ; AND it with 0x0F
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x0F, cpu.memory[0x2000]);
}

#[test]
fn INTEGRATION_CPU_can_load_byte_into_memory_and_logical_AND_it_with_A_register_using_a_variable
    () {
    let asm = "
        MEMORY_LOCATION = $2000

        LDA #$0F
        STA MEMORY_LOCATION     ; Load the mask 0x0F into $2000
        LDA #$FF                ; Load 0xFF into A
        AND MEMORY_LOCATION     ; AND it with 0x0F
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x0F, cpu.memory[0x2000]);
}<|endoftext|>


<commit_before>use std::collections::VecDeque;

#[macro_use]
extern crate sliding_window;
use sliding_window::SliceRing;
use sliding_window::OptimizedSliceRing;

#[test]
fn test_deque_slice_ring() {
    test_slice_ring!(VecDeque::<i32>::new());
}

#[test]
fn test_optimized_slice_ring() {
    test_slice_ring!(OptimizedSliceRing::<i32>::new());
}
// #[test]
// fn test_window_1_step_1() {
//     let mut sliding_window: SlidingWindow<i32> = SlidingWindow::new(1, 1);
//     assert!(!sliding_window.can_fill());
//     let samples: Vec<i32> = vec![];
//     sliding_window.write(&samples[..]);
//     assert!(!sliding_window.can_fill());
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//
//     let mut window: Vec<i32> = vec![0];
//     assert!(!sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![0]);
//
//     let samples: Vec<i32> = vec![1];
//     sliding_window.write(&samples[..]);
//     assert_eq!(sliding_window.ringbuffer.len(), 1);
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![1]);
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//
//     let samples: Vec<i32> = vec![1, 2, 3];
//     sliding_window.write(&samples[..]);
//     assert_eq!(sliding_window.ringbuffer.len(), 3);
//
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![1]);
//     assert_eq!(sliding_window.ringbuffer.len(), 2);
//
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![2]);
//     assert_eq!(sliding_window.ringbuffer.len(), 1);
//
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![3]);
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//     assert!(!sliding_window.can_fill());
// }
//
// #[test]
// fn test_window_4_step_2() {
//     // 50% overlap
//
//     let mut sliding_window: SlidingWindow<i32> = SlidingWindow::new(4, 2);
//     assert!(!sliding_window.can_fill());
//     let samples: Vec<i32> = vec![];
//     sliding_window.write(&samples[..]);
//     assert!(!sliding_window.can_fill());
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//
//     let mut window: Vec<i32> = vec![0];
//     assert!(!sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![0]);
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0, 0, 0, 0];
//         let samples: Vec<i32> = vec![1, 2, 3];
//         // println!("samples {:?}", samples);
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             calls += 1;
//         });
//         assert_eq!(calls, 0);
//         assert_eq!(window, vec![0, 0, 0, 0]);
//         assert_eq!(ring.len(), 3);
//     }
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0, 0, 0, 0];
//         let samples: Vec<i32> = vec![1, 2, 3, 4];
//         // println!("samples {:?}", samples);
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             assert_eq!(ring.len(), 2);
//             assert_eq!(window, vec![1, 2, 3, 4]);
//             calls += 1;
//         });
//         assert_eq!(calls, 1);
//         assert_eq!(window, vec![1, 2, 3, 4]);
//         assert_eq!(ring.len(), 2);
//     }
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0, 0, 0, 0];
//         let samples: Vec<i32> = vec![1, 2, 3 ,4, 5, 6, 7, 8, 9, 10, 11];
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             match calls {
//                 0 => { assert_eq!(window, vec![1, 2, 3, 4]) },
//                 1 => { assert_eq!(window, vec![3, 4, 5, 6]) },
//                 2 => { assert_eq!(window, vec![5, 6, 7, 8]) },
//                 3 => { assert_eq!(window, vec![7, 8, 9, 10]) },
//                 _ => { assert!(false) },
//             }
//             calls += 1;
//         });
//         assert_eq!(calls, 4);
//         assert_eq!(window, vec![7, 8, 9, 10]);
//         assert_eq!(ring.len(), 3);
//
//         let samples: Vec<i32> = vec![12, 13, 14, 15, 16];
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             match calls {
//                 0 => { assert_eq!(window, vec![9, 10, 11, 12]) },
//                 1 => { assert_eq!(window, vec![11, 12, 13, 14]) },
//                 2 => { assert_eq!(window, vec![13, 14, 15, 16]) },
//                 _ => { assert!(false) },
//             }
//             calls += 1;
//         });
//         assert_eq!(calls, 3);
//         assert_eq!(window, vec![13, 14, 15, 16]);
//         assert_eq!(ring.len(), 2);
//     }
// }
//
// #[test]
// fn test_window_1024_step_512() {
//     // 50% overlap
//     use std::collections::VecDeque;
//     use std::iter;
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0; 1024];
//         let samples: Vec<i32> =
//             iter::repeat(1).take(1024)
//             .chain(iter::repeat(2).take(1024))
//             .chain(iter::repeat(3).take(1024))
//             .chain(iter::repeat(4).take(1024))
//             .collect();
//         assert_eq!(samples.len(), 1024 * 4);
//         let mut calls = 0;
//         window!(512, ring, &samples[..], &mut window[..], {
//             match calls {
//                 0 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(1).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 1 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(1).take(512)
//                         .chain(iter::repeat(2).take(512))
//                         .collect::<Vec<i32>>()
//                     );
//                 },
//                 2 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(2).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 3 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(2).take(512)
//                         .chain(iter::repeat(3).take(512))
//                         .collect::<Vec<i32>>()
//                     );
//                 },
//                 4 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(3).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 5 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(3).take(512)
//                         .chain(iter::repeat(4).take(512))
//                         .collect::<Vec<i32>>()
//                     );
//                 },
//                 6 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(4).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 _ => {}
//             }
//             calls += 1;
//         });
//         assert_eq!(calls, 7);
//         assert_eq!(ring.len(), 512);
//     }
// }

// 4048 and 512
<commit_msg>improve test naming<commit_after>use std::collections::VecDeque;

#[macro_use]
extern crate sliding_window;
use sliding_window::SliceRing;
use sliding_window::OptimizedSliceRing;

#[test]
fn test_slice_ring_unoptimized() {
    test_slice_ring!(VecDeque::<i32>::new());
}

#[test]
fn test_slice_ring_optimized() {
    test_slice_ring!(OptimizedSliceRing::<i32>::new());
}
// #[test]
// fn test_window_1_step_1() {
//     let mut sliding_window: SlidingWindow<i32> = SlidingWindow::new(1, 1);
//     assert!(!sliding_window.can_fill());
//     let samples: Vec<i32> = vec![];
//     sliding_window.write(&samples[..]);
//     assert!(!sliding_window.can_fill());
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//
//     let mut window: Vec<i32> = vec![0];
//     assert!(!sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![0]);
//
//     let samples: Vec<i32> = vec![1];
//     sliding_window.write(&samples[..]);
//     assert_eq!(sliding_window.ringbuffer.len(), 1);
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![1]);
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//
//     let samples: Vec<i32> = vec![1, 2, 3];
//     sliding_window.write(&samples[..]);
//     assert_eq!(sliding_window.ringbuffer.len(), 3);
//
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![1]);
//     assert_eq!(sliding_window.ringbuffer.len(), 2);
//
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![2]);
//     assert_eq!(sliding_window.ringbuffer.len(), 1);
//
//     assert!(sliding_window.can_fill());
//     assert!(sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![3]);
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//     assert!(!sliding_window.can_fill());
// }
//
// #[test]
// fn test_window_4_step_2() {
//     // 50% overlap
//
//     let mut sliding_window: SlidingWindow<i32> = SlidingWindow::new(4, 2);
//     assert!(!sliding_window.can_fill());
//     let samples: Vec<i32> = vec![];
//     sliding_window.write(&samples[..]);
//     assert!(!sliding_window.can_fill());
//     assert_eq!(sliding_window.ringbuffer.len(), 0);
//
//     let mut window: Vec<i32> = vec![0];
//     assert!(!sliding_window.read(&mut window[..]));
//     assert_eq!(window, vec![0]);
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0, 0, 0, 0];
//         let samples: Vec<i32> = vec![1, 2, 3];
//         // println!("samples {:?}", samples);
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             calls += 1;
//         });
//         assert_eq!(calls, 0);
//         assert_eq!(window, vec![0, 0, 0, 0]);
//         assert_eq!(ring.len(), 3);
//     }
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0, 0, 0, 0];
//         let samples: Vec<i32> = vec![1, 2, 3, 4];
//         // println!("samples {:?}", samples);
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             assert_eq!(ring.len(), 2);
//             assert_eq!(window, vec![1, 2, 3, 4]);
//             calls += 1;
//         });
//         assert_eq!(calls, 1);
//         assert_eq!(window, vec![1, 2, 3, 4]);
//         assert_eq!(ring.len(), 2);
//     }
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0, 0, 0, 0];
//         let samples: Vec<i32> = vec![1, 2, 3 ,4, 5, 6, 7, 8, 9, 10, 11];
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             match calls {
//                 0 => { assert_eq!(window, vec![1, 2, 3, 4]) },
//                 1 => { assert_eq!(window, vec![3, 4, 5, 6]) },
//                 2 => { assert_eq!(window, vec![5, 6, 7, 8]) },
//                 3 => { assert_eq!(window, vec![7, 8, 9, 10]) },
//                 _ => { assert!(false) },
//             }
//             calls += 1;
//         });
//         assert_eq!(calls, 4);
//         assert_eq!(window, vec![7, 8, 9, 10]);
//         assert_eq!(ring.len(), 3);
//
//         let samples: Vec<i32> = vec![12, 13, 14, 15, 16];
//         let mut calls = 0;
//         window!(2, ring, &samples[..], &mut window[..], {
//             match calls {
//                 0 => { assert_eq!(window, vec![9, 10, 11, 12]) },
//                 1 => { assert_eq!(window, vec![11, 12, 13, 14]) },
//                 2 => { assert_eq!(window, vec![13, 14, 15, 16]) },
//                 _ => { assert!(false) },
//             }
//             calls += 1;
//         });
//         assert_eq!(calls, 3);
//         assert_eq!(window, vec![13, 14, 15, 16]);
//         assert_eq!(ring.len(), 2);
//     }
// }
//
// #[test]
// fn test_window_1024_step_512() {
//     // 50% overlap
//     use std::collections::VecDeque;
//     use std::iter;
//
//     {
//         let mut ring: VecDeque<i32> = VecDeque::new();
//         let mut window: Vec<i32> = vec![0; 1024];
//         let samples: Vec<i32> =
//             iter::repeat(1).take(1024)
//             .chain(iter::repeat(2).take(1024))
//             .chain(iter::repeat(3).take(1024))
//             .chain(iter::repeat(4).take(1024))
//             .collect();
//         assert_eq!(samples.len(), 1024 * 4);
//         let mut calls = 0;
//         window!(512, ring, &samples[..], &mut window[..], {
//             match calls {
//                 0 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(1).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 1 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(1).take(512)
//                         .chain(iter::repeat(2).take(512))
//                         .collect::<Vec<i32>>()
//                     );
//                 },
//                 2 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(2).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 3 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(2).take(512)
//                         .chain(iter::repeat(3).take(512))
//                         .collect::<Vec<i32>>()
//                     );
//                 },
//                 4 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(3).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 5 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(3).take(512)
//                         .chain(iter::repeat(4).take(512))
//                         .collect::<Vec<i32>>()
//                     );
//                 },
//                 6 => {
//                     assert_eq!(
//                         window,
//                         iter::repeat(4).take(1024).collect::<Vec<i32>>()
//                     );
//                 },
//                 _ => {}
//             }
//             calls += 1;
//         });
//         assert_eq!(calls, 7);
//         assert_eq!(ring.len(), 512);
//     }
// }

// 4048 and 512
<|endoftext|>


<commit_before>// TODO: COPYRIGHT, USE & AUTHORS
// TODO: RUST DOCS!

extern crate rust_monster;
#[macro_use]
extern crate log;
extern crate env_logger;
#[cfg(test)]
mod tests
{
    use rust_monster::ga::ga_core::{GeneticAlgorithm, GASolution, GAFactory, DEBUG_FLAG};
    use rust_monster::ga::ga_population::{GAPopulation, GAPopulationSortOrder, GAPopulationSortBasis};
    use rust_monster::ga::ga_simple::{SimpleGeneticAlgorithm, SimpleGeneticAlgorithmCfg};
    use rust_monster::ga::ga_selectors::{GASelector, GARankSelector, GAUniformSelector, GARawScoreBasedSelection, GAScaledScoreBasedSelection};

    use env_logger;
    use std::sync::{Once, ONCE_INIT};

    static INIT: Once = ONCE_INIT;
    const VAL: f32 = 3.14159;

    struct TestSolution
    {
        fitness: f32
    }
    impl GASolution for TestSolution
    {
        fn new() -> TestSolution
        {
            TestSolution{ fitness: VAL }
        }

        fn clone(&self) -> Self { TestSolution::new() }
        fn evaluate(&mut self) -> f32 { self.fitness }
    #[allow(unused_variables)]
        fn crossover(&self, other : &Self) -> Self { TestSolution::new() }
    #[allow(unused_variables)]
        fn mutate(&mut self, pm : f32) {}
        fn fitness(&self) -> f32 { (1.0 / self.fitness) }
        fn score(&self) -> f32 { self.fitness }
    }

    #[allow(dead_code)]
    struct TestFactory
    {
        starting_fitness: f32
    }
    impl GAFactory<TestSolution> for TestFactory
    {
        fn initial_population(&mut self) -> GAPopulation<TestSolution> {
            GAPopulation::new(vec![TestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
        }
    }

////////////////////////////////////////
// Utility functions

    fn ga_test_setup()
    {
        // This is only called once, works nicely as a Setup mechanism
        // TODO: Can we do somethign similar for teardown?
        INIT.call_once(||{
            env_logger::init().unwrap();
        });
    }

    fn simple_ga_validation(sga:&mut SimpleGeneticAlgorithm<TestSolution>)
    {
        sga.initialize();
        assert_eq!(sga.step(), 1);
        assert_eq!(sga.done(), false);
        assert_eq!(sga.population().size(), 1);
        assert_eq!(sga.population().best().score(), VAL);
    }

////////////////////////////////////////
// Tests

    #[test]
    fn init_test_with_initial_population()
    {
        ga_test_setup();
        let initial_population = GAPopulation::new(vec![TestSolution { fitness: VAL}], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(initial_population)
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    fn init_test_with_factory()
    {
        ga_test_setup();
        let mut factory = TestFactory { starting_fitness: VAL };
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 Some(&mut factory as &mut GAFactory<TestSolution>),
                                                 None
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn init_test_missing_args()
    {
        ga_test_setup();
        let ga : SimpleGeneticAlgorithm<TestSolution> =
                 SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                               d_seed : 1,
                                               flags : DEBUG_FLAG,
                                               max_generations: 100,
                                               ..Default::default()
                                             },
                                             None,
                                             None
                                             );
        // Not reached
    }

    #[test]
    #[should_panic]
    fn init_test_empty_initial_pop()
    {
        ga_test_setup();
        let empty_initial_population : GAPopulation<TestSolution> = GAPopulation::new(vec![], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(empty_initial_population)
                                                 );
        ga.initialize()
        //Not reached
    }

    // This test should live in the ga_population file directly,
    // but since it requires GASolution objects it is here for now.
    // Maybe we could use a Mocking library.
    // TODO: This doesn't go here.
    #[test]
    fn test_sort_population()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![TestSolution { fitness: f }, TestSolution { fitness: f_m }], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //TestSolution's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Scaled).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Scaled).fitness(), i_f);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_rank_selector()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;
            let mut raw_rank_selector = GARankSelector::new(&mut population, &raw_score_selection);

            // Best Raw score is that of 1st solution.
            assert_eq!(raw_rank_selector.select().score(), f);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;
            let mut scaled_rank_selector = GARankSelector::new(&mut population, &scaled_score_selection);

            // Best Scaled score is that of 2nd solution (because fitness is inverse of score). Weird. In this case, LowIsBest.
            assert_eq!(scaled_rank_selector.select().fitness(), i_f_m);
        }
    }

    #[test]
    fn test_uniform_selector()
    {
        let f = VAL;
        let f_m = VAL - 1.0;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        let mut uniform_selector = GAUniformSelector::new(&mut population);

        let selected_individual = uniform_selector.select();
        assert!(selected_individual.score() == f || selected_individual.score() == f_m);
    }
}
<commit_msg>Exercise GARouletteWheelSelector and GATournamentSelector.<commit_after>// TODO: COPYRIGHT, USE & AUTHORS
// TODO: RUST DOCS!

extern crate rust_monster;
#[macro_use]
extern crate log;
extern crate env_logger;
#[cfg(test)]
mod tests
{
    use rust_monster::ga::ga_core::{GeneticAlgorithm, GASolution, GAFactory, DEBUG_FLAG};
    use rust_monster::ga::ga_population::{GAPopulation, GAPopulationSortOrder, GAPopulationSortBasis};
    use rust_monster::ga::ga_simple::{SimpleGeneticAlgorithm, SimpleGeneticAlgorithmCfg};
    use rust_monster::ga::ga_selectors::{GASelector, GARankSelector, GAUniformSelector, GARouletteWheelSelector, GATournamentSelector, GARawScoreBasedSelection, GAScaledScoreBasedSelection};
    use rust_monster::ga::ga_random;

    use env_logger;
    use std::sync::{Once, ONCE_INIT};

    static INIT: Once = ONCE_INIT;
    const VAL: f32 = 3.14159;

    struct TestSolution
    {
        fitness: f32
    }
    impl GASolution for TestSolution
    {
        fn new() -> TestSolution
        {
            TestSolution{ fitness: VAL }
        }

        fn clone(&self) -> Self { TestSolution::new() }
        fn evaluate(&mut self) -> f32 { self.fitness }
    #[allow(unused_variables)]
        fn crossover(&self, other : &Self) -> Self { TestSolution::new() }
    #[allow(unused_variables)]
        fn mutate(&mut self, pm : f32) {}
        fn fitness(&self) -> f32 { (1.0 / self.fitness) }
        fn score(&self) -> f32 { self.fitness }
    }

    #[allow(dead_code)]
    struct TestFactory
    {
        starting_fitness: f32
    }
    impl GAFactory<TestSolution> for TestFactory
    {
        fn initial_population(&mut self) -> GAPopulation<TestSolution> {
            GAPopulation::new(vec![TestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
        }
    }

////////////////////////////////////////
// Utility functions

    fn ga_test_setup()
    {
        // This is only called once, works nicely as a Setup mechanism
        // TODO: Can we do somethign similar for teardown?
        INIT.call_once(||{
            env_logger::init().unwrap();
        });
    }

    fn simple_ga_validation(sga:&mut SimpleGeneticAlgorithm<TestSolution>)
    {
        sga.initialize();
        assert_eq!(sga.step(), 1);
        assert_eq!(sga.done(), false);
        assert_eq!(sga.population().size(), 1);
        assert_eq!(sga.population().best().score(), VAL);
    }

////////////////////////////////////////
// Tests

    #[test]
    fn init_test_with_initial_population()
    {
        ga_test_setup();
        let initial_population = GAPopulation::new(vec![TestSolution { fitness: VAL}], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(initial_population)
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    fn init_test_with_factory()
    {
        ga_test_setup();
        let mut factory = TestFactory { starting_fitness: VAL };
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 Some(&mut factory as &mut GAFactory<TestSolution>),
                                                 None
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn init_test_missing_args()
    {
        ga_test_setup();
        let ga : SimpleGeneticAlgorithm<TestSolution> =
                 SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                               d_seed : 1,
                                               flags : DEBUG_FLAG,
                                               max_generations: 100,
                                               ..Default::default()
                                             },
                                             None,
                                             None
                                             );
        // Not reached
    }

    #[test]
    #[should_panic]
    fn init_test_empty_initial_pop()
    {
        ga_test_setup();
        let empty_initial_population : GAPopulation<TestSolution> = GAPopulation::new(vec![], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(empty_initial_population)
                                                 );
        ga.initialize()
        //Not reached
    }

    // This test should live in the ga_population file directly,
    // but since it requires GASolution objects it is here for now.
    // Maybe we could use a Mocking library.
    // TODO: This doesn't go here.
    #[test]
    fn test_sort_population()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![TestSolution { fitness: f }, TestSolution { fitness: f_m }], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //TestSolution's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Scaled).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Scaled).fitness(), i_f);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_rank_selector()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;
            let mut raw_rank_selector = GARankSelector::new(&mut population, &raw_score_selection);

            raw_rank_selector.update();

            // Best Raw score is that of 1st solution.
            assert_eq!(raw_rank_selector.select().score(), f);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;
            let mut scaled_rank_selector = GARankSelector::new(&mut population, &scaled_score_selection);

            scaled_rank_selector.update();

            // Best Scaled score is that of 2nd solution (because fitness is inverse of score). Weird. In this case, LowIsBest.
            assert_eq!(scaled_rank_selector.select().fitness(), i_f_m);
        }
    }

    #[test]
    fn test_uniform_selector()
    {
        let f = VAL;
        let f_m = VAL - 1.0;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        let mut uniform_selector = GAUniformSelector::new(&mut population);

        uniform_selector.update();

        let selected_individual = uniform_selector.select();
        assert!(selected_individual.score() == f || selected_individual.score() == f_m);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_roulette_wheel_selector()
    {
        // Just exercise the code.
        // TODO: How to test when there is randomness?

        let mut individuals = vec![];

        for i in 1 .. 20
        {
            individuals.push(TestSolution { fitness: ga_random::ga_random_float() });
        }

        let mut population
          = GAPopulation::new(individuals, GAPopulationSortOrder::LowIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;

            let mut raw_roulette_wheel_selector
              = GARouletteWheelSelector::new(&mut population, &raw_score_selection);

            raw_roulette_wheel_selector.update();

            raw_roulette_wheel_selector.select();
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;

            let mut scaled_roulette_wheel_selector
              = GARouletteWheelSelector::new(&mut population, &scaled_score_selection);

            scaled_roulette_wheel_selector.update();

            scaled_roulette_wheel_selector.select();
        }
    }

    #[test]
    #[allow(unused_variables)]
    fn test_tournament_selector()
    {
        // Just exercise the code.
        // TODO: How to test when there is randomness?

        let mut individuals = vec![];

        for i in 1 .. 20
        {
            individuals.push(TestSolution { fitness: ga_random::ga_random_float() });
        }

        let mut population
          = GAPopulation::new(individuals, GAPopulationSortOrder::LowIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;

            let mut raw_tournament_selector
              = GARouletteWheelSelector::new(&mut population, &raw_score_selection);

            raw_tournament_selector.update();

            raw_tournament_selector.select();
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;

            let mut scaled_tournament_selector
              = GARouletteWheelSelector::new(&mut population, &scaled_score_selection);

            scaled_tournament_selector.update();

            scaled_tournament_selector.select();
        }
    }

}
<|endoftext|>


<commit_before>#![recursion_limit = "128"]
#![no_std]
#[macro_use]
extern crate generic_array;
use core::cell::Cell;
use core::ops::{Add, Drop};
use generic_array::functional::*;
use generic_array::sequence::*;
use generic_array::typenum::{U3, U4, U97};
use generic_array::GenericArray;

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l: GenericArray<i32, U97> = GenericArray::clone_from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

#[test]
fn test_drop() {
    #[derive(Clone)]
    struct TestDrop<'a>(&'a Cell<u32>);

    impl<'a> Drop for TestDrop<'a> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    let drop_counter = Cell::new(0);
    {
        let _: GenericArray<TestDrop, U3> = arr![TestDrop; TestDrop(&drop_counter),
                           TestDrop(&drop_counter),
                           TestDrop(&drop_counter)];
    }
    assert_eq!(drop_counter.get(), 3);
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_copy() {
    let test = arr![u32; 1, 2, 3];
    let test2 = test;
    // if GenericArray is not copy, this should fail as a use of a moved value
    assert_eq!(test[1], 2);
    assert_eq!(test2[0], 1);
}

#[derive(Debug, PartialEq, Eq)]
struct NoClone<T>(T);

#[test]
fn test_from_slice() {
    let arr = [1, 2, 3, 4];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
    let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
}

#[test]
fn test_from_mut_slice() {
    let mut arr = [1, 2, 3, 4];
    {
        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = 10;
    }
    assert_eq!(arr, [1, 2, 10, 4]);
    let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    {
        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = NoClone(10);
    }
    assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]);
}

#[test]
fn test_default() {
    let arr = GenericArray::<u8, U4>::default();
    assert_eq!(arr.as_slice(), &[0, 0, 0, 0]);
}

#[test]
fn test_from() {
    let data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)];
    let garray: GenericArray<(usize, usize, usize), U3> = data.into();
    assert_eq!(&data, garray.as_slice());
}

#[test]
fn test_unit_macro() {
    let arr = arr![f32; 3.14];
    assert_eq!(arr[0], 3.14);
}

#[test]
fn test_empty_macro() {
    let _arr = arr![f32;];
}

#[test]
fn test_cmp() {
    arr![u8; 0x00].cmp(&arr![u8; 0x00]);
}

/// This test should cause a helpful compile error if uncommented.
// #[test]
// fn test_empty_macro2(){
//     let arr = arr![];
// }
#[cfg(feature = "serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::typenum::U6;
    use generic_array::GenericArray;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}

#[test]
fn test_map() {
    let b: GenericArray<i32, U4> = GenericArray::generate(|i| i as i32 * 4).map(|x| x - 3);

    assert_eq!(b, arr![i32; -3, 1, 5, 9]);
}

#[test]
fn test_zip() {
    let a: GenericArray<_, U4> = GenericArray::generate(|i| i + 1);
    let b: GenericArray<_, U4> = GenericArray::generate(|i| i as i32 * 4);

    // Uses reference and non-reference arguments
    let c = (&a).zip(b, |r, l| *r as i32 + l);

    assert_eq!(c, arr![i32; 1, 6, 11, 16]);
}

#[test]
#[should_panic]
fn test_from_iter_short() {
    use core::iter::repeat;

    let a: GenericArray<_, U4> = repeat(11).take(3).collect();

    assert_eq!(a, arr![i32; 11, 11, 11, 0]);
}

#[test]
fn test_from_iter() {
    use core::iter::{once, repeat};

    let a: GenericArray<_, U4> = repeat(11).take(3).chain(once(0)).collect();

    assert_eq!(a, arr![i32; 11, 11, 11, 0]);
}

#[test]
fn test_sizes() {
    #![allow(dead_code)]
    use core::ffi::c_void;
    use core::mem::{size_of, size_of_val};

    #[derive(Debug, Copy, Clone)]
    enum E {
        V,
        V2(i32),
        V3 { h: bool, i: i32 },
    }

    #[derive(Debug, Copy, Clone)]
    #[repr(C)]
    #[repr(packed)]
    struct Test {
        t: u16,
        s: u32,
        mm: bool,
        r: u16,
        f: u16,
        p: (),
        o: u32,
        ff: *const extern "C" fn(*const char) -> *const c_void,
        l: *const c_void,
        w: bool,
        q: bool,
        v: E,
    }

    assert_eq!(size_of::<E>(), 8);

    assert_eq!(size_of::<Test>(), 25 + size_of::<usize>() * 2);

    assert_eq!(size_of_val(&arr![u8; 1, 2, 3]), size_of::<u8>() * 3);
    assert_eq!(size_of_val(&arr![u32; 1]), size_of::<u32>() * 1);
    assert_eq!(size_of_val(&arr![u64; 1, 2, 3, 4]), size_of::<u64>() * 4);

    assert_eq!(size_of::<GenericArray<Test, U97>>(), size_of::<Test>() * 97);
}

#[test]
fn test_append() {
    let a = arr![i32; 1, 2, 3];

    let b = a.append(4);

    assert_eq!(b, arr![i32; 1, 2, 3, 4]);
}

#[test]
fn test_prepend() {
    let a = arr![i32; 1, 2, 3];

    let b = a.prepend(4);

    assert_eq!(b, arr![i32; 4, 1, 2, 3]);
}

#[test]
fn test_pop() {
    let a = arr![i32; 1, 2, 3, 4];

    let (init, last) = a.pop_back();

    assert_eq!(init, arr![i32; 1, 2, 3]);
    assert_eq!(last, 4);

    let (head, tail) = a.pop_front();

    assert_eq!(head, 1);
    assert_eq!(tail, arr![i32; 2, 3, 4]);
}

#[test]
fn test_split() {
    let a = arr![i32; 1, 2, 3, 4];

    let (b, c) = a.split();

    assert_eq!(b, arr![i32; 1]);
    assert_eq!(c, arr![i32; 2, 3, 4]);

    let (e, f) = a.split();

    assert_eq!(e, arr![i32; 1, 2]);
    assert_eq!(f, arr![i32; 3, 4]);
}

#[test]
fn test_split_ref() {
    let a = arr![i32; 1, 2, 3, 4];
    let a_ref = &a;

    let (b_ref, c_ref) = a_ref.split();

    assert_eq!(b_ref, &arr![i32; 1]);
    assert_eq!(c_ref, &arr![i32; 2, 3, 4]);

    let (e_ref, f_ref) = a_ref.split();

    assert_eq!(e_ref, &arr![i32; 1, 2]);
    assert_eq!(f_ref, &arr![i32; 3, 4]);
}

#[test]
fn test_split_mut() {
    let mut a = arr![i32; 1, 2, 3, 4];
    let a_ref = &mut a;

    let (b_ref, c_ref) = a_ref.split();

    assert_eq!(b_ref, &mut arr![i32; 1]);
    assert_eq!(c_ref, &mut arr![i32; 2, 3, 4]);

    let (e_ref, f_ref) = a_ref.split();

    assert_eq!(e_ref, &mut arr![i32; 1, 2]);
    assert_eq!(f_ref, &mut arr![i32; 3, 4]);
}

#[test]
fn test_concat() {
    let a = arr![i32; 1, 2];
    let b = arr![i32; 3, 4, 5];

    let c = a.concat(b);

    assert_eq!(c, arr![i32; 1, 2, 3, 4, 5]);

    let (d, e) = c.split();

    assert_eq!(d, arr![i32; 1, 2]);
    assert_eq!(e, arr![i32; 3, 4, 5]);
}

#[test]
fn test_fold() {
    let a = arr![i32; 1, 2, 3, 4];

    assert_eq!(10, a.fold(0, |a, x| a + x));
}

fn sum_generic<S>(s: S) -> i32
where
    S: FunctionalSequence<i32>,
    S::Item: Add<i32, Output = i32>, // `+`
    i32: Add<S::Item, Output = i32>, // reflexive
{
    s.fold(0, |a, x| a + x)
}

#[test]
fn test_sum() {
    let a = sum_generic(arr![i32; 1, 2, 3, 4]);

    assert_eq!(a, 10);
}

#[test]
fn test_as_ref() {
    let a = arr![i32; 1, 2, 3, 4];
    let a_ref: &[i32; 4] = a.as_ref();
    assert_eq!(a_ref, &[1, 2, 3, 4]);
}

#[test]
fn test_as_mut() {
    let mut a = arr![i32; 1, 2, 3, 4];
    let a_mut: &mut [i32; 4] = a.as_mut();
    assert_eq!(a_mut, &mut [1, 2, 3, 4]);
    a_mut[2] = 0;
    assert_eq!(a_mut, &mut [1, 2, 0, 4]);
    assert_eq!(a, arr![i32; 1, 2, 0, 4]);
}

#[test]
fn test_from_array_ref() {
    let mut a = arr![i32; 1, 2, 3, 4];
    let a_ref: &[i32; 4] = a.as_ref();
    let a_from: &GenericArray<i32, U4> = a_ref.into();
    assert_eq!(&a, a_from);
}

#[test]
fn test_from_array_mut() {
    let mut a = arr![i32; 1, 2, 3, 4];
    let mut a_copy = a;
    let a_mut: &mut [i32; 4] = a.as_mut();
    let a_from: &mut GenericArray<i32, U4> = a_mut.into();
    assert_eq!(&mut a_copy, a_from);
}
<commit_msg>Add tests for alignment<commit_after>#![recursion_limit = "128"]
#![no_std]
#[macro_use]
extern crate generic_array;
use core::cell::Cell;
use core::ops::{Add, Drop};
use generic_array::functional::*;
use generic_array::sequence::*;
use generic_array::typenum::{U0, U3, U4, U97};
use generic_array::GenericArray;

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l: GenericArray<i32, U97> = GenericArray::clone_from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

#[test]
fn test_drop() {
    #[derive(Clone)]
    struct TestDrop<'a>(&'a Cell<u32>);

    impl<'a> Drop for TestDrop<'a> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    let drop_counter = Cell::new(0);
    {
        let _: GenericArray<TestDrop, U3> = arr![TestDrop; TestDrop(&drop_counter),
                           TestDrop(&drop_counter),
                           TestDrop(&drop_counter)];
    }
    assert_eq!(drop_counter.get(), 3);
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_copy() {
    let test = arr![u32; 1, 2, 3];
    let test2 = test;
    // if GenericArray is not copy, this should fail as a use of a moved value
    assert_eq!(test[1], 2);
    assert_eq!(test2[0], 1);
}

#[derive(Debug, PartialEq, Eq)]
struct NoClone<T>(T);

#[test]
fn test_from_slice() {
    let arr = [1, 2, 3, 4];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
    let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
}

#[test]
fn test_from_mut_slice() {
    let mut arr = [1, 2, 3, 4];
    {
        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = 10;
    }
    assert_eq!(arr, [1, 2, 10, 4]);
    let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    {
        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = NoClone(10);
    }
    assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]);
}

#[test]
fn test_default() {
    let arr = GenericArray::<u8, U4>::default();
    assert_eq!(arr.as_slice(), &[0, 0, 0, 0]);
}

#[test]
fn test_from() {
    let data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)];
    let garray: GenericArray<(usize, usize, usize), U3> = data.into();
    assert_eq!(&data, garray.as_slice());
}

#[test]
fn test_unit_macro() {
    let arr = arr![f32; 3.14];
    assert_eq!(arr[0], 3.14);
}

#[test]
fn test_empty_macro() {
    let _arr = arr![f32;];
}

#[test]
fn test_cmp() {
    let _ = arr![u8; 0x00].cmp(&arr![u8; 0x00]);
}

/// This test should cause a helpful compile error if uncommented.
// #[test]
// fn test_empty_macro2(){
//     let arr = arr![];
// }
#[cfg(feature = "serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::typenum::U6;
    use generic_array::GenericArray;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}

#[test]
fn test_map() {
    let b: GenericArray<i32, U4> = GenericArray::generate(|i| i as i32 * 4).map(|x| x - 3);

    assert_eq!(b, arr![i32; -3, 1, 5, 9]);
}

#[test]
fn test_zip() {
    let a: GenericArray<_, U4> = GenericArray::generate(|i| i + 1);
    let b: GenericArray<_, U4> = GenericArray::generate(|i| i as i32 * 4);

    // Uses reference and non-reference arguments
    let c = (&a).zip(b, |r, l| *r as i32 + l);

    assert_eq!(c, arr![i32; 1, 6, 11, 16]);
}

#[test]
#[should_panic]
fn test_from_iter_short() {
    use core::iter::repeat;

    let a: GenericArray<_, U4> = repeat(11).take(3).collect();

    assert_eq!(a, arr![i32; 11, 11, 11, 0]);
}

#[test]
fn test_from_iter() {
    use core::iter::{once, repeat};

    let a: GenericArray<_, U4> = repeat(11).take(3).chain(once(0)).collect();

    assert_eq!(a, arr![i32; 11, 11, 11, 0]);
}

#[allow(unused)]
#[derive(Debug, Copy, Clone)]
enum E {
    V,
    V2(i32),
    V3 { h: bool, i: i32 },
}

#[allow(unused)]
#[derive(Debug, Copy, Clone)]
#[repr(C)]
#[repr(packed)]
struct Test {
    t: u16,
    s: u32,
    mm: bool,
    r: u16,
    f: u16,
    p: (),
    o: u32,
    ff: *const extern "C" fn(*const char) -> *const core::ffi::c_void,
    l: *const core::ffi::c_void,
    w: bool,
    q: bool,
    v: E,
}

#[test]
fn test_sizes() {
    use core::mem::{size_of, size_of_val};

    assert_eq!(size_of::<E>(), 8);

    assert_eq!(size_of::<Test>(), 25 + size_of::<usize>() * 2);

    assert_eq!(size_of_val(&arr![u8; 1, 2, 3]), size_of::<u8>() * 3);
    assert_eq!(size_of_val(&arr![u32; 1]), size_of::<u32>() * 1);
    assert_eq!(size_of_val(&arr![u64; 1, 2, 3, 4]), size_of::<u64>() * 4);

    assert_eq!(size_of::<GenericArray<Test, U97>>(), size_of::<Test>() * 97);
}

#[test]
fn test_alignment() {
    use core::mem::align_of;

    assert_eq!(align_of::<GenericArray::<u32, U0>>(), align_of::<[u32; 0]>());
    assert_eq!(align_of::<GenericArray::<u32, U3>>(), align_of::<[u32; 3]>());
    assert_eq!(align_of::<GenericArray::<Test, U3>>(), align_of::<[Test; 3]>());
}

#[test]
fn test_append() {
    let a = arr![i32; 1, 2, 3];

    let b = a.append(4);

    assert_eq!(b, arr![i32; 1, 2, 3, 4]);
}

#[test]
fn test_prepend() {
    let a = arr![i32; 1, 2, 3];

    let b = a.prepend(4);

    assert_eq!(b, arr![i32; 4, 1, 2, 3]);
}

#[test]
fn test_pop() {
    let a = arr![i32; 1, 2, 3, 4];

    let (init, last) = a.pop_back();

    assert_eq!(init, arr![i32; 1, 2, 3]);
    assert_eq!(last, 4);

    let (head, tail) = a.pop_front();

    assert_eq!(head, 1);
    assert_eq!(tail, arr![i32; 2, 3, 4]);
}

#[test]
fn test_split() {
    let a = arr![i32; 1, 2, 3, 4];

    let (b, c) = a.split();

    assert_eq!(b, arr![i32; 1]);
    assert_eq!(c, arr![i32; 2, 3, 4]);

    let (e, f) = a.split();

    assert_eq!(e, arr![i32; 1, 2]);
    assert_eq!(f, arr![i32; 3, 4]);
}

#[test]
fn test_split_ref() {
    let a = arr![i32; 1, 2, 3, 4];
    let a_ref = &a;

    let (b_ref, c_ref) = a_ref.split();

    assert_eq!(b_ref, &arr![i32; 1]);
    assert_eq!(c_ref, &arr![i32; 2, 3, 4]);

    let (e_ref, f_ref) = a_ref.split();

    assert_eq!(e_ref, &arr![i32; 1, 2]);
    assert_eq!(f_ref, &arr![i32; 3, 4]);
}

#[test]
fn test_split_mut() {
    let mut a = arr![i32; 1, 2, 3, 4];
    let a_ref = &mut a;

    let (b_ref, c_ref) = a_ref.split();

    assert_eq!(b_ref, &mut arr![i32; 1]);
    assert_eq!(c_ref, &mut arr![i32; 2, 3, 4]);

    let (e_ref, f_ref) = a_ref.split();

    assert_eq!(e_ref, &mut arr![i32; 1, 2]);
    assert_eq!(f_ref, &mut arr![i32; 3, 4]);
}

#[test]
fn test_concat() {
    let a = arr![i32; 1, 2];
    let b = arr![i32; 3, 4, 5];

    let c = a.concat(b);

    assert_eq!(c, arr![i32; 1, 2, 3, 4, 5]);

    let (d, e) = c.split();

    assert_eq!(d, arr![i32; 1, 2]);
    assert_eq!(e, arr![i32; 3, 4, 5]);
}

#[test]
fn test_fold() {
    let a = arr![i32; 1, 2, 3, 4];

    assert_eq!(10, a.fold(0, |a, x| a + x));
}

fn sum_generic<S>(s: S) -> i32
where
    S: FunctionalSequence<i32>,
    S::Item: Add<i32, Output = i32>, // `+`
    i32: Add<S::Item, Output = i32>, // reflexive
{
    s.fold(0, |a, x| a + x)
}

#[test]
fn test_sum() {
    let a = sum_generic(arr![i32; 1, 2, 3, 4]);

    assert_eq!(a, 10);
}

#[test]
fn test_as_ref() {
    let a = arr![i32; 1, 2, 3, 4];
    let a_ref: &[i32; 4] = a.as_ref();
    assert_eq!(a_ref, &[1, 2, 3, 4]);
}

#[test]
fn test_as_mut() {
    let mut a = arr![i32; 1, 2, 3, 4];
    let a_mut: &mut [i32; 4] = a.as_mut();
    assert_eq!(a_mut, &mut [1, 2, 3, 4]);
    a_mut[2] = 0;
    assert_eq!(a_mut, &mut [1, 2, 0, 4]);
    assert_eq!(a, arr![i32; 1, 2, 0, 4]);
}

#[test]
fn test_from_array_ref() {
    let a = arr![i32; 1, 2, 3, 4];
    let a_ref: &[i32; 4] = a.as_ref();
    let a_from: &GenericArray<i32, U4> = a_ref.into();
    assert_eq!(&a, a_from);
}

#[test]
fn test_from_array_mut() {
    let mut a = arr![i32; 1, 2, 3, 4];
    let mut a_copy = a;
    let a_mut: &mut [i32; 4] = a.as_mut();
    let a_from: &mut GenericArray<i32, U4> = a_mut.into();
    assert_eq!(&mut a_copy, a_from);
}
<|endoftext|>


<commit_before>use std::{thread, time};

use clerk::Delay;

pub struct CustomDelay;

impl Delay for CustomDelay {
    fn delay_ns(ns: u16) {
        thread::sleep(time::Duration::new(0, ns as u32));
    }
}
<commit_msg>Fix clippy issues<commit_after>use std::{thread, time};

use clerk::Delay;

pub struct CustomDelay;

impl Delay for CustomDelay {
    fn delay_ns(ns: u16) {
        thread::sleep(time::Duration::new(0, u32::from(ns)));
    }
}
<|endoftext|>