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

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use byteorder::{ByteOrder, LittleEndian};

use super::*;
use hw::BusDevice;
use sys_util::{Result, EventFd, GuestAddress, GuestMemory};

const VENDOR_ID: u32 = 0;

const MMIO_MAGIC_VALUE: u32 = 0x74726976;
const MMIO_VERSION: u32 = 2;

/// Trait for virtio devices to be driven by a virtio transport.
///
/// The lifecycle of a virtio device is to be moved to a virtio transport, which will then query the
/// device. Once the guest driver has configured the device, `VirtioDevice::activate` will be called
/// and all the events, memory, and queues for device operation will be moved into the device.
/// Optionally, a virtio device can implement device reset in which it returns said resources and
/// resets its internal.
pub trait VirtioDevice: Send {
    /// The virtio device type.
    fn device_type(&self) -> u32;

    /// The maximum size of each queue that this device supports.
    fn queue_max_sizes(&self) -> &[u16];

    /// The set of feature bits shifted by `page * 32`.
    fn features(&self, page: u32) -> u32 {
        let _ = page;
        0
    }

    /// Acknowledges that this set of features should be enabled.
    fn ack_features(&mut self, page: u32, value: u32) {
        let _ = page;
        let _ = value;
    }

    /// Reads this device configuration space at `offset`.
    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Writes to this device configuration space at `offset`.
    fn write_config(&mut self, offset: u64, data: &[u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Activates this device for real usage.
    fn activate(&mut self,
                mem: GuestMemory,
                interrupt_evt: EventFd,
                status: Arc<AtomicUsize>,
                queues: Vec<Queue>,
                queue_evts: Vec<EventFd>);

    /// Optionally deactivates this device and returns ownership of the guest memory map, interrupt
    /// event, and queue events.
    fn reset(&mut self) -> Option<(EventFd, Vec<EventFd>)> {
        None
    }
}

/// Implements the
/// [MMIO](http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-1090002)
/// transport for virtio devices.
///
/// This requires 3 points of installation to work with a VM:
///
/// 1. Mmio reads and writes must be sent to this device at what is referred to here as MMIO base.
/// 1. `Mmio::queue_evts` must be installed at `hw::virtio::NOITFY_REG_OFFSET` offset from the MMIO
/// base. Each event in the array must be signaled if the index is written at that offset.
/// 1. `Mmio::interrupt_evt` must signal an interrupt that the guest driver is listening to when it
/// is written to.
///
/// Typically one page (4096 bytes) of MMIO address space is sufficient to handle this transport
/// and inner virtio device.
pub struct MmioDevice {
    device: Box<VirtioDevice>,
    device_activated: bool,

    features_select: u32,
    acked_features_select: u32,
    queue_select: u32,
    interrupt_status: Arc<AtomicUsize>,
    interrupt_evt: Option<EventFd>,
    driver_status: u32,
    config_generation: u32,
    queues: Vec<Queue>,
    queue_evts: Vec<EventFd>,
    mem: Option<GuestMemory>,
}

impl MmioDevice {
    /// Constructs a new MMIO transport for the given virtio device.
    pub fn new(mem: GuestMemory, device: Box<VirtioDevice>) -> Result<MmioDevice> {
        let mut queue_evts = Vec::new();
        for _ in device.queue_max_sizes().iter() {
            queue_evts.push(EventFd::new()?)
        }
        let queues = device
            .queue_max_sizes()
            .iter()
            .map(|&s| Queue::new(s))
            .collect();
        Ok(MmioDevice {
               device: device,
               device_activated: false,
               features_select: 0,
               acked_features_select: 0,
               queue_select: 0,
               interrupt_status: Arc::new(AtomicUsize::new(0)),
               interrupt_evt: Some(EventFd::new()?),
               driver_status: 0,
               config_generation: 0,
               queues: queues,
               queue_evts: queue_evts,
               mem: Some(mem),
           })
    }

    /// Gets the list of queue events that must be triggered whenever the VM writes to
    /// `hw::virtio::NOITFY_REG_OFFSET` past the MMIO base. Each event must be triggered when the
    /// value being written equals the index of the event in this list.
    pub fn queue_evts(&self) -> &[EventFd] {
        self.queue_evts.as_slice()
    }

    /// Gets the event this device uses to interrupt the VM when the used queue is changed.
    pub fn interrupt_evt(&self) -> Option<&EventFd> {
        self.interrupt_evt.as_ref()
    }

    fn is_driver_ready(&self) -> bool {
        let ready_bits = DEVICE_ACKNOWLEDGE | DEVICE_DRIVER | DEVICE_DRIVER_OK | DEVICE_FEATURES_OK;
        self.driver_status == ready_bits && self.driver_status & DEVICE_FAILED == 0
    }

    fn with_queue<U, F>(&self, d: U, f: F) -> U
        where F: FnOnce(&Queue) -> U
    {
        match self.queues.get(self.queue_select as usize) {
            Some(queue) => f(queue),
            None => d,
        }
    }

    fn with_queue_mut<F: FnOnce(&mut Queue)>(&mut self, f: F) -> bool {
        if let Some(queue) = self.queues.get_mut(self.queue_select as usize) {
            f(queue);
            true
        } else {
            false
        }
    }
}

impl BusDevice for MmioDevice {
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        if data.len() != 4 {
            println!("invalid virtio mmio read of size {}", data.len());
            return;
        }

        let v = match offset {
            0x0 => MMIO_MAGIC_VALUE,
            0x004 => MMIO_VERSION,
            0x008 => self.device.device_type(),
            0x00c => VENDOR_ID, // vendor id
            0x010 => {
                self.device.features(self.features_select) |
                if self.features_select == 1 { 0x1 } else { 0x0 }
            }
            0x034 => self.with_queue(0, |q| q.max_size as u32),
            0x044 => self.with_queue(0, |q| q.ready as u32),
            0x060 => self.interrupt_status.load(Ordering::SeqCst) as u32,
            0x070 => self.driver_status,
            0x0fc => self.config_generation,
            o @ 0x100...0xfff if o % 4 == 0 => return self.device.read_config(offset - 0x100, data),
            _ => {
                println!("unknown virtio mmio read: 0x{:x}", offset);
                0
            }
        };

        LittleEndian::write_u32(data, v);
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        fn hi(v: &mut GuestAddress, x: u32) {
            *v = (*v & 0xffffffff) | ((x as u64) << 32)
        }

        fn lo(v: &mut GuestAddress, x: u32) {
            *v = (*v & !0xffffffff) | (x as u64)
        }

        if data.len() != 4 {
            println!("invalid virtio mmio write of size {}", data.len());
            return;
        }

        let mut mut_q = false;
        let v = LittleEndian::read_u32(data);
        match offset {
            0x014 => self.features_select = v,
            0x020 => self.device.ack_features(v, self.acked_features_select),
            0x024 => self.acked_features_select = v,
            0x030 => self.queue_select = v,
            0x038 => mut_q = self.with_queue_mut(|q| q.size = v as u16),
            0x044 => mut_q = self.with_queue_mut(|q| q.ready = v == 1),
            0x050 => println!("received unexpected virtio queue notification via mmio write"),
            0x064 => {
                self.interrupt_status
                    .fetch_and(!(v as usize), Ordering::SeqCst);
            }
            0x070 => self.driver_status = v,
            0x080 => mut_q = self.with_queue_mut(|q| lo(&mut q.desc_table, v)),
            0x084 => mut_q = self.with_queue_mut(|q| hi(&mut q.desc_table, v)),
            0x090 => mut_q = self.with_queue_mut(|q| lo(&mut q.avail_ring, v)),
            0x094 => mut_q = self.with_queue_mut(|q| hi(&mut q.avail_ring, v)),
            0x0a0 => mut_q = self.with_queue_mut(|q| lo(&mut q.used_ring, v)),
            0x0a4 => mut_q = self.with_queue_mut(|q| hi(&mut q.used_ring, v)),
            o @ 0x100...0xfff if o % 4 == 0 => self.device.write_config(offset - 0x100, data),
            _ => {
                println!("unknown mmio write: 0x{:x} = {}", offset, v);
            }
        }

        if self.device_activated && mut_q {
            println!("warning: virtio queue was changed after device was activated");
        }

        if !self.device_activated && self.is_driver_ready() {
            if let Some(interrupt_evt) = self.interrupt_evt.take() {
                if let Some(mem) = self.mem.take() {
                    self.device
                        .activate(mem,
                                  interrupt_evt,
                                  self.interrupt_status.clone(),
                                  self.queues.clone(),
                                  self.queue_evts.split_off(0));
                    self.device_activated = true;
                }
            }
        }
    }
}
<commit_msg>crosvm: fix ordering of args for ack_features<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use byteorder::{ByteOrder, LittleEndian};

use super::*;
use hw::BusDevice;
use sys_util::{Result, EventFd, GuestAddress, GuestMemory};

const VENDOR_ID: u32 = 0;

const MMIO_MAGIC_VALUE: u32 = 0x74726976;
const MMIO_VERSION: u32 = 2;

/// Trait for virtio devices to be driven by a virtio transport.
///
/// The lifecycle of a virtio device is to be moved to a virtio transport, which will then query the
/// device. Once the guest driver has configured the device, `VirtioDevice::activate` will be called
/// and all the events, memory, and queues for device operation will be moved into the device.
/// Optionally, a virtio device can implement device reset in which it returns said resources and
/// resets its internal.
pub trait VirtioDevice: Send {
    /// The virtio device type.
    fn device_type(&self) -> u32;

    /// The maximum size of each queue that this device supports.
    fn queue_max_sizes(&self) -> &[u16];

    /// The set of feature bits shifted by `page * 32`.
    fn features(&self, page: u32) -> u32 {
        let _ = page;
        0
    }

    /// Acknowledges that this set of features should be enabled.
    fn ack_features(&mut self, page: u32, value: u32) {
        let _ = page;
        let _ = value;
    }

    /// Reads this device configuration space at `offset`.
    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Writes to this device configuration space at `offset`.
    fn write_config(&mut self, offset: u64, data: &[u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Activates this device for real usage.
    fn activate(&mut self,
                mem: GuestMemory,
                interrupt_evt: EventFd,
                status: Arc<AtomicUsize>,
                queues: Vec<Queue>,
                queue_evts: Vec<EventFd>);

    /// Optionally deactivates this device and returns ownership of the guest memory map, interrupt
    /// event, and queue events.
    fn reset(&mut self) -> Option<(EventFd, Vec<EventFd>)> {
        None
    }
}

/// Implements the
/// [MMIO](http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-1090002)
/// transport for virtio devices.
///
/// This requires 3 points of installation to work with a VM:
///
/// 1. Mmio reads and writes must be sent to this device at what is referred to here as MMIO base.
/// 1. `Mmio::queue_evts` must be installed at `hw::virtio::NOITFY_REG_OFFSET` offset from the MMIO
/// base. Each event in the array must be signaled if the index is written at that offset.
/// 1. `Mmio::interrupt_evt` must signal an interrupt that the guest driver is listening to when it
/// is written to.
///
/// Typically one page (4096 bytes) of MMIO address space is sufficient to handle this transport
/// and inner virtio device.
pub struct MmioDevice {
    device: Box<VirtioDevice>,
    device_activated: bool,

    features_select: u32,
    acked_features_select: u32,
    queue_select: u32,
    interrupt_status: Arc<AtomicUsize>,
    interrupt_evt: Option<EventFd>,
    driver_status: u32,
    config_generation: u32,
    queues: Vec<Queue>,
    queue_evts: Vec<EventFd>,
    mem: Option<GuestMemory>,
}

impl MmioDevice {
    /// Constructs a new MMIO transport for the given virtio device.
    pub fn new(mem: GuestMemory, device: Box<VirtioDevice>) -> Result<MmioDevice> {
        let mut queue_evts = Vec::new();
        for _ in device.queue_max_sizes().iter() {
            queue_evts.push(EventFd::new()?)
        }
        let queues = device
            .queue_max_sizes()
            .iter()
            .map(|&s| Queue::new(s))
            .collect();
        Ok(MmioDevice {
               device: device,
               device_activated: false,
               features_select: 0,
               acked_features_select: 0,
               queue_select: 0,
               interrupt_status: Arc::new(AtomicUsize::new(0)),
               interrupt_evt: Some(EventFd::new()?),
               driver_status: 0,
               config_generation: 0,
               queues: queues,
               queue_evts: queue_evts,
               mem: Some(mem),
           })
    }

    /// Gets the list of queue events that must be triggered whenever the VM writes to
    /// `hw::virtio::NOITFY_REG_OFFSET` past the MMIO base. Each event must be triggered when the
    /// value being written equals the index of the event in this list.
    pub fn queue_evts(&self) -> &[EventFd] {
        self.queue_evts.as_slice()
    }

    /// Gets the event this device uses to interrupt the VM when the used queue is changed.
    pub fn interrupt_evt(&self) -> Option<&EventFd> {
        self.interrupt_evt.as_ref()
    }

    fn is_driver_ready(&self) -> bool {
        let ready_bits = DEVICE_ACKNOWLEDGE | DEVICE_DRIVER | DEVICE_DRIVER_OK | DEVICE_FEATURES_OK;
        self.driver_status == ready_bits && self.driver_status & DEVICE_FAILED == 0
    }

    fn with_queue<U, F>(&self, d: U, f: F) -> U
        where F: FnOnce(&Queue) -> U
    {
        match self.queues.get(self.queue_select as usize) {
            Some(queue) => f(queue),
            None => d,
        }
    }

    fn with_queue_mut<F: FnOnce(&mut Queue)>(&mut self, f: F) -> bool {
        if let Some(queue) = self.queues.get_mut(self.queue_select as usize) {
            f(queue);
            true
        } else {
            false
        }
    }
}

impl BusDevice for MmioDevice {
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        if data.len() != 4 {
            println!("invalid virtio mmio read of size {}", data.len());
            return;
        }

        let v = match offset {
            0x0 => MMIO_MAGIC_VALUE,
            0x004 => MMIO_VERSION,
            0x008 => self.device.device_type(),
            0x00c => VENDOR_ID, // vendor id
            0x010 => {
                self.device.features(self.features_select) |
                if self.features_select == 1 { 0x1 } else { 0x0 }
            }
            0x034 => self.with_queue(0, |q| q.max_size as u32),
            0x044 => self.with_queue(0, |q| q.ready as u32),
            0x060 => self.interrupt_status.load(Ordering::SeqCst) as u32,
            0x070 => self.driver_status,
            0x0fc => self.config_generation,
            o @ 0x100...0xfff if o % 4 == 0 => return self.device.read_config(offset - 0x100, data),
            _ => {
                println!("unknown virtio mmio read: 0x{:x}", offset);
                0
            }
        };

        LittleEndian::write_u32(data, v);
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        fn hi(v: &mut GuestAddress, x: u32) {
            *v = (*v & 0xffffffff) | ((x as u64) << 32)
        }

        fn lo(v: &mut GuestAddress, x: u32) {
            *v = (*v & !0xffffffff) | (x as u64)
        }

        if data.len() != 4 {
            println!("invalid virtio mmio write of size {}", data.len());
            return;
        }

        let mut mut_q = false;
        let v = LittleEndian::read_u32(data);
        match offset {
            0x014 => self.features_select = v,
            0x020 => self.device.ack_features(self.acked_features_select, v),
            0x024 => self.acked_features_select = v,
            0x030 => self.queue_select = v,
            0x038 => mut_q = self.with_queue_mut(|q| q.size = v as u16),
            0x044 => mut_q = self.with_queue_mut(|q| q.ready = v == 1),
            0x050 => println!("received unexpected virtio queue notification via mmio write"),
            0x064 => {
                self.interrupt_status
                    .fetch_and(!(v as usize), Ordering::SeqCst);
            }
            0x070 => self.driver_status = v,
            0x080 => mut_q = self.with_queue_mut(|q| lo(&mut q.desc_table, v)),
            0x084 => mut_q = self.with_queue_mut(|q| hi(&mut q.desc_table, v)),
            0x090 => mut_q = self.with_queue_mut(|q| lo(&mut q.avail_ring, v)),
            0x094 => mut_q = self.with_queue_mut(|q| hi(&mut q.avail_ring, v)),
            0x0a0 => mut_q = self.with_queue_mut(|q| lo(&mut q.used_ring, v)),
            0x0a4 => mut_q = self.with_queue_mut(|q| hi(&mut q.used_ring, v)),
            o @ 0x100...0xfff if o % 4 == 0 => self.device.write_config(offset - 0x100, data),
            _ => {
                println!("unknown mmio write: 0x{:x} = {}", offset, v);
            }
        }

        if self.device_activated && mut_q {
            println!("warning: virtio queue was changed after device was activated");
        }

        if !self.device_activated && self.is_driver_ready() {
            if let Some(interrupt_evt) = self.interrupt_evt.take() {
                if let Some(mem) = self.mem.take() {
                    self.device
                        .activate(mem,
                                  interrupt_evt,
                                  self.interrupt_status.clone(),
                                  self.queues.clone(),
                                  self.queue_evts.split_off(0));
                    self.device_activated = true;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn run_mode(dir: &'static str, mode: &'static str, sysroot: &str) {
    // Disable rustc's new error fomatting. It breaks these tests.
    std::env::remove_var("RUST_NEW_ERROR_FORMAT");
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = mode.parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from(format!("tests/{}", dir));
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for target in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let target = target.unwrap();
        if !target.metadata().unwrap().is_dir() {
            continue;
        }
        let target = target.file_name().into_string().unwrap();
        if target == "etc" {
            continue;
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    run_mode("compile-fail", "compile-fail", &sysroot);
    for_all_targets(&sysroot, |target| {
        for file in std::fs::read_dir("tests/run-pass").unwrap() {
            let file = file.unwrap();
            if !file.metadata().unwrap().is_file() {
                continue;
            }
            let file = file.path();
            let stderr = std::io::stderr();
            write!(stderr.lock(), "test [miri-pass] {} ", file.to_str().unwrap()).unwrap();
            let mut cmd = std::process::Command::new("target/debug/miri");
            cmd.arg(file);
            cmd.arg("-Dwarnings");
            cmd.arg(format!("--target={}", target));
            let libs = Path::new(&sysroot).join("lib");
            let sysroot = libs.join("rustlib").join(&target).join("lib");
            let paths = std::env::join_paths(&[libs, sysroot]).unwrap();
            cmd.env(compiletest::procsrv::dylib_env_var(), paths);
            match cmd.output() {
                Ok(ref output) if output.status.success() => writeln!(stderr.lock(), "ok").unwrap(),
                Ok(output) => {
                    writeln!(stderr.lock(), "FAILED with exit code {}", output.status.code().unwrap_or(0)).unwrap();
                    writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
                    writeln!(stderr.lock(), "stderr: \n {}", std::str::from_utf8(&output.stderr).unwrap()).unwrap();
                    panic!("some tests failed");
                }
                Err(e) => {
                    writeln!(stderr.lock(), "FAILED: {}", e).unwrap();
                    panic!("some tests failed");
                },
            }
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "").unwrap();
    });
}
<commit_msg>run the *compiled* run-pass tests on the host machine<commit_after>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &str) {
    // Disable rustc's new error fomatting. It breaks these tests.
    std::env::remove_var("RUST_NEW_ERROR_FORMAT");
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    // Disable rustc's new error fomatting. It breaks these tests.
    std::env::remove_var("RUST_NEW_ERROR_FORMAT");
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    compiletest::run_tests(&config);
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for target in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let target = target.unwrap();
        if !target.metadata().unwrap().is_dir() {
            continue;
        }
        let target = target.file_name().into_string().unwrap();
        if target == "etc" {
            continue;
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    compile_fail(&sysroot);
    run_pass();
    for_all_targets(&sysroot, |target| {
        for file in std::fs::read_dir("tests/run-pass").unwrap() {
            let file = file.unwrap();
            if !file.metadata().unwrap().is_file() {
                continue;
            }
            let file = file.path();
            let stderr = std::io::stderr();
            write!(stderr.lock(), "test [miri-pass] {} ", file.to_str().unwrap()).unwrap();
            let mut cmd = std::process::Command::new("target/debug/miri");
            cmd.arg(file);
            cmd.arg("-Dwarnings");
            cmd.arg(format!("--target={}", target));
            let libs = Path::new(&sysroot).join("lib");
            let sysroot = libs.join("rustlib").join(&target).join("lib");
            let paths = std::env::join_paths(&[libs, sysroot]).unwrap();
            cmd.env(compiletest::procsrv::dylib_env_var(), paths);
            match cmd.output() {
                Ok(ref output) if output.status.success() => writeln!(stderr.lock(), "ok").unwrap(),
                Ok(output) => {
                    writeln!(stderr.lock(), "FAILED with exit code {}", output.status.code().unwrap_or(0)).unwrap();
                    writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
                    writeln!(stderr.lock(), "stderr: \n {}", std::str::from_utf8(&output.stderr).unwrap()).unwrap();
                    panic!("some tests failed");
                }
                Err(e) => {
                    writeln!(stderr.lock(), "FAILED: {}", e).unwrap();
                    panic!("some tests failed");
                },
            }
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "").unwrap();
    });
}
<|endoftext|>


<commit_before>extern crate id_tree;

use id_tree::NodeIdError;
use id_tree::Node;
use id_tree::TreeBuilder;
use id_tree::Tree;
use id_tree::RemoveBehavior;
use id_tree::MoveBehavior;
use id_tree::InsertBehavior;
use id_tree::SwapBehavior;

#[test]
fn test_old_node_id() {
    let mut tree: Tree<i32> = TreeBuilder::new().build();

    let root_node = Node::new(1);

    let root_id = tree.insert(root_node, InsertBehavior::AsRoot).ok().unwrap();
    let root_id_copy = root_id.clone(); // this is essential to getting the Result::Err()

    let root_node = tree.remove_node(root_id, RemoveBehavior::OrphanChildren);
    assert!(root_node.is_ok());

    let root_node_again = tree.remove_node(root_id_copy, RemoveBehavior::OrphanChildren);
    assert!(root_node_again.is_err());

    let error = root_node_again.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_get_node_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_a = tree_a.get(&root_node_id_a);
    let root_node_b = tree_b.get(&root_node_id_a); //note use of wrong tree

    assert!(root_node_a.is_ok());
    assert!(root_node_b.is_err());
    assert_eq!(root_node_b.err().unwrap(),
               NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_get_mut_node_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_a = tree_a.get_mut(&root_node_id_a);
    let root_node_b = tree_b.get_mut(&root_node_id_a); //note use of wrong tree

    assert!(root_node_a.is_ok());
    assert!(root_node_b.is_err());
    assert_eq!(root_node_b.err().unwrap(),
               NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_remove_node_lift_children_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_id_a = tree_a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note use of wrong tree
    let root_node_b = tree_b.remove_node(root_node_id_a, RemoveBehavior::LiftChildren);
    assert!(root_node_b.is_err());

    let error = root_node_b.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_remove_node_orphan_children_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_id_a = tree_a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note use of wrong tree
    let root_node_b = tree_b.remove_node(root_node_id_a, RemoveBehavior::OrphanChildren);
    assert!(root_node_b.is_err());

    let error = root_node_b.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_remove_node_remove_children_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_id_a = tree_a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note use of wrong tree
    let root_node_b = tree_b.remove_node(root_node_id_a, RemoveBehavior::DropChildren);
    assert!(root_node_b.is_err());

    let error = root_node_b.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_move_node_into_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    // note use of invalid parent
    let result = tree_a.move_node(&root_node_id_a, MoveBehavior::ToParent(&root_node_id_b));
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_move_node_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    // note use of invalid child
    let result = tree_a.move_node(&root_node_id_b, MoveBehavior::ToParent(&root_node_id_a));
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_move_node_to_root_by_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.move_node(&root_node_id_b, MoveBehavior::ToRoot);
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_sort_by_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.sort_children_by(&root_node_id_b, |a, b| a.data().cmp(b.data()));
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_sort_by_data_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.sort_children_by_data(&root_node_id_b);
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_sort_by_key_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.sort_children_by_key(&root_node_id_b, |x| x.data().clone());
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_swap_sub_trees_of_different_trees() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    // note use of invalid child
    let result = tree_a.swap_nodes(&root_node_id_b, &root_node_id_a, SwapBehavior::TakeChildren);
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_ancestors_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.ancestors(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_ancestors_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.ancestors(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_ancestor_ids_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.ancestor_ids(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_ancestor_ids_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.ancestor_ids(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_children_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.children(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_children_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.children(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_children_ids_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.children_ids(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_children_ids_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.children_ids(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}
<commit_msg>get rid of clone on copy type<commit_after>extern crate id_tree;

use id_tree::NodeIdError;
use id_tree::Node;
use id_tree::TreeBuilder;
use id_tree::Tree;
use id_tree::RemoveBehavior;
use id_tree::MoveBehavior;
use id_tree::InsertBehavior;
use id_tree::SwapBehavior;

#[test]
fn test_old_node_id() {
    let mut tree: Tree<i32> = TreeBuilder::new().build();

    let root_node = Node::new(1);

    let root_id = tree.insert(root_node, InsertBehavior::AsRoot).ok().unwrap();
    let root_id_copy = root_id.clone(); // this is essential to getting the Result::Err()

    let root_node = tree.remove_node(root_id, RemoveBehavior::OrphanChildren);
    assert!(root_node.is_ok());

    let root_node_again = tree.remove_node(root_id_copy, RemoveBehavior::OrphanChildren);
    assert!(root_node_again.is_err());

    let error = root_node_again.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_get_node_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_a = tree_a.get(&root_node_id_a);
    let root_node_b = tree_b.get(&root_node_id_a); //note use of wrong tree

    assert!(root_node_a.is_ok());
    assert!(root_node_b.is_err());
    assert_eq!(root_node_b.err().unwrap(),
               NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_get_mut_node_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_a = tree_a.get_mut(&root_node_id_a);
    let root_node_b = tree_b.get_mut(&root_node_id_a); //note use of wrong tree

    assert!(root_node_a.is_ok());
    assert!(root_node_b.is_err());
    assert_eq!(root_node_b.err().unwrap(),
               NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_remove_node_lift_children_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_id_a = tree_a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note use of wrong tree
    let root_node_b = tree_b.remove_node(root_node_id_a, RemoveBehavior::LiftChildren);
    assert!(root_node_b.is_err());

    let error = root_node_b.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_remove_node_orphan_children_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_id_a = tree_a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note use of wrong tree
    let root_node_b = tree_b.remove_node(root_node_id_a, RemoveBehavior::OrphanChildren);
    assert!(root_node_b.is_err());

    let error = root_node_b.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_remove_node_remove_children_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_id_a = tree_a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note use of wrong tree
    let root_node_b = tree_b.remove_node(root_node_id_a, RemoveBehavior::DropChildren);
    assert!(root_node_b.is_err());

    let error = root_node_b.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_move_node_into_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    // note use of invalid parent
    let result = tree_a.move_node(&root_node_id_a, MoveBehavior::ToParent(&root_node_id_b));
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_move_node_from_other_tree() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    // note use of invalid child
    let result = tree_a.move_node(&root_node_id_b, MoveBehavior::ToParent(&root_node_id_a));
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_move_node_to_root_by_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.move_node(&root_node_id_b, MoveBehavior::ToRoot);
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_sort_by_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.sort_children_by(&root_node_id_b, |a, b| a.data().cmp(b.data()));
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_sort_by_data_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.sort_children_by_data(&root_node_id_b);
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_sort_by_key_invalid_id() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let _ = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    let result = tree_a.sort_children_by_key(&root_node_id_b, |x| *x.data());
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_swap_sub_trees_of_different_trees() {
    let mut tree_a: Tree<i32> = TreeBuilder::new().build();
    let mut tree_b: Tree<i32> = TreeBuilder::new().build();

    let root_node_a = Node::new(1);
    let root_node_id_a = tree_a.insert(root_node_a, InsertBehavior::AsRoot).unwrap();

    let root_node_b = Node::new(1);
    let root_node_id_b = tree_b.insert(root_node_b, InsertBehavior::AsRoot).unwrap();

    // note use of invalid child
    let result = tree_a.swap_nodes(&root_node_id_b, &root_node_id_a, SwapBehavior::TakeChildren);
    assert!(result.is_err());

    let error = result.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_ancestors_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.ancestors(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_ancestors_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.ancestors(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_ancestor_ids_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.ancestor_ids(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_ancestor_ids_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.ancestor_ids(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_children_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.children(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_children_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.children(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}

#[test]
fn test_children_ids_different_trees() {
    let mut a = Tree::new();
    let b = Tree::<i32>::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();

    // note usage of `b` instead of `a`
    let ancestors = b.children_ids(&root_id);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::InvalidNodeIdForTree);
}

#[test]
fn test_children_ids_old_id() {
    let mut a = Tree::new();

    let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap();
    // `.clone()` required to get this error
    let root_id_clone = root_id.clone();
    let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap();

    // note usage of cloned `NodeId`
    let ancestors = a.children_ids(&root_id_clone);

    assert!(ancestors.is_err());
    let error = ancestors.err().unwrap();
    assert_eq!(error, NodeIdError::NodeIdNoLongerValid);
}
<|endoftext|>


<commit_before>extern crate thoughtfuck;

mod common;

#[test]
fn hello_world () {
    common::test_output("./tests/hello.b", "./tests/hello.txt");
}

#[test]
fn sierpinski () {
    common::test_output("./tests/sierpinski.b", "./tests/sierpinski.txt");
}
<commit_msg>Add integration test for print_brainfuck file pair<commit_after>extern crate thoughtfuck;

mod common;

#[test]
fn hello_world () {
    common::test_output("./tests/hello.b", "./tests/hello.txt");
}

#[test]
fn sierpinski () {
    common::test_output("./tests/sierpinski.b", "./tests/sierpinski.txt");
}

#[test]
fn print_brainfuck () {
    common::test_output("./tests/print_brainfuck.b", "./tests/print_brainfuck.txt");
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate claxon;
extern crate hound;

use std::fs;
use std::io;
use std::path;

fn run_metaflac(fname: &path::Path) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
                     .arg("--show-min-blocksize")
                     .arg("--show-max-blocksize")
                     .arg("--show-min-framesize")
                     .arg("--show-max-framesize")
                     .arg("--show-sample-rate")
                     .arg("--show-channels")
                     .arg("--show-bps")
                     .arg("--show-total-samples")
                     .arg("--show-md5sum")
                     .arg(fname.to_str().expect("unsupported filename"))
                     .output()
                     .expect("failed to run metaflac");
    String::from_utf8(output.stdout).expect("metaflac wrote invalid UTF-8")
}

fn decode_file(fname: &path::Path) {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let success = Command::new("flac")
                      .arg("--decode")
                      .arg("--silent")
                      .arg(fname.to_str().expect("unsupported filename"))
                      .status()
                      .expect("failed to run flac")
                      .success();
    assert!(success);
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo(fname: &path::Path) -> String {
    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = claxon::FlacReader::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac(fname: &path::Path) {
    let metaflac = run_metaflac(fname);
    let streaminfo = read_streaminfo(fname);
    let mut mf_lines = metaflac.lines();
    let mut si_lines = streaminfo.lines();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    }
}

fn compare_decoded_stream(fname: &path::Path) {
    let ref_fname = fname.with_extension("wav");
    if !ref_fname.exists() {
        // TODO: actually, we might only want to run the test for files that
        // do exist already. It is fine to run streaminfo or decode-only tests
        // on thousands of files, but decoding thousands of files to wav before
        // running the tests will take a lot of space. For now, while the
        // number of samples is closer to 10 than to 100, this is fine.
        decode_file(fname);
    }

    // If the reference file does exist after decoding, we can compare it to
    // how Claxon decodes it, sample by sample.
    if ref_fname.exists() {
        let mut ref_wav_reader = hound::WavReader::open(ref_fname).unwrap();

        let try_file = fs::File::open(fname).unwrap();
        let try_buf_reader = io::BufReader::new(try_file);
        let mut try_flac_reader = claxon::FlacReader::new(try_buf_reader).unwrap();

        // The streaminfo test will ensure that things like bit depth and
        // sample rate match, only the actual samples are compared here.

        let mut ref_samples = ref_wav_reader.samples::<i32>();

        let samples = try_flac_reader.streaminfo().samples.unwrap();
        let n_channels = try_flac_reader.streaminfo().channels;
        let mut blocks = try_flac_reader.blocks();
        let mut sample = 0u64;
        let mut b = 0u64;
        let mut buffer = Vec::new();

        while sample < samples {
            let block = blocks.read_next_or_eof(buffer).unwrap().unwrap();
            {
                let mut channels: Vec<_> = (0..n_channels)
                                               .map(|i| block.channel(i).iter().cloned())
                                               .collect();
                for i in 0..block.len() {
                    for ch in 0..n_channels as usize {
                        let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                        let try_sample = channels[ch].next();
                        if ref_sample != try_sample {
                            println!("disagreement at sample {} of block {} in channel {}: \
                                      reference is {} but decoded is {}",
                                     i,
                                     b,
                                     ch,
                                     ref_sample.unwrap(),
                                     try_sample.unwrap());
                            panic!("decoding differs from reference decoder");
                        }
                    }
                }
                sample = sample + block.len() as u64;
            }
            b = b + 1;
            buffer = block.into_buffer();
        }
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac(path::Path::new("testsamples/p4.flac"));
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream(path::Path::new("testsamples/p4.flac"));
}
<commit_msg>Verify benchmark samples in tests for now<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate claxon;
extern crate hound;

use std::fs;
use std::io;
use std::path::Path;

fn run_metaflac<P: AsRef<Path>>(fname: P) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
                     .arg("--show-min-blocksize")
                     .arg("--show-max-blocksize")
                     .arg("--show-min-framesize")
                     .arg("--show-max-framesize")
                     .arg("--show-sample-rate")
                     .arg("--show-channels")
                     .arg("--show-bps")
                     .arg("--show-total-samples")
                     .arg("--show-md5sum")
                     .arg(fname.as_ref().to_str().expect("unsupported filename"))
                     .output()
                     .expect("failed to run metaflac");
    String::from_utf8(output.stdout).expect("metaflac wrote invalid UTF-8")
}

fn decode_file<P: AsRef<Path>>(fname: P) {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let success = Command::new("flac")
                      .arg("--decode")
                      .arg("--silent")
                      .arg(fname.as_ref().to_str().expect("unsupported filename"))
                      .status()
                      .expect("failed to run flac")
                      .success();
    assert!(success);
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo<P: AsRef<Path>>(fname: P) -> String {
    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = claxon::FlacReader::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac<P: AsRef<Path>>(fname: P) {
    let metaflac = run_metaflac(&fname);
    let streaminfo = read_streaminfo(&fname);
    let mut mf_lines = metaflac.lines();
    let mut si_lines = streaminfo.lines();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    }
}

fn compare_decoded_stream<P: AsRef<Path>>(fname: P) {
    let ref_fname = fname.as_ref().with_extension("wav");
    if !ref_fname.exists() {
        // TODO: actually, we might only want to run the test for files that
        // do exist already. It is fine to run streaminfo or decode-only tests
        // on thousands of files, but decoding thousands of files to wav before
        // running the tests will take a lot of space. For now, while the
        // number of samples is closer to 10 than to 100, this is fine.
        decode_file(&fname);
    }

    // If the reference file does exist after decoding, we can compare it to
    // how Claxon decodes it, sample by sample.
    if ref_fname.exists() {
        let mut ref_wav_reader = hound::WavReader::open(ref_fname).unwrap();

        let try_file = fs::File::open(fname).unwrap();
        let try_buf_reader = io::BufReader::new(try_file);
        let mut try_flac_reader = claxon::FlacReader::new(try_buf_reader).unwrap();

        // The streaminfo test will ensure that things like bit depth and
        // sample rate match, only the actual samples are compared here.

        let mut ref_samples = ref_wav_reader.samples::<i32>();

        let samples = try_flac_reader.streaminfo().samples.unwrap();
        let n_channels = try_flac_reader.streaminfo().channels;
        let mut blocks = try_flac_reader.blocks();
        let mut sample = 0u64;
        let mut b = 0u64;
        let mut buffer = Vec::new();

        while sample < samples {
            let block = blocks.read_next_or_eof(buffer).unwrap().unwrap();
            {
                let mut channels: Vec<_> = (0..n_channels)
                                               .map(|i| block.channel(i).iter().cloned())
                                               .collect();
                for i in 0..block.len() {
                    for ch in 0..n_channels as usize {
                        let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                        let try_sample = channels[ch].next();
                        if ref_sample != try_sample {
                            println!("disagreement at sample {} of block {} in channel {}: \
                                      reference is {} but decoded is {}",
                                     i,
                                     b,
                                     ch,
                                     ref_sample.unwrap(),
                                     try_sample.unwrap());
                            panic!("decoding differs from reference decoder");
                        }
                    }
                }
                sample = sample + block.len() as u64;
            }
            b = b + 1;
            buffer = block.into_buffer();
        }
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac("testsamples/p0.flac");
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac("testsamples/p1.flac");
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac("testsamples/p2.flac");
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac("testsamples/p3.flac");
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac("testsamples/p4.flac");
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream("testsamples/p0.flac");
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream("testsamples/p1.flac");
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream("testsamples/p2.flac");
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream("testsamples/p3.flac");
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream("testsamples/p4.flac");
}

#[test]
fn verify_decoded_stream_b0() {
    compare_decoded_stream("testsamples/b0_daft_punk_one_more_time.flac");
}

#[test]
fn verify_decoded_stream_b1() {
    compare_decoded_stream("testsamples/b1_deadmau5_i_remember.flac");
}

#[test]
fn verify_decoded_stream_b2() {
    compare_decoded_stream("testsamples/b2_massive_attack_unfinished_sympathy.flac");
}

#[test]
fn verify_decoded_stream_b3() {
    compare_decoded_stream("testsamples/b3_muse_starlight.flac");
}

#[test]
fn verify_decoded_stream_b4() {
    compare_decoded_stream("testsamples/b4_u2_sunday_bloody_sunday.flac");
}
<|endoftext|>


<commit_before>use std;

pub type id = libc::intptr_t;
pub type Class = libc::intptr_t;
pub type IMP = *u8;
pub type SEL = libc::intptr_t;
pub type Ivar = libc::intptr_t;

pub const nil : id = 0 as id;

pub extern mod objc {
    fn class_addMethod(cls : Class,
                       name : SEL,
                       imp : IMP,
                       types : *libc::c_char) -> bool;
    fn class_addIvar(cls : Class,
                     name : *libc::c_char,
                     size : libc::size_t,
                     alignment: u8,
		             types: *libc::c_char) -> bool;
    fn object_setInstanceVariable(obj : id,
                                  name : *libc::c_char,
                                  value : *libc::c_void);
    fn object_getInstanceVariable(obj : id,
                                  name : *libc::c_char,
                                  outValue : **libc::c_void);
    fn objc_allocateClassPair(superclass : Class,
                              name : *libc::c_char,
                              extraBytes : libc::size_t) -> Class;
    fn objc_getClass(name : *libc::c_char) -> id;
    fn objc_msgSend(theReceiver : id, theSelector : SEL) -> id;
    fn objc_registerClassPair(cls : Class);
    fn sel_registerName(name : *libc::c_char) -> SEL;
}

#[test]
pub fn test_nsapp() {
    let klass = str::as_c_str(~"NSApplication", |s|
        unsafe {
            objc::objc_getClass(s)
        }
    );

    let sel = str::as_c_str(~"sharedApplication", |s|
        unsafe {
            objc::sel_registerName(s)
        }
    );

    unsafe {
        let nsapp = objc::objc_msgSend(klass, sel);
        io::println(fmt!("nsapp: %d", (nsapp as int)));
    }
}

#[test]
pub fn test_custom_obj() {
    extern fn MyObject_doSomething(this : id, _sel : SEL) -> id {
        io::println(~"doSomething");
        return this;
    }

    let NSObject = str::as_c_str(~"NSObject", |s|
        unsafe {
            objc::objc_getClass(s)
        }
    );
    let MyObject = str::as_c_str(~"MyObject", |s|
        unsafe {
            objc::objc_allocateClassPair(NSObject, s, 0 as libc::size_t)
        }
    );
    let doSomething = str::as_c_str(~"doSomething", |s|
        unsafe {
            objc::sel_registerName(s)
        }
    );
    let _ = str::as_c_str(~"@@:", |types|
        unsafe {
            objc::class_addMethod(MyObject,
                                  doSomething,
                                  MyObject_doSomething,
                                  types)
        }
    );

    unsafe {
        objc::objc_registerClassPair(MyObject);
    }

    let alloc = str::as_c_str(~"alloc", |s| unsafe { objc::sel_registerName(s) });
    let init = str::as_c_str(~"init", |s| unsafe { objc::sel_registerName(s) });

    unsafe {
        let mut obj = objc::objc_msgSend(MyObject, alloc);
        obj = objc::objc_msgSend(obj, init);
        objc::objc_msgSend(obj, doSomething);
    }
}

<commit_msg>Update to rust 0.6 and remove unused imports.<commit_after>pub type id = libc::intptr_t;
pub type Class = libc::intptr_t;
pub type IMP = *u8;
pub type SEL = libc::intptr_t;
pub type Ivar = libc::intptr_t;

pub static nil : id = 0 as id;

pub extern mod objc {
    fn class_addMethod(cls : Class,
                       name : SEL,
                       imp : IMP,
                       types : *libc::c_char) -> bool;
    fn class_addIvar(cls : Class,
                     name : *libc::c_char,
                     size : libc::size_t,
                     alignment: u8,
		             types: *libc::c_char) -> bool;
    fn object_setInstanceVariable(obj : id,
                                  name : *libc::c_char,
                                  value : *libc::c_void);
    fn object_getInstanceVariable(obj : id,
                                  name : *libc::c_char,
                                  outValue : **libc::c_void);
    fn objc_allocateClassPair(superclass : Class,
                              name : *libc::c_char,
                              extraBytes : libc::size_t) -> Class;
    fn objc_getClass(name : *libc::c_char) -> id;
    fn objc_msgSend(theReceiver : id, theSelector : SEL) -> id;
    fn objc_registerClassPair(cls : Class);
    fn sel_registerName(name : *libc::c_char) -> SEL;
}

#[test]
pub fn test_nsapp() {
    let klass = str::as_c_str(~"NSApplication", |s|
        unsafe {
            objc::objc_getClass(s)
        }
    );

    let sel = str::as_c_str(~"sharedApplication", |s|
        unsafe {
            objc::sel_registerName(s)
        }
    );

    unsafe {
        let nsapp = objc::objc_msgSend(klass, sel);
        io::println(fmt!("nsapp: %d", (nsapp as int)));
    }
}

#[test]
pub fn test_custom_obj() {
    extern fn MyObject_doSomething(this : id, _sel : SEL) -> id {
        io::println(~"doSomething");
        return this;
    }

    let NSObject = str::as_c_str(~"NSObject", |s|
        unsafe {
            objc::objc_getClass(s)
        }
    );
    let MyObject = str::as_c_str(~"MyObject", |s|
        unsafe {
            objc::objc_allocateClassPair(NSObject, s, 0 as libc::size_t)
        }
    );
    let doSomething = str::as_c_str(~"doSomething", |s|
        unsafe {
            objc::sel_registerName(s)
        }
    );
    let _ = str::as_c_str(~"@@:", |types|
        unsafe {
            objc::class_addMethod(MyObject,
                                  doSomething,
                                  MyObject_doSomething,
                                  types)
        }
    );

    unsafe {
        objc::objc_registerClassPair(MyObject);
    }

    let alloc = str::as_c_str(~"alloc", |s| unsafe { objc::sel_registerName(s) });
    let init = str::as_c_str(~"init", |s| unsafe { objc::sel_registerName(s) });

    unsafe {
        let mut obj = objc::objc_msgSend(MyObject, alloc);
        obj = objc::objc_msgSend(obj, init);
        objc::objc_msgSend(obj, doSomething);
    }
}

<|endoftext|>