<commit_before>//! Standard symbolic constants and types
//!
use {Errno, Error, Result, NixPath};
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{self, c_char, c_void, c_int, size_t, pid_t, off_t, uid_t, gid_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

#[derive(Clone, Copy)]
pub enum ForkResult {
    Parent {
        child: pid_t
    },
    Child
}

impl ForkResult {
    pub fn is_child(&self) -> bool {
        match *self {
            ForkResult::Child => true,
            _ => false
        }
    }

    pub fn is_parent(&self) -> bool {
        !self.is_child()
    }
}

pub fn fork() -> Result<ForkResult> {
    use self::ForkResult::*;
    let res = unsafe { libc::fork() };

    Errno::result(res).map(|res| match res {
        0 => Child,
        res => Parent { child: res }
    })
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { libc::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { libc::getppid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn setpgid(pid: pid_t, pgid: pid_t) -> Result<()> {
    let res = unsafe { libc::setpgid(pid, pgid) };
    Errno::result(res).map(drop)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[inline]
pub fn gettid() -> pid_t {
    unsafe { libc::syscall(libc::SYS_gettid) as pid_t }    // no error handling, according to man page: "These functions are always successful."
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { libc::dup(oldfd) };

    Errno::result(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { libc::dup2(oldfd, newfd) };

    Errno::result(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { libc::chdir(cstr.as_ptr()) }
    }));

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

#[inline]
pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<uid_t>, group: Option<gid_t>) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        // We use `0 - 1` to get `-1 : {u,g}id_t` which is specified as the no-op value for chown(3).
        unsafe { libc::chown(cstr.as_ptr(), owner.unwrap_or(0 - 1), group.unwrap_or(0 - 1)) }
    }));

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

fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
    use std::ptr;
    use libc::c_char;

    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());
    args_p
}

#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
    let args_p = to_exec_array(argv);

    unsafe {
        libc::execv(path.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);
    let env_p = to_exec_array(env);

    unsafe {
        libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);

    unsafe {
        libc::execvp(filename.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
    Errno::result(res).map(drop)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    // Handle some differences in type of the len arg across platforms.
    cfg_if! {
        if #[cfg(any(target_os = "macos", target_os = "ios"))] {
            type sethostname_len_t = c_int;
        } else {
            type sethostname_len_t = size_t;
        }
    }
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as sethostname_len_t;

    let res = unsafe { libc::sethostname(ptr, len) };
    Errno::result(res).map(drop)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { libc::gethostname(ptr, len) };
    Errno::result(res).map(drop)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { libc::close(fd) };
    Errno::result(res).map(drop)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    Errno::result(res).map(|r| r as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    Errno::result(res).map(|r| r as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = libc::pipe(fds.as_mut_ptr());

        try!(Errno::result(res));

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = libc::pipe(fds.as_mut_ptr());

        try!(Errno::result(res));

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    unsafe {
        // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
        // we return `Ok(false)`
        if libc::isatty(fd) == 1 {
            Ok(true)
        } else {
            match Errno::last() {
                Errno::ENOTTY => Ok(false),
                err => Err(Error::Sys(err)),
            }
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            libc::unlink(cstr.as_ptr())
        }
    }));

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

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { libc::chroot(cstr.as_ptr()) }
    }));

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

#[inline]
pub fn fsync(fd: RawFd) -> Result<()> {
    let res = unsafe { libc::fsync(fd) };

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

// `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
// TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
#[cfg(any(target_os = "linux",
          target_os = "android",
          target_os = "emscripten"))]
#[inline]
pub fn fdatasync(fd: RawFd) -> Result<()> {
    let res = unsafe { libc::fdatasync(fd) };

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

// POSIX requires that getuid, geteuid, getgid, getegid are always successful,
// so no need to check return value or errno. See:
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
#[inline]
pub fn getuid() -> uid_t {
    unsafe { libc::getuid() }
}

#[inline]
pub fn geteuid() -> uid_t {
    unsafe { libc::geteuid() }
}

#[inline]
pub fn getgid() -> gid_t {
    unsafe { libc::getgid() }
}

#[inline]
pub fn getegid() -> gid_t {
    unsafe { libc::getegid() }
}

#[inline]
pub fn setuid(uid: uid_t) -> Result<()> {
    let res = unsafe { libc::setuid(uid) };

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

#[inline]
pub fn setgid(gid: gid_t) -> Result<()> {
    let res = unsafe { libc::setgid(gid) };

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

#[inline]
pub fn pause() -> Result<()> {
    let res = unsafe { libc::pause() };

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

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use {Errno, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

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

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        Err(Error::Sys(Errno::last()))
    }
}
<commit_msg>unistd: Mark fork() and related methods as #[inline]<commit_after>//! Standard symbolic constants and types
//!
use {Errno, Error, Result, NixPath};
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{self, c_char, c_void, c_int, size_t, pid_t, off_t, uid_t, gid_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

#[derive(Clone, Copy)]
pub enum ForkResult {
    Parent {
        child: pid_t
    },
    Child
}

impl ForkResult {
    #[inline]
    pub fn is_child(&self) -> bool {
        match *self {
            ForkResult::Child => true,
            _ => false
        }
    }

    #[inline]
    pub fn is_parent(&self) -> bool {
        !self.is_child()
    }
}

#[inline]
pub fn fork() -> Result<ForkResult> {
    use self::ForkResult::*;
    let res = unsafe { libc::fork() };

    Errno::result(res).map(|res| match res {
        0 => Child,
        res => Parent { child: res }
    })
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { libc::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { libc::getppid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn setpgid(pid: pid_t, pgid: pid_t) -> Result<()> {
    let res = unsafe { libc::setpgid(pid, pgid) };
    Errno::result(res).map(drop)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[inline]
pub fn gettid() -> pid_t {
    unsafe { libc::syscall(libc::SYS_gettid) as pid_t }    // no error handling, according to man page: "These functions are always successful."
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { libc::dup(oldfd) };

    Errno::result(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { libc::dup2(oldfd, newfd) };

    Errno::result(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { libc::chdir(cstr.as_ptr()) }
    }));

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

#[inline]
pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<uid_t>, group: Option<gid_t>) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        // We use `0 - 1` to get `-1 : {u,g}id_t` which is specified as the no-op value for chown(3).
        unsafe { libc::chown(cstr.as_ptr(), owner.unwrap_or(0 - 1), group.unwrap_or(0 - 1)) }
    }));

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

fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
    use std::ptr;
    use libc::c_char;

    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());
    args_p
}

#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
    let args_p = to_exec_array(argv);

    unsafe {
        libc::execv(path.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);
    let env_p = to_exec_array(env);

    unsafe {
        libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);

    unsafe {
        libc::execvp(filename.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
    Errno::result(res).map(drop)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    // Handle some differences in type of the len arg across platforms.
    cfg_if! {
        if #[cfg(any(target_os = "macos", target_os = "ios"))] {
            type sethostname_len_t = c_int;
        } else {
            type sethostname_len_t = size_t;
        }
    }
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as sethostname_len_t;

    let res = unsafe { libc::sethostname(ptr, len) };
    Errno::result(res).map(drop)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { libc::gethostname(ptr, len) };
    Errno::result(res).map(drop)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { libc::close(fd) };
    Errno::result(res).map(drop)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    Errno::result(res).map(|r| r as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    Errno::result(res).map(|r| r as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = libc::pipe(fds.as_mut_ptr());

        try!(Errno::result(res));

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = libc::pipe(fds.as_mut_ptr());

        try!(Errno::result(res));

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    unsafe {
        // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
        // we return `Ok(false)`
        if libc::isatty(fd) == 1 {
            Ok(true)
        } else {
            match Errno::last() {
                Errno::ENOTTY => Ok(false),
                err => Err(Error::Sys(err)),
            }
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            libc::unlink(cstr.as_ptr())
        }
    }));

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

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { libc::chroot(cstr.as_ptr()) }
    }));

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

#[inline]
pub fn fsync(fd: RawFd) -> Result<()> {
    let res = unsafe { libc::fsync(fd) };

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

// `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
// TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
#[cfg(any(target_os = "linux",
          target_os = "android",
          target_os = "emscripten"))]
#[inline]
pub fn fdatasync(fd: RawFd) -> Result<()> {
    let res = unsafe { libc::fdatasync(fd) };

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

// POSIX requires that getuid, geteuid, getgid, getegid are always successful,
// so no need to check return value or errno. See:
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html
//   - http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html
#[inline]
pub fn getuid() -> uid_t {
    unsafe { libc::getuid() }
}

#[inline]
pub fn geteuid() -> uid_t {
    unsafe { libc::geteuid() }
}

#[inline]
pub fn getgid() -> gid_t {
    unsafe { libc::getgid() }
}

#[inline]
pub fn getegid() -> gid_t {
    unsafe { libc::getegid() }
}

#[inline]
pub fn setuid(uid: uid_t) -> Result<()> {
    let res = unsafe { libc::setuid(uid) };

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

#[inline]
pub fn setgid(gid: gid_t) -> Result<()> {
    let res = unsafe { libc::setgid(gid) };

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

#[inline]
pub fn pause() -> Result<()> {
    let res = unsafe { libc::pause() };

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

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use {Errno, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

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

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        Err(Error::Sys(Errno::last()))
    }
}
<|endoftext|>


<commit_before>//! Generate update information from dependency information.

use std::rc::Rc;
use std::collections::HashMap;
use std::io::Write;

use semver::{ self, Version };

use dependencies;

/// Stores old and new version.
pub struct Bump {
    /// The old version.
    pub old: Version,
    /// The new version.
    pub new: Version,
}

/// Stores update info for dependency.
pub struct Dependency {
    /// The library name.
    pub name: Rc<String>,
    /// Bump info.
    pub bump: Bump,
}

/// Stores information about a package.
pub struct Package {
    /// The package name.
    pub name: Rc<String>,
    /// The order to update library.
    pub order: u32,
    /// Update information.
    pub bump: Bump,
    /// The dependencies.
    pub dependencies: Vec<Dependency>,
}

/// Generates update info.
pub fn generate_update_info_from(dependency_info: &str) -> Result<String, String> {
    use piston_meta::*;
    use std::iter::FromIterator;

    type PackageIndex = usize;
    type Depth = u32;

    fn depth_of(
        package_index: PackageIndex,
        package_indices: &HashMap<Rc<String>, PackageIndex>,
        depths: &mut HashMap<PackageIndex, Depth>,
        dependencies_data: &[dependencies::Package]
    ) -> Depth {
        let package = &dependencies_data[package_index];
        let d = depths.get(&package_index).map(|d| *d);
        match d {
            None => {
                // The depth of a package equals maximum depth of the dependencies + 1.
                let new_depth: Depth = package.dependencies.iter().map(|dep| {
                        package_indices.get(&dep.name).map(|&p| {
                                depth_of(p, package_indices, depths, dependencies_data)
                            }).unwrap_or(0)
                    }).max().unwrap_or(0) + 1;
                depths.insert(package_index, new_depth);
                new_depth
            }
            Some(x) => x
        }
    }

    // Tries appending zero to version to make it parse.
    fn parse_version(text: &str) -> Result<Version, semver::ParseError> {
        match Version::parse(text) {
            Err(_) => {
                let append_zero = format!("{}.0", text);
                Version::parse(&append_zero)
            }
            x => x
        }
    }

    // Whether the version should be ignored.
    fn ignore_version(text: &str) -> bool {
        text == "*"
    }

    // Returns true if two different versions means a breaking change.
    fn breaks(a: &Version, b: &Version) -> bool {
        if a.major != b.major { true }
        else if a.major != 0 { false }
        else if a.minor != b.minor { true }
        else if a.minor != 0 { false }
        else if a.patch != b.patch { true }
        else { false }
    }

    // Increment first non-zero number.
    fn increment_version(version: &mut Version) {
        if version.major != 0 { version.increment_major(); }
        else if version.minor != 0 { version.increment_minor(); }
        else { version.increment_patch(); }
    }

    // Parse and convert to dependencies data.
    let dependencies_meta_syntax = include_str!("../assets/dependencies/syntax.txt");
    let dependencies_meta_rules = stderr_unwrap(dependencies_meta_syntax,
        syntax(dependencies_meta_syntax));
    let dependency_info = stderr_unwrap(dependency_info,
        parse(&dependencies_meta_rules, dependency_info));
    let mut ignored = vec![];
    let dependencies_data = try!(dependencies::convert(&dependency_info, &mut ignored)
        .map_err(|_| String::from("Could not convert dependency info")));

    // Stores the package indices using package name as key.
    let package_indices: HashMap<Rc<String>, PackageIndex> =
        HashMap::from_iter(dependencies_data.iter().enumerate().map(
            |(i, p)| {
                (p.name.clone(), i)
            }));

    // Store the depths of libraries.
    let mut depths: HashMap<PackageIndex, Depth> = HashMap::new();
    for i in 0 .. dependencies_data.len() {
        let _depth = depth_of(i, &package_indices, &mut depths, &dependencies_data);
    }

    let mut new_versions: HashMap<Rc<String>, Version> = HashMap::new();
    for package in &dependencies_data {
        // Get latest version used by any dependency.
        for dep in &package.dependencies {
            if ignore_version(&dep.version) { continue; }

            let version = try!(parse_version(&dep.version)
                .map_err(|_| format!("Could not parse version `{}` for dependency `{}` in `{}`",
                    &dep.version, &dep.name, &package.name)));
            let v = new_versions.get(&dep.name).map(|v| v.clone());
            match v {
                None => {
                    new_versions.insert(dep.name.clone(), version);
                }
                Some(v) => {
                    if v < version {
                        new_versions.insert(dep.name.clone(), version);
                    }
                }
            }
        }
    }

    // Overwrite the versions used by packages.
    for package in &dependencies_data {
        let version = try!(Version::parse(&package.version)
            .map_err(|_| format!("Could not parse version `{}` for `{}`",
                &package.version, &package.name)));
        new_versions.insert(package.name.clone(), version);
    }

    // Create list of sorted package indices by depth.
    let mut sorted_depths: Vec<_> = depths.iter().collect();
    sorted_depths.sort_by(|&(_, da), &(_, db)| da.cmp(db));

    // Stores the update info.
    let mut update_packages: Vec<Package> = vec![];

    for (&package_index, &order) in sorted_depths {
        let package = &dependencies_data[package_index];
        let mut update_dependencies = vec![];

        // Find dependencies that needs update.
        for dep in &package.dependencies {
            if ignore_version(&dep.version) { continue; }

            let old_version = try!(parse_version(&dep.version)
                .map_err(|_| format!("Could not parse version `{}` for dependency `{}` in `{}`",
                    &dep.version, &dep.name, &package.name)));
            let new_version = new_versions.get(&dep.name).unwrap();
            if breaks(new_version, &old_version) {
                update_dependencies.push(Dependency {
                        name: dep.name.clone(),
                        bump: Bump {
                            old: old_version,
                            new: new_version.clone(),
                        }
                    });
            }
        }

        // If any dependency needs update, then the package needs update.
        if update_dependencies.len() > 0 {
            let old_version = try!(Version::parse(&package.version)
                .map_err(|_| format!("Could not parse version `{}` for `{}`",
                    &package.version, &package.name)));
            let new_version = new_versions.get_mut(&package.name).unwrap();
            if *new_version == old_version {
                increment_version(new_version);
            }
            update_packages.push(Package {
                    name: package.name.clone(),
                    order: order,
                    bump: Bump {
                        old: old_version,
                        new: new_version.clone(),
                    },
                    dependencies: update_dependencies,
                });
        }
    }

    let mut w: Vec<u8> = vec![];
    writeln!(w, "{{").unwrap();
    let n0 = update_packages.len();
    for (i0, update_package) in update_packages.iter().enumerate() {
        write!(w, "  ").unwrap();
        json::write_string(&mut w, &update_package.name).unwrap();
        writeln!(w, ": {{").unwrap();
        writeln!(w, "    \"order\": {},", update_package.order).unwrap();

        // Bump package.
        writeln!(w, "    \"bump\": {{").unwrap();
        write!(w, "      \"old\": ").unwrap();
        json::write_string(&mut w, &format!("{}", update_package.bump.old)).unwrap();
        writeln!(w, ",").unwrap();
        write!(w, "      \"new\": ").unwrap();
        json::write_string(&mut w, &format!("{}", update_package.bump.new)).unwrap();
        writeln!(w, "").unwrap();
        writeln!(w, "    }},").unwrap();

        // Dependencies.
        writeln!(w, "    \"dependencies\": {{").unwrap();
        let n1 = update_package.dependencies.len();
        for (i1, dep) in update_package.dependencies.iter().enumerate() {
            write!(w, "      ").unwrap();
            json::write_string(&mut w, &dep.name).unwrap();
            writeln!(w, ": {{").unwrap();
            writeln!(w, "        \"bump\": {{").unwrap();
            write!(w, "          \"old\": ").unwrap();
            json::write_string(&mut w, &format!("{}", dep.bump.old)).unwrap();
            writeln!(w, ",").unwrap();
            write!(w, "          \"new\": ").unwrap();
            json::write_string(&mut w, &format!("{}", dep.bump.new)).unwrap();
            writeln!(w, "").unwrap();
            writeln!(w, "        }}").unwrap();
            write!(w, "      }}").unwrap();
            if i1 + 1 < n1 {
                writeln!(w, ",").unwrap();
            } else {
                writeln!(w, "").unwrap();
            }
        }
        writeln!(w, "    }}").unwrap();

        write!(w, "  }}").unwrap();
        if i0 + 1 < n0 {
            writeln!(w, ",").unwrap();
        } else {
            writeln!(w, "").unwrap();
        }
    }
    writeln!(w, "}}").unwrap();

    Ok(String::from_utf8(w).unwrap())
}
<commit_msg>Support dependencies staring with `>=`<commit_after>//! Generate update information from dependency information.

use std::rc::Rc;
use std::collections::HashMap;
use std::io::Write;

use semver::{ self, Version };

use dependencies;

/// Stores old and new version.
pub struct Bump {
    /// The old version.
    pub old: Version,
    /// The new version.
    pub new: Version,
}

/// Stores update info for dependency.
pub struct Dependency {
    /// The library name.
    pub name: Rc<String>,
    /// Bump info.
    pub bump: Bump,
}

/// Stores information about a package.
pub struct Package {
    /// The package name.
    pub name: Rc<String>,
    /// The order to update library.
    pub order: u32,
    /// Update information.
    pub bump: Bump,
    /// The dependencies.
    pub dependencies: Vec<Dependency>,
}

/// Generates update info.
pub fn generate_update_info_from(dependency_info: &str) -> Result<String, String> {
    use piston_meta::*;
    use std::iter::FromIterator;

    type PackageIndex = usize;
    type Depth = u32;

    fn depth_of(
        package_index: PackageIndex,
        package_indices: &HashMap<Rc<String>, PackageIndex>,
        depths: &mut HashMap<PackageIndex, Depth>,
        dependencies_data: &[dependencies::Package]
    ) -> Depth {
        let package = &dependencies_data[package_index];
        let d = depths.get(&package_index).map(|d| *d);
        match d {
            None => {
                // The depth of a package equals maximum depth of the dependencies + 1.
                let new_depth: Depth = package.dependencies.iter().map(|dep| {
                        package_indices.get(&dep.name).map(|&p| {
                                depth_of(p, package_indices, depths, dependencies_data)
                            }).unwrap_or(0)
                    }).max().unwrap_or(0) + 1;
                depths.insert(package_index, new_depth);
                new_depth
            }
            Some(x) => x
        }
    }

    // Tries appending zero to version to make it parse.
    fn parse_version(text: &str) -> Result<Version, semver::ParseError> {
        // Ignore `>=`.
        let text = if text.starts_with(">=") {
            &text[2..]
        } else {
            text
        };
        match Version::parse(text) {
            Err(_) => {
                let append_zero = format!("{}.0", text);
                Version::parse(&append_zero)
            }
            x => x
        }
    }

    // Whether the version should be ignored.
    fn ignore_version(text: &str) -> bool {
        text == "*"
    }

    // Returns true if two different versions means a breaking change.
    fn breaks(a: &Version, b: &Version) -> bool {
        if a.major != b.major { true }
        else if a.major != 0 { false }
        else if a.minor != b.minor { true }
        else if a.minor != 0 { false }
        else if a.patch != b.patch { true }
        else { false }
    }

    // Increment first non-zero number.
    fn increment_version(version: &mut Version) {
        if version.major != 0 { version.increment_major(); }
        else if version.minor != 0 { version.increment_minor(); }
        else { version.increment_patch(); }
    }

    // Parse and convert to dependencies data.
    let dependencies_meta_syntax = include_str!("../assets/dependencies/syntax.txt");
    let dependencies_meta_rules = stderr_unwrap(dependencies_meta_syntax,
        syntax(dependencies_meta_syntax));
    let dependency_info = stderr_unwrap(dependency_info,
        parse(&dependencies_meta_rules, dependency_info));
    let mut ignored = vec![];
    let dependencies_data = try!(dependencies::convert(&dependency_info, &mut ignored)
        .map_err(|_| String::from("Could not convert dependency info")));

    // Stores the package indices using package name as key.
    let package_indices: HashMap<Rc<String>, PackageIndex> =
        HashMap::from_iter(dependencies_data.iter().enumerate().map(
            |(i, p)| {
                (p.name.clone(), i)
            }));

    // Store the depths of libraries.
    let mut depths: HashMap<PackageIndex, Depth> = HashMap::new();
    for i in 0 .. dependencies_data.len() {
        let _depth = depth_of(i, &package_indices, &mut depths, &dependencies_data);
    }

    let mut new_versions: HashMap<Rc<String>, Version> = HashMap::new();
    for package in &dependencies_data {
        // Get latest version used by any dependency.
        for dep in &package.dependencies {
            if ignore_version(&dep.version) { continue; }

            let version = try!(parse_version(&dep.version)
                .map_err(|_| format!("Could not parse version `{}` for dependency `{}` in `{}`",
                    &dep.version, &dep.name, &package.name)));
            let v = new_versions.get(&dep.name).map(|v| v.clone());
            match v {
                None => {
                    new_versions.insert(dep.name.clone(), version);
                }
                Some(v) => {
                    if v < version {
                        new_versions.insert(dep.name.clone(), version);
                    }
                }
            }
        }
    }

    // Overwrite the versions used by packages.
    for package in &dependencies_data {
        let version = try!(Version::parse(&package.version)
            .map_err(|_| format!("Could not parse version `{}` for `{}`",
                &package.version, &package.name)));
        new_versions.insert(package.name.clone(), version);
    }

    // Create list of sorted package indices by depth.
    let mut sorted_depths: Vec<_> = depths.iter().collect();
    sorted_depths.sort_by(|&(_, da), &(_, db)| da.cmp(db));

    // Stores the update info.
    let mut update_packages: Vec<Package> = vec![];

    for (&package_index, &order) in sorted_depths {
        let package = &dependencies_data[package_index];
        let mut update_dependencies = vec![];

        // Find dependencies that needs update.
        for dep in &package.dependencies {
            if ignore_version(&dep.version) { continue; }
            // Do not generate update info for dependencies starting with `>=`.
            if dep.version.starts_with(">=") { continue; }

            let old_version = try!(parse_version(&dep.version)
                .map_err(|_| format!("Could not parse version `{}` for dependency `{}` in `{}`",
                    &dep.version, &dep.name, &package.name)));
            let new_version = new_versions.get(&dep.name).unwrap();
            if breaks(new_version, &old_version) {
                update_dependencies.push(Dependency {
                        name: dep.name.clone(),
                        bump: Bump {
                            old: old_version,
                            new: new_version.clone(),
                        }
                    });
            }
        }

        // If any dependency needs update, then the package needs update.
        if update_dependencies.len() > 0 {
            let old_version = try!(Version::parse(&package.version)
                .map_err(|_| format!("Could not parse version `{}` for `{}`",
                    &package.version, &package.name)));
            let new_version = new_versions.get_mut(&package.name).unwrap();
            if *new_version == old_version {
                increment_version(new_version);
            }
            update_packages.push(Package {
                    name: package.name.clone(),
                    order: order,
                    bump: Bump {
                        old: old_version,
                        new: new_version.clone(),
                    },
                    dependencies: update_dependencies,
                });
        }
    }

    let mut w: Vec<u8> = vec![];
    writeln!(w, "{{").unwrap();
    let n0 = update_packages.len();
    for (i0, update_package) in update_packages.iter().enumerate() {
        write!(w, "  ").unwrap();
        json::write_string(&mut w, &update_package.name).unwrap();
        writeln!(w, ": {{").unwrap();
        writeln!(w, "    \"order\": {},", update_package.order).unwrap();

        // Bump package.
        writeln!(w, "    \"bump\": {{").unwrap();
        write!(w, "      \"old\": ").unwrap();
        json::write_string(&mut w, &format!("{}", update_package.bump.old)).unwrap();
        writeln!(w, ",").unwrap();
        write!(w, "      \"new\": ").unwrap();
        json::write_string(&mut w, &format!("{}", update_package.bump.new)).unwrap();
        writeln!(w, "").unwrap();
        writeln!(w, "    }},").unwrap();

        // Dependencies.
        writeln!(w, "    \"dependencies\": {{").unwrap();
        let n1 = update_package.dependencies.len();
        for (i1, dep) in update_package.dependencies.iter().enumerate() {
            write!(w, "      ").unwrap();
            json::write_string(&mut w, &dep.name).unwrap();
            writeln!(w, ": {{").unwrap();
            writeln!(w, "        \"bump\": {{").unwrap();
            write!(w, "          \"old\": ").unwrap();
            json::write_string(&mut w, &format!("{}", dep.bump.old)).unwrap();
            writeln!(w, ",").unwrap();
            write!(w, "          \"new\": ").unwrap();
            json::write_string(&mut w, &format!("{}", dep.bump.new)).unwrap();
            writeln!(w, "").unwrap();
            writeln!(w, "        }}").unwrap();
            write!(w, "      }}").unwrap();
            if i1 + 1 < n1 {
                writeln!(w, ",").unwrap();
            } else {
                writeln!(w, "").unwrap();
            }
        }
        writeln!(w, "    }}").unwrap();

        write!(w, "  }}").unwrap();
        if i0 + 1 < n0 {
            writeln!(w, ",").unwrap();
        } else {
            writeln!(w, "").unwrap();
        }
    }
    writeln!(w, "}}").unwrap();

    Ok(String::from_utf8(w).unwrap())
}
<|endoftext|>


<commit_before>use common::*;
use std::io::{Read, Write};

mod interrupts;
mod memory;
mod modes;
mod opcodes;
mod registers;

use self::memory::*;

pub struct VM<'a, R: Read, W: Write> {
    input: R,
    output: W,

    registers: Registers,
    memory: Memory<'a>,
}

impl<'a, R: Read, W: Write> VM<'a, R, W> {
    pub fn new(input: R, output: W) -> Self {
        unimplemented!()
    }

    pub fn run(&mut self, executable: Data) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use self::interrupts::*;
    use self::modes::*;
    use self::opcodes::*;
    use self::registers::*;
    use std::io::{BufReader, BufWriter};
    use super::*;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    fn simple() {
        assert!(run(&[], vec![]).0.is_empty());

        {
            let mut executable = vec![0, 0,
                MOV, REG, A, VALUE, 123, 0,
                ADD, REG, B, REG, A, REG, A];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(123, registers[A as usize]);
            assert_eq!(246, registers[B as usize]);
            assert!(output.is_empty());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                // stack allocation for 2 words
                SUB, REG, SP,  REG, SP,  VALUE, 4, 0,

                PUSH, VALUE, 5, 0,
                PUSH, VALUE, 6, 0,
                ADD,  REG, A,  PTR, REG, SP,  PTR_WITH_OFFSET, REG, SP, 2, 0,
                // add a, [sp], [sp+2]
                POP, B,
                POP, C,
                ADD, REG, SP,  REG, SP,  4, 0];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory)  = run(&[], executable);

            assert_eq!(11, registers[A as usize]);
            assert_eq!(6, registers[B as usize]);
            assert_eq!(5, registers[C as usize]);
            assert!(output.is_empty());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                MOV, REG, A, VALUE, 10, 0,
                DEC, REG, A,
                INT, OUTPUT,
                JNZ, 2, 0];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[10, 0, 9, 0, 8, 0, 7, 0, 6, 0, 5, 0,
                         4, 0, 3, 0, 2, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                MOV, REG, B, VALUE, 24, 0,       // data address
                MOV, REG, A, PTR, REG, B,        // dereference B
                INT, OUTPUT,
                INC, REG, B,
                INC, REG, B,
                JNZ, 2, 0,

                3, 0,                            // data with address 24
                2, 0,                            // data with address 26
                1, 0,
                0, 0];
            let data_length = 8;
            let code_length = executable.len() as u8 - data_length;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(8, memory.data.len());
            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[3, 0, 2, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                INT, INPUT,
                INT, OUTPUT,
                JNZ, 2, 0];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[3, 0, 2, 0, 1, 0, 0, 0], executable);
            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[3, 0, 2, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                                                      // do
                INT, INPUT,                           // a = read
                SUB, REG, SP,  REG, SP,  VALUE, 2, 0, //   (stack allocation)
                PUSH, REG, A,
                CALL, VALUE, 35, 0,                   //   a = f(a)
                INT, OUTPUT,                          //   print a
                ADD, REG, SP,  REG, SP,  VALUE, 2, 0, //   (stack deallocation)
                JNZ, 2, 0,                            // while a != 0 jmp addr 0
                JMP, 63, 0,                           // exit

                // label f
                PUSH, REG, BP,
                MOV, REG, BP, REG, SP,

                POP, REG, A,
                MUL, REG, A, REG, A, VALUE, 2, 0,    // a = a * 2

                MOV, REG, SP, REG, BP,
                POP, REG, BP,
                RET,

                NOP                                  // optional
            ];

            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[3, 0, 2, 0, 1, 0, 0, 0],
                                                  executable);

            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[6, 0, 4, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }
    }

    fn run<'a>(input: &[u8], executable: Data) -> (Data, Registers, Memory<'a>) {
        let input = BufReader::new(input);

        let output: Data = vec![];
        let output = BufWriter::new(output);

        let mut vm = VM::new(input, output);
        vm.run(executable);

        let output = vm.output
            .get_mut()
            .by_ref()
            .iter()
            .map(|x| *x)
            .collect::<Data>();

        (output, vm.registers, vm.memory)
    }
}
<commit_msg>add interrupts tests<commit_after>use common::*;
use std::io::{Read, Write};

mod interrupts;
mod memory;
mod modes;
mod opcodes;
mod registers;

use self::memory::*;

pub struct VM<'a, R: Read, W: Write> {
    input: R,
    output: W,

    registers: Registers,
    memory: Memory<'a>,
}

impl<'a, R: Read, W: Write> VM<'a, R, W> {
    pub fn new(input: R, output: W) -> Self {
        unimplemented!()
    }

    pub fn run(&mut self, executable: Data) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use self::interrupts::*;
    use self::modes::*;
    use self::opcodes::*;
    use self::registers::*;
    use std::io::{BufReader, BufWriter};
    use super::*;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
    fn simple() {
        assert!(run(&[], vec![]).0.is_empty());

        {
            let mut executable = vec![0, 0,
                MOV, REG, A, VALUE, 123, 0,
                ADD, REG, B, REG, A, REG, A];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(123, registers[A as usize]);
            assert_eq!(246, registers[B as usize]);
            assert!(output.is_empty());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                // stack allocation for 2 words
                SUB, REG, SP,  REG, SP,  VALUE, 4, 0,

                PUSH, VALUE, 5, 0,
                PUSH, VALUE, 6, 0,
                ADD,  REG, A,  PTR, REG, SP,  PTR_WITH_OFFSET, REG, SP, 2, 0,
                // add a, [sp], [sp+2]
                POP, B,
                POP, C,
                ADD, REG, SP,  REG, SP,  4, 0];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory)  = run(&[], executable);

            assert_eq!(11, registers[A as usize]);
            assert_eq!(6, registers[B as usize]);
            assert_eq!(5, registers[C as usize]);
            assert!(output.is_empty());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                MOV, REG, A, VALUE, 10, 0,
                DEC, REG, A,
                INT, OUTPUT,
                JNZ, 2, 0];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[10, 0, 9, 0, 8, 0, 7, 0, 6, 0, 5, 0,
                         4, 0, 3, 0, 2, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                MOV, REG, B, VALUE, 24, 0,       // data address
                MOV, REG, A, PTR, REG, B,        // dereference B
                INT, OUTPUT,
                INC, REG, B,
                INC, REG, B,
                JNZ, 2, 0,

                3, 0,                            // data with address 24
                2, 0,                            // data with address 26
                1, 0,
                0, 0];
            let data_length = 8;
            let code_length = executable.len() as u8 - data_length;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(8, memory.data.len());
            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[3, 0, 2, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                INT, INPUT,
                INT, OUTPUT,
                JNZ, 2, 0];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[3, 0, 2, 0, 1, 0, 0, 0], executable);

            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[3, 0, 2, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                                                      // do
                INT, INPUT,                           // a = read
                SUB, REG, SP,  REG, SP,  VALUE, 2, 0, //   (stack allocation)
                PUSH, REG, A,
                CALL, VALUE, 35, 0,                   //   a = f(a)
                INT, OUTPUT,                          //   print a
                ADD, REG, SP,  REG, SP,  VALUE, 2, 0, //   (stack deallocation)
                JNZ, 2, 0,                            // while a != 0 jmp addr 0
                JMP, 63, 0,                           // exit

                // label f
                PUSH, REG, BP,
                MOV, REG, BP, REG, SP,

                POP, REG, A,
                MUL, REG, A, REG, A, VALUE, 2, 0,    // a = a * 2

                MOV, REG, SP, REG, BP,
                POP, REG, BP,
                RET,

                NOP                                  // optional
            ];

            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[3, 0, 2, 0, 1, 0, 0, 0],
                                                  executable);

            assert_eq!(0, registers[A as usize]);
            assert_eq!(&[6, 0, 4, 0, 1, 0, 0, 0], output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                DIV, REG, A, VALUE, 1, VALUE, 0,
                MOV, REG, A, 123,
            ];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(0, registers[A as usize]);
            assert_eq!(b"Unknown Error", output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }

        {
            let mut executable = vec![0, 0,
                MOV,  PTR, VALUE,  255, 255,  VALUE, 1,
                MOV, A, 123,
            ];
            let code_length = executable.len() as u8;
            executable[0] = code_length;

            let (output, registers, memory) = run(&[], executable);

            assert_eq!(0, registers[A as usize]);
            assert_eq!(b"Segfault", output.as_slice());
            assert!(memory.stack_is_empty(registers[SP as usize]));
        }
    }

    fn run<'a>(input: &[u8], executable: Data) -> (Data, Registers, Memory<'a>) {
        let input = BufReader::new(input);

        let output: Data = vec![];
        let output = BufWriter::new(output);

        let mut vm = VM::new(input, output);
        vm.run(executable);

        let output = vm.output
            .get_mut()
            .by_ref()
            .iter()
            .map(|x| *x)
            .collect::<Data>();

        (output, vm.registers, vm.memory)
    }
}
<|endoftext|>


<commit_before><commit_msg>Added opcodes for BitVec SMT operations<commit_after>use std::fmt::Debug;
use smt::fmt

#[derive(Clone, Copy, Debug)]
#[allow(non_camel_case_types)]
pub enum OpCodes {
    concat,
    extract(u64, u64),
    bvnot,
    bvand,
    bvor,
    bvneg,
    bvadd,
    bvmul,
    bvudiv,
    bvurem,
    bvshl,
    bvlshr,
    bvult,
    bvnand,
    bvnor,
    bvxor,
    bvxnor,
    bvcomp,
    bvsub,
    bvsdiv,
    bvsrem,
    bvsmod,
    bvashr,
    // parameterized functions
    repeat(u64),
    zero_extend(u64),
    sign_extend(u64),
    rotate_left(u64),
    rotate_right(u64),
    // logical functions
    bvule,
    bvugt,
    bvuge,
    bvslt,
    bvsle,
    bvsgt,
    bvsge,
}

impl fmt::Display for OpCodes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            OpCodes::concat => "concat",
            OpCodes::extract(i, j) => format!("_ extract {} {}", i, j),
            OpCodes::bvnot => "bvnot",
            OpCodes::bvand => "bvand",
            OpCodes::bvor => "bvor",
            OpCodes::bvneg => "bvneg",
            OpCodes::bvadd => "bvadd",
            OpCodes::bvmul => "bvmul",
            OpCodes::bvudiv => "bvudiv",
            OpCodes::bvurem => "bvurem",
            OpCodes::bvshl => "bvshl",
            OpCodes::bvlshr => "bvlshr",
            OpCodes::bvult => "bvult",
            OpCodes::bvnand => "bvnand",
            OpCodes::bvnor => "bvnor",
            OpCodes::bvxor => "bvxor",
            OpCodes::bvxnor => "bvxnor",
            OpCodes::bvcomp => "bvcomp",
            OpCodes::bvsub => "bvsub",
            OpCodes::bvsdiv => "bvsdiv",
            OpCodes::bvsrem => "bvsrem",
            OpCodes::bvsmod => "bvsmod",
            OpCodes::bvashr => "bvashr",
            OpCodes::repeat(i) => format!("_ repeat {}", i),
            OpCodes::zero_extend(i) => format!("_ zero_extend {}", i),
            OpCodes::sign_extend(i) => format!("_ sign_extend {}", i),
            OpCodes::rotate_left(i) => format!("_ rotate_left {}", i),
            OpCodes::rotate_right(i) => format!("_ rotate_right {}", i),
            OpCodes::bvule => "bvule",
            OpCodes::bvugt => "bvugt",
            OpCodes::bvuge => "bvuge",
            OpCodes::bvslt => "bvslt",
            OpCodes::bvsle => "bvsle",
            OpCodes::bvsgt => "bvsgt",
            OpCodes::bvsge => "bvsge",
        };
        write!(f, "{}", s)
    }
}
<|endoftext|>


<commit_before><commit_msg>codegen: allow custom gcc configuration.<commit_after><|endoftext|>


<commit_before>use std::sync::ONCE_INIT;
use conduit::{Handler, Method};

use cargo_registry::User;
use record::GhUser;

// Users: `crates-tester-1` and `crates-tester-2`
// Passwords: ask acrichto or gankro
// Teams: `crates-test-org:owners`, `crates-test-org:just-for-crates-2`
// tester-1 is on owners only, tester-2 is on both

static GH_USER_1: GhUser = GhUser { login: "crates-tester-1", init: ONCE_INIT };
static GH_USER_2: GhUser = GhUser { login: "crates-tester-2", init: ONCE_INIT };

fn mock_user_on_only_x() -> User { GH_USER_1.user() }
fn mock_user_on_x_and_y() -> User { GH_USER_2.user() }

fn body_for_team_y() -> &'static str {
    r#"{"users":["github:crates-test-org:just-for-crates-2"]}"#
}

fn body_for_team_x() -> &'static str {
    r#"{"users":["github:crates-test-org:owners"]}"#
}

// Test adding team without `github:`
#[test]
fn not_github() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = r#"{"users":["dropbox:foo:foo"]}"#;
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("unknown organization"),
            "{:?}", json.errors);
}

// Test adding team without second `:`
#[test]
fn one_colon() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = r#"{"users":["github:foo"]}"#;
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("missing github team"),
            "{:?}", json.errors);
}

// Test adding team as owner when on it
#[test]
fn add_team_as_member() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));
}

// Test adding team as owner when not on in
#[test]
fn add_team_as_non_member() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_only_x());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_y();
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("only members"),
            "{:?}", json.errors);
}

// Test removing team as named owner
#[test]
fn remove_team_as_named_owner() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Delete)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new")
                                        .with_body(&body)
                                        .with_method(Method::Put)));
    assert!(json.errors[0].detail.contains("another user"),
            "{:?}", json.errors);
}

// Test removing team as team owner
#[test]
fn remove_team_as_team_owner() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = body_for_team_x();
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Delete)
                                        .with_body(body.as_bytes())));

    assert!(json.errors[0].detail.contains("don't have permission"),
            "{:?}", json.errors);

    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    ok_resp!(middle.call(req.with_path("/api/v1/crates/new")
                            .with_body(&body)
                            .with_method(Method::Put)));
}

// Test trying to publish a krate we don't own
#[test]
fn publish_not_owned() {
    let (_b, app, middle) = ::app();

    let mut req = ::new_req(app.clone(), "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_y();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new")
                                        .with_body(&body)
                                        .with_method(Method::Put)));
    assert!(json.errors[0].detail.contains("another user"),
            "{:?}", json.errors);
}

// Test trying to publish a krate we do own (but only because of teams)
#[test]
fn publish_owned() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app.clone(), "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    ok_resp!(middle.call(req.with_path("/api/v1/crates/new")
                            .with_body(&body)
                            .with_method(Method::Put)));
}

// Test trying to change owners (when only on an owning team)
#[test]
fn add_owners_as_team_owner() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app.clone(), "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = r#"{"users":["FlashCat"]}"#;     // User doesn't matter
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("don't have permission"),
            "{:?}", json.errors);
}

<commit_msg>Add a test for rejecting weird team names<commit_after>use std::sync::ONCE_INIT;
use conduit::{Handler, Method};

use cargo_registry::User;
use record::GhUser;

// Users: `crates-tester-1` and `crates-tester-2`
// Passwords: ask acrichto or gankro
// Teams: `crates-test-org:owners`, `crates-test-org:just-for-crates-2`
// tester-1 is on owners only, tester-2 is on both

static GH_USER_1: GhUser = GhUser { login: "crates-tester-1", init: ONCE_INIT };
static GH_USER_2: GhUser = GhUser { login: "crates-tester-2", init: ONCE_INIT };

fn mock_user_on_only_x() -> User { GH_USER_1.user() }
fn mock_user_on_x_and_y() -> User { GH_USER_2.user() }

fn body_for_team_y() -> &'static str {
    r#"{"users":["github:crates-test-org:just-for-crates-2"]}"#
}

fn body_for_team_x() -> &'static str {
    r#"{"users":["github:crates-test-org:owners"]}"#
}

// Test adding team without `github:`
#[test]
fn not_github() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = r#"{"users":["dropbox:foo:foo"]}"#;
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("unknown organization"),
            "{:?}", json.errors);
}

#[test]
fn weird_name() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = r#"{"users":["github:foo/../bar:wut"]}"#;
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("organization cannot contain"),
            "{:?}", json.errors);
}

// Test adding team without second `:`
#[test]
fn one_colon() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = r#"{"users":["github:foo"]}"#;
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("missing github team"),
            "{:?}", json.errors);
}

// Test adding team as owner when on it
#[test]
fn add_team_as_member() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));
}

// Test adding team as owner when not on in
#[test]
fn add_team_as_non_member() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "2.0.0");
    ::mock_user(&mut req, mock_user_on_only_x());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_y();
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("only members"),
            "{:?}", json.errors);
}

// Test removing team as named owner
#[test]
fn remove_team_as_named_owner() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Delete)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new")
                                        .with_body(&body)
                                        .with_method(Method::Put)));
    assert!(json.errors[0].detail.contains("another user"),
            "{:?}", json.errors);
}

// Test removing team as team owner
#[test]
fn remove_team_as_team_owner() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app, "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = body_for_team_x();
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Delete)
                                        .with_body(body.as_bytes())));

    assert!(json.errors[0].detail.contains("don't have permission"),
            "{:?}", json.errors);

    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    ok_resp!(middle.call(req.with_path("/api/v1/crates/new")
                            .with_body(&body)
                            .with_method(Method::Put)));
}

// Test trying to publish a krate we don't own
#[test]
fn publish_not_owned() {
    let (_b, app, middle) = ::app();

    let mut req = ::new_req(app.clone(), "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_y();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/new")
                                        .with_body(&body)
                                        .with_method(Method::Put)));
    assert!(json.errors[0].detail.contains("another user"),
            "{:?}", json.errors);
}

// Test trying to publish a krate we do own (but only because of teams)
#[test]
fn publish_owned() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app.clone(), "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = ::new_req_body(::krate("foo"), "2.0.0", vec![]);
    ok_resp!(middle.call(req.with_path("/api/v1/crates/new")
                            .with_body(&body)
                            .with_method(Method::Put)));
}

// Test trying to change owners (when only on an owning team)
#[test]
fn add_owners_as_team_owner() {
    let (_b, app, middle) = ::app();
    let mut req = ::new_req(app.clone(), "foo", "1.0.0");
    ::mock_user(&mut req, mock_user_on_x_and_y());
    ::mock_crate(&mut req, ::krate("foo"));

    let body = body_for_team_x();
    ok_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                            .with_method(Method::Put)
                            .with_body(body.as_bytes())));

    ::mock_user(&mut req, mock_user_on_only_x());
    let body = r#"{"users":["FlashCat"]}"#;     // User doesn't matter
    let json = bad_resp!(middle.call(req.with_path("/api/v1/crates/foo/owners")
                                        .with_method(Method::Put)
                                        .with_body(body.as_bytes())));
    assert!(json.errors[0].detail.contains("don't have permission"),
            "{:?}", json.errors);
}

<|endoftext|>


<commit_before>#![feature(test)]

extern crate gltile;
extern crate pixset;
extern crate test;

use test::Bencher;

#[bench]
fn bench_vertex_data_set(b: &mut Bencher) {
    let pixset = pixset::Pixset::new(100, 16);
    let size = gltile::units::Size2D::new(40, 40);
    let mut vb = gltile::VertexData::new(size, &pixset);
    let st = gltile::units::ScreenTile2D::new(0, 0);
    let tile = gltile::Tile::make(
        *gltile::colors::YELLOW,
        *gltile::colors::BLACK,
        pixset::Pix::A,
    );
    let coords = pixset.get(&tile.pix);
    b.iter(|| vb.set(st, tile, coords));
}
<commit_msg>chore(benches): remove broken bench<commit_after><|endoftext|>