<commit_before>extern crate foxbox_thinkerbell;
extern crate transformable_channels;

use foxbox_thinkerbell::parse::*;
use foxbox_thinkerbell::run::*;
use foxbox_thinkerbell::simulator::*;

use std::thread;

use transformable_channels::mpsc::*;

#[derive(Debug)]
enum Event {
    Simulator(SimulatorEvent),
    Env(ExecutionEvent),
}

#[test]
fn test_start() {
    let (tx, rx) : (_, Receiver<Event>)= channel();

    let tx_env = Box::new(tx.map(|event| Event::Simulator(event)));
    let env = TestEnv::new(tx_env);
    let mut exec = Execution::<TestEnv>::new();

    thread::spawn(move || {
        for msg in rx {
            println!("LOG: {:?}", msg)
        }
    });

    println!("* Attempting to parse an run an empty script...");
    let script = Parser::parse("{\"rules\": []}".to_owned()).unwrap();
    let tx_simulator = tx.map(|event| Event::Env(event));
    match exec.start(env, script, tx_simulator) {
        Err(Error::CompileError(CompileError::SourceError(SourceError::NoRule))) => {},
        other => panic!("Unexpected result {:?}", other)
    }
}<commit_msg>[fxbox/thinkerbell] Trivial test tweak<commit_after>extern crate foxbox_thinkerbell;
extern crate transformable_channels;

use foxbox_thinkerbell::parse::*;
use foxbox_thinkerbell::run::*;
use foxbox_thinkerbell::simulator::*;

use std::thread;

use transformable_channels::mpsc::*;

#[derive(Debug)]
enum Event {
    Simulator(SimulatorEvent),
    Env(ExecutionEvent),
}

#[test]
fn test_compile() {
    let (tx, rx) : (_, Receiver<Event>)= channel();

    let tx_env = Box::new(tx.map(|event| Event::Simulator(event)));
    let tx_simulator = tx.map(|event| Event::Env(event));

    let env = TestEnv::new(tx_env);
    let mut exec = Execution::<TestEnv>::new();

    thread::spawn(move || {
        for msg in rx {
            println!("LOG: {:?}", msg)
        }
    });

    println!("* Attempting to parse an run an empty script will raise an error.");
    let script = Parser::parse("{\"rules\": []}".to_owned()).unwrap();
    match exec.start(env, script, tx_simulator) {
        Err(Error::CompileError(CompileError::SourceError(SourceError::NoRule))) => {},
        other => panic!("Unexpected result {:?}", other)
    }

    println!("//FIXME: Attempting to parse a script with an empty condition will raise an error.");
    println!("//FIXME: Attempting to parse a script with an empty statement will raise an error.");
    println!("//FIXME: Attempting to parse a script with an empty source will raise an error.");
    println!("//FIXME: Attempting to parse a script with an empty destination will raise an error.");
    println!("//FIXME: Attempting to parse a script with a type error in a match will raise an error.");
    println!("//FIXME: Attempting to parse a script with a type error in a send will raise an error.");

}<|endoftext|>


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

use super::constants::*;
use super::evdev::{grab_evdev, ungrab_evdev};
use super::virtio_input_event;
use super::InputError;
use super::Result;
use data_model::DataInit;
use std::collections::VecDeque;
use std::io::Read;
use std::io::Write;
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, RawFd};

#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct input_event {
    timestamp_fields: [u64; 2],
    pub type_: u16,
    pub code: u16,
    pub value: u32,
}
// Safe because it only has data and has no implicit padding.
unsafe impl DataInit for input_event {}

impl input_event {
    const EVENT_SIZE: usize = size_of::<input_event>();

    fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
        input_event {
            timestamp_fields: [0, 0],
            type_: other.type_.into(),
            code: other.code.into(),
            value: other.value.into(),
        }
    }
}

/// Encapsulates a socket or device node into an abstract event source, providing a common
/// interface.
/// It supports read and write operations to provide and accept events just like an event device
/// node would, except that it handles virtio_input_event instead of input_event structures.
/// It's necessary to call receive_events() before events are available for read.
pub trait EventSource: Read + Write + AsRawFd {
    /// Perform any necessary initialization before receiving and sending events from/to the source.
    fn init(&mut self) -> Result<()> {
        Ok(())
    }
    /// Perform any necessary cleanup when the device will no longer be used.
    fn finalize(&mut self) -> Result<()> {
        Ok(())
    }

    /// Receive events from the source, filters them and stores them in a queue for future
    /// consumption by reading from this object. Returns the number of new non filtered events
    /// received. This function may block waiting for events to be available.
    fn receive_events(&mut self) -> Result<usize>;
    /// Returns the number of received events that have not been filtered or consumed yet.
    fn available_events_count(&self) -> usize;
}

// Try to read 16 events at a time to match what the linux guest driver does.
const READ_BUFFER_SIZE: usize = 16 * size_of::<input_event>();

// The read buffer needs to be aligned to the alignment of input_event, which is aligned as u64
#[repr(align(8))]
pub struct ReadBuffer {
    buffer: [u8; READ_BUFFER_SIZE],
}

/// Encapsulates implementation details common to all kinds of event sources.
pub struct EventSourceImpl<T> {
    source: T,
    queue: VecDeque<virtio_input_event>,
    read_buffer: ReadBuffer,
    // The read index accounts for incomplete events read previously.
    read_idx: usize,
}

// Reads input events from the source.
// Events are originally read as input_event structs and converted to virtio_input_event internally.
impl<T: Read> EventSourceImpl<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        let mut bytes = 0usize;
        for evt_slice in buf.chunks_exact_mut(virtio_input_event::EVENT_SIZE) {
            match self.queue.pop_front() {
                None => {
                    break;
                }
                Some(evt) => {
                    evt_slice.copy_from_slice(evt.as_slice());
                    bytes += evt_slice.len();
                }
            }
        }
        Ok(bytes)
    }
}

// Writes input events to the source.
// Events come as virtio_input_event structs and are converted to input_event internally.
impl<T: Write> EventSourceImpl<T> {
    fn write<F: Fn(&virtio_input_event) -> bool>(
        &mut self,
        buf: &[u8],
        event_filter: F,
    ) -> std::io::Result<usize> {
        for evt_slice in buf.chunks_exact(virtio_input_event::EVENT_SIZE) {
            // Don't use from_slice() here, the buffer is not guaranteed to be properly aligned.
            let mut vio_evt = virtio_input_event::new(0, 0, 0);
            vio_evt.as_mut_slice().copy_from_slice(evt_slice);
            if !event_filter(&vio_evt) {
                continue;
            }
            let evt = input_event::from_virtio_input_event(&vio_evt);
            self.source.write_all(evt.as_slice())?;
        }

        let len = buf.len() - buf.len() % virtio_input_event::EVENT_SIZE;
        Ok(len)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.source.flush()
    }
}

impl<T: AsRawFd> EventSourceImpl<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.source.as_raw_fd()
    }
}

impl<T> EventSourceImpl<T>
where
    T: Read + Write + AsRawFd,
{
    // Receive events from the source and store them in a queue, unless they should be filtered out.
    fn receive_events<F: Fn(&input_event) -> bool>(&mut self, event_filter: F) -> Result<usize> {
        let read = self
            .source
            .read(&mut self.read_buffer.buffer[self.read_idx..])
            .map_err(|e| InputError::EventsReadError(e))?;
        let buff_size = read + self.read_idx;

        for evt_slice in self.read_buffer.buffer[..buff_size].chunks_exact(input_event::EVENT_SIZE)
        {
            let input_evt = match input_event::from_slice(evt_slice) {
                Some(x) => x,
                None => {
                    // This shouldn't happen because all slices (even the last one) are guaranteed
                    // to have the correct size and be properly aligned.
                    error!(
                        "Failed converting a slice of sice {} to input_event",
                        evt_slice.len()
                    );
                    // Skipping the event here effectively means no events will be received, because
                    // if from_slice fails once it will fail always.
                    continue;
                }
            };
            if !event_filter(&input_evt) {
                continue;
            }
            let vio_evt = virtio_input_event::from_input_event(input_evt);
            self.queue.push_back(vio_evt);
        }

        let remainder = buff_size % input_event::EVENT_SIZE;
        // If there is an incomplete event at the end of the buffer, it needs to be moved to the
        // beginning and the next read operation must write right after it.
        if remainder != 0 {
            warn!("read incomplete event from source");
            // The copy should only happen if there is at least one complete event in the buffer,
            // otherwise source and destination would be the same.
            if buff_size != remainder {
                let (des, src) = self.read_buffer.buffer.split_at_mut(buff_size - remainder);
                des[..remainder].copy_from_slice(src);
            }
        }
        self.read_idx = remainder;

        let received_events = buff_size / input_event::EVENT_SIZE;

        Ok(received_events)
    }

    fn available_events(&self) -> usize {
        self.queue.len()
    }

    fn new(source: T) -> EventSourceImpl<T> {
        EventSourceImpl {
            source,
            queue: VecDeque::new(),
            read_buffer: ReadBuffer {
                buffer: [0u8; READ_BUFFER_SIZE],
            },
            read_idx: 0,
        }
    }
}

/// Encapsulates a (unix) socket as an event source.
pub struct SocketEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> SocketEventSource<T> {
        SocketEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for SocketEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |_evt| true)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for SocketEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        Ok(())
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}

/// Encapsulates an event device node as an event source
pub struct EvdevEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> EvdevEventSource<T> {
        EvdevEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for EvdevEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |evt| {
            // Miscellaneous events produced by the device are sent back to it by the kernel input
            // subsystem, but because these events are handled by the host kernel as well as the
            // guest the device would get them twice. Which would prompt the device to send the
            // event to the guest again entering an infinite loop.
            evt.type_ != EV_MSC
        })
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for EvdevEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        grab_evdev(self)
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}
<commit_msg>Add tests for virtio input device<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use super::constants::*;
use super::evdev::{grab_evdev, ungrab_evdev};
use super::virtio_input_event;
use super::InputError;
use super::Result;
use data_model::DataInit;
use std::collections::VecDeque;
use std::io::Read;
use std::io::Write;
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, RawFd};

#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct input_event {
    timestamp_fields: [u64; 2],
    pub type_: u16,
    pub code: u16,
    pub value: u32,
}
// Safe because it only has data and has no implicit padding.
unsafe impl DataInit for input_event {}

impl input_event {
    const EVENT_SIZE: usize = size_of::<input_event>();

    fn from_virtio_input_event(other: &virtio_input_event) -> input_event {
        input_event {
            timestamp_fields: [0, 0],
            type_: other.type_.into(),
            code: other.code.into(),
            value: other.value.into(),
        }
    }
}

/// Encapsulates a socket or device node into an abstract event source, providing a common
/// interface.
/// It supports read and write operations to provide and accept events just like an event device
/// node would, except that it handles virtio_input_event instead of input_event structures.
/// It's necessary to call receive_events() before events are available for read.
pub trait EventSource: Read + Write + AsRawFd {
    /// Perform any necessary initialization before receiving and sending events from/to the source.
    fn init(&mut self) -> Result<()> {
        Ok(())
    }
    /// Perform any necessary cleanup when the device will no longer be used.
    fn finalize(&mut self) -> Result<()> {
        Ok(())
    }

    /// Receive events from the source, filters them and stores them in a queue for future
    /// consumption by reading from this object. Returns the number of new non filtered events
    /// received. This function may block waiting for events to be available.
    fn receive_events(&mut self) -> Result<usize>;
    /// Returns the number of received events that have not been filtered or consumed yet.
    fn available_events_count(&self) -> usize;
}

// Try to read 16 events at a time to match what the linux guest driver does.
const READ_BUFFER_SIZE: usize = 16 * size_of::<input_event>();

// The read buffer needs to be aligned to the alignment of input_event, which is aligned as u64
#[repr(align(8))]
pub struct ReadBuffer {
    buffer: [u8; READ_BUFFER_SIZE],
}

/// Encapsulates implementation details common to all kinds of event sources.
pub struct EventSourceImpl<T> {
    source: T,
    queue: VecDeque<virtio_input_event>,
    read_buffer: ReadBuffer,
    // The read index accounts for incomplete events read previously.
    read_idx: usize,
}

// Reads input events from the source.
// Events are originally read as input_event structs and converted to virtio_input_event internally.
impl<T: Read> EventSourceImpl<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        let mut bytes = 0usize;
        for evt_slice in buf.chunks_exact_mut(virtio_input_event::EVENT_SIZE) {
            match self.queue.pop_front() {
                None => {
                    break;
                }
                Some(evt) => {
                    evt_slice.copy_from_slice(evt.as_slice());
                    bytes += evt_slice.len();
                }
            }
        }
        Ok(bytes)
    }
}

// Writes input events to the source.
// Events come as virtio_input_event structs and are converted to input_event internally.
impl<T: Write> EventSourceImpl<T> {
    fn write<F: Fn(&virtio_input_event) -> bool>(
        &mut self,
        buf: &[u8],
        event_filter: F,
    ) -> std::io::Result<usize> {
        for evt_slice in buf.chunks_exact(virtio_input_event::EVENT_SIZE) {
            // Don't use from_slice() here, the buffer is not guaranteed to be properly aligned.
            let mut vio_evt = virtio_input_event::new(0, 0, 0);
            vio_evt.as_mut_slice().copy_from_slice(evt_slice);
            if !event_filter(&vio_evt) {
                continue;
            }
            let evt = input_event::from_virtio_input_event(&vio_evt);
            self.source.write_all(evt.as_slice())?;
        }

        let len = buf.len() - buf.len() % virtio_input_event::EVENT_SIZE;
        Ok(len)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.source.flush()
    }
}

impl<T: AsRawFd> EventSourceImpl<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.source.as_raw_fd()
    }
}

impl<T> EventSourceImpl<T>
where
    T: Read + Write,
{
    // Receive events from the source and store them in a queue, unless they should be filtered out.
    fn receive_events<F: Fn(&input_event) -> bool>(&mut self, event_filter: F) -> Result<usize> {
        let read = self
            .source
            .read(&mut self.read_buffer.buffer[self.read_idx..])
            .map_err(|e| InputError::EventsReadError(e))?;
        let buff_size = read + self.read_idx;

        for evt_slice in self.read_buffer.buffer[..buff_size].chunks_exact(input_event::EVENT_SIZE)
        {
            let input_evt = match input_event::from_slice(evt_slice) {
                Some(x) => x,
                None => {
                    // This shouldn't happen because all slices (even the last one) are guaranteed
                    // to have the correct size and be properly aligned.
                    error!(
                        "Failed converting a slice of sice {} to input_event",
                        evt_slice.len()
                    );
                    // Skipping the event here effectively means no events will be received, because
                    // if from_slice fails once it will fail always.
                    continue;
                }
            };
            if !event_filter(&input_evt) {
                continue;
            }
            let vio_evt = virtio_input_event::from_input_event(input_evt);
            self.queue.push_back(vio_evt);
        }

        let remainder = buff_size % input_event::EVENT_SIZE;
        // If there is an incomplete event at the end of the buffer, it needs to be moved to the
        // beginning and the next read operation must write right after it.
        if remainder != 0 {
            warn!("read incomplete event from source");
            // The copy should only happen if there is at least one complete event in the buffer,
            // otherwise source and destination would be the same.
            if buff_size != remainder {
                let (des, src) = self.read_buffer.buffer.split_at_mut(buff_size - remainder);
                des[..remainder].copy_from_slice(src);
            }
        }
        self.read_idx = remainder;

        let received_events = buff_size / input_event::EVENT_SIZE;

        Ok(received_events)
    }

    fn available_events(&self) -> usize {
        self.queue.len()
    }

    fn new(source: T) -> EventSourceImpl<T> {
        EventSourceImpl {
            source,
            queue: VecDeque::new(),
            read_buffer: ReadBuffer {
                buffer: [0u8; READ_BUFFER_SIZE],
            },
            read_idx: 0,
        }
    }
}

/// Encapsulates a (unix) socket as an event source.
pub struct SocketEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> SocketEventSource<T> {
        SocketEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for SocketEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |_evt| true)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for SocketEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for SocketEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        Ok(())
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}

/// Encapsulates an event device node as an event source
pub struct EvdevEventSource<T> {
    evt_source_impl: EventSourceImpl<T>,
}

impl<T> EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    pub fn new(source: T) -> EvdevEventSource<T> {
        EvdevEventSource {
            evt_source_impl: EventSourceImpl::new(source),
        }
    }
}

impl<T: Read> Read for EvdevEventSource<T> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.evt_source_impl.read(buf)
    }
}

impl<T> Write for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.evt_source_impl.write(buf, |evt| {
            // Miscellaneous events produced by the device are sent back to it by the kernel input
            // subsystem, but because these events are handled by the host kernel as well as the
            // guest the device would get them twice. Which would prompt the device to send the
            // event to the guest again entering an infinite loop.
            evt.type_ != EV_MSC
        })
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.evt_source_impl.flush()
    }
}

impl<T: AsRawFd> AsRawFd for EvdevEventSource<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.evt_source_impl.as_raw_fd()
    }
}

impl<T> EventSource for EvdevEventSource<T>
where
    T: Read + Write + AsRawFd,
{
    fn init(&mut self) -> Result<()> {
        grab_evdev(self)
    }

    fn finalize(&mut self) -> Result<()> {
        ungrab_evdev(self)
    }

    fn receive_events(&mut self) -> Result<usize> {
        self.evt_source_impl.receive_events(|_evt| true)
    }

    fn available_events_count(&self) -> usize {
        self.evt_source_impl.available_events()
    }
}

#[cfg(test)]
mod tests {
    use data_model::{DataInit, Le16, Le32};
    use std::cmp::min;
    use std::io::Read;
    use std::io::Write;
    use std::mem::size_of;
    use virtio::input::event_source::input_event;
    use virtio::input::event_source::EventSourceImpl;
    use virtio::input::virtio_input_event;

    struct SourceMock {
        events: Vec<u8>,
    }

    impl SourceMock {
        fn new(evts: &Vec<input_event>) -> SourceMock {
            let mut events: Vec<u8> = vec![];
            for evt in evts {
                for byte in evt.as_slice() {
                    events.push(byte.clone());
                }
            }
            SourceMock { events }
        }
    }

    impl Read for SourceMock {
        fn read(&mut self, buf: &mut [u8]) -> std::result::Result<usize, std::io::Error> {
            let copy_size = min(buf.len(), self.events.len());
            buf[..copy_size].copy_from_slice(&self.events[..copy_size]);
            Ok(copy_size)
        }
    }
    impl Write for SourceMock {
        fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, std::io::Error> {
            Ok(buf.len())
        }

        fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
            Ok(())
        }
    }

    #[test]
    fn empty_new() {
        let mut source = EventSourceImpl::new(SourceMock::new(&vec![]));
        assert_eq!(
            source.available_events(),
            0,
            "zero events should be available"
        );
        let mut buffer = [0u8, 80];
        assert_eq!(
            source.read(&mut buffer).unwrap(),
            0,
            "zero events should be read"
        );
    }

    #[test]
    fn empty_receive() {
        let mut source = EventSourceImpl::new(SourceMock::new(&vec![]));
        assert_eq!(
            source.receive_events(|_| true).unwrap(),
            0,
            "zero events should be received"
        );
        let mut buffer = [0u8, 80];
        assert_eq!(
            source.read(&mut buffer).unwrap(),
            0,
            "zero events should be read"
        );
    }

    fn instantiate_input_events(count: usize) -> Vec<input_event> {
        let mut ret: Vec<input_event> = Vec::with_capacity(count);
        for idx in 0..count {
            ret.push(input_event {
                timestamp_fields: [0, 0],
                type_: 3 * (idx as u16) + 1,
                code: 3 * (idx as u16) + 2,
                value: 3 * (idx as u32) + 3,
            });
        }
        ret
    }

    fn assert_events_match(e1: &virtio_input_event, e2: &input_event) {
        assert_eq!(e1.type_, Le16::from(e2.type_), "type should match");
        assert_eq!(e1.code, Le16::from(e2.code), "code should match");
        assert_eq!(e1.value, Le32::from(e2.value), "value should match");
    }

    #[test]
    fn partial_read() {
        let evts = instantiate_input_events(4usize);
        let mut source = EventSourceImpl::new(SourceMock::new(&evts));
        assert_eq!(
            source.receive_events(|_| true).unwrap(),
            evts.len(),
            "should receive all events"
        );
        let mut evt = virtio_input_event {
            type_: Le16::from(0),
            code: Le16::from(0),
            value: Le32::from(0),
        };
        assert_eq!(
            source.read(evt.as_mut_slice()).unwrap(),
            virtio_input_event::EVENT_SIZE,
            "should read a single event"
        );
        assert_events_match(&evt, &evts[0]);
    }

    #[test]
    fn exact_read() {
        const EVENT_COUNT: usize = 4;
        let evts = instantiate_input_events(EVENT_COUNT);
        let mut source = EventSourceImpl::new(SourceMock::new(&evts));
        assert_eq!(
            source.receive_events(|_| true).unwrap(),
            evts.len(),
            "should receive all events"
        );
        let mut vio_evts = [0u8; EVENT_COUNT * size_of::<virtio_input_event>()];
        assert_eq!(
            source.read(&mut vio_evts).unwrap(),
            EVENT_COUNT * virtio_input_event::EVENT_SIZE,
            "should read all events"
        );

        let mut chunks = vio_evts.chunks_exact(virtio_input_event::EVENT_SIZE);
        for idx in 0..EVENT_COUNT {
            let evt = virtio_input_event::from_slice(chunks.next().unwrap()).unwrap();
            assert_events_match(&evt, &evts[idx]);
        }
    }

    #[test]
    fn over_read() {
        const EVENT_COUNT: usize = 4;
        let evts = instantiate_input_events(EVENT_COUNT);
        let mut source = EventSourceImpl::new(SourceMock::new(&evts));
        assert_eq!(
            source.receive_events(|_| true).unwrap(),
            evts.len(),
            "should receive all events"
        );
        let mut vio_evts = [0u8; 2 * EVENT_COUNT * size_of::<virtio_input_event>()];
        assert_eq!(
            source.read(&mut vio_evts).unwrap(),
            EVENT_COUNT * virtio_input_event::EVENT_SIZE,
            "should only read available events"
        );

        let mut chunks = vio_evts.chunks_exact(virtio_input_event::EVENT_SIZE);
        for idx in 0..EVENT_COUNT {
            let evt = virtio_input_event::from_slice(chunks.next().unwrap()).unwrap();
            assert_events_match(&evt, &evts[idx]);
        }
    }

    #[test]
    fn incomplete_read() {
        const EVENT_COUNT: usize = 4;
        let evts = instantiate_input_events(EVENT_COUNT);
        let mut source = EventSourceImpl::new(SourceMock::new(&evts));
        assert_eq!(
            source.receive_events(|_| true).unwrap(),
            evts.len(),
            "should receive all events"
        );
        let mut vio_evts = [0u8; 3];
        assert_eq!(
            source.read(&mut vio_evts).unwrap(),
            0,
            "shouldn't read incomplete events"
        );
    }
}
<|endoftext|>


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

use timely::PartialOrder;
use timely::dataflow::Scope;
use timely::dataflow::channels::pact::{Pipeline, Exchange};
use timely::dataflow::operators::Operator;

use timely_sort::Unsigned;

use differential_dataflow::{ExchangeData, Collection, AsCollection, Hashable};
use differential_dataflow::difference::Monoid;
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::arrange::Arranged;
use differential_dataflow::trace::{Cursor, TraceReader, BatchReader};

/// Proposes extensions to a stream of prefixes.
///
/// This method takes a stream of prefixes and for each determines a
/// key with `key_selector` and then proposes all pair af the prefix
/// and values associated with the key in `arrangement`.
pub fn lookup_map<G, D, R, Tr, F, DOut, ROut, S>(
    prefixes: &Collection<G, D, R>,
    arrangement: Arranged<G, Tr>,
    key_selector: F,
    output_func: S,
) -> Collection<G, DOut, ROut>
where
    G: Scope,
    G::Timestamp: Lattice,
    Tr: TraceReader<Time=G::Timestamp>+Clone+'static,
    Tr::Key: Ord+Hashable+Default,
    Tr::Val: Clone,
    Tr::Batch: BatchReader<Tr::Key, Tr::Val, Tr::Time, Tr::R>,
    Tr::Cursor: Cursor<Tr::Key, Tr::Val, Tr::Time, Tr::R>,
    Tr::R: Monoid+ExchangeData,
    F: Fn(&D, &mut Tr::Key)+Clone+'static,
    D: ExchangeData,
    R: ExchangeData+Monoid,
    DOut: Clone+'static,
    ROut: Monoid,
    S: Fn(&D, &R, &Tr::Val, &Tr::R)->(DOut, ROut)+'static,
{
    let propose_stream = arrangement.stream;
    let mut propose_trace = Some(arrangement.trace);

    let mut stash = HashMap::new();
    let logic1 = key_selector.clone();
    let logic2 = key_selector.clone();

    let mut buffer1 = Vec::new();
    let mut buffer2 = Vec::new();

    let mut key: Tr::Key = Default::default();
    let exchange = Exchange::new(move |update: &(D,G::Timestamp,R)| {
        logic1(&update.0, &mut key);
        key.hashed().as_u64()
    });

    let mut key1: Tr::Key = Default::default();
    let mut key2: Tr::Key = Default::default();
    prefixes.inner.binary_frontier(&propose_stream, exchange, Pipeline, "LookupMap", move |_,_| move |input1, input2, output| {

        // drain the first input, stashing requests.
        input1.for_each(|capability, data| {
            data.swap(&mut buffer1);
            stash.entry(capability.retain())
                 .or_insert(Vec::new())
                 .extend(buffer1.drain(..))
        });

        // advance the `distinguish_since` frontier to allow all merges.
        input2.for_each(|_, batches| {
            batches.swap(&mut buffer2);
            for batch in buffer2.drain(..) {
                if let Some(ref mut trace) = propose_trace {
                    trace.distinguish_since(batch.upper());
                }
            }
        });

        if let Some(ref mut trace) = propose_trace {

            for (capability, prefixes) in stash.iter_mut() {

                // defer requests at incomplete times.
                // NOTE: not all updates may be at complete times, but if this test fails then none of them are.
                if !input2.frontier.less_equal(capability.time()) {

                    let mut session = output.session(capability);

                    // sort requests for in-order cursor traversal. could consolidate?
                    prefixes.sort_by(|x,y| {
                        logic2(&x.0, &mut key1);
                        logic2(&y.0, &mut key2);
                        key1.cmp(&key2)
                    });

                    let (mut cursor, storage) = trace.cursor();

                    for &mut (ref prefix, ref time, ref mut diff) in prefixes.iter_mut() {
                        if !input2.frontier.less_equal(time) {
                            logic2(prefix, &mut key1);
                            // let key = logic2(prefix);
                            cursor.seek_key(&storage, &key1);
                            if cursor.get_key(&storage) == Some(&key1) {
                                while let Some(value) = cursor.get_val(&storage) {
                                    let mut count = Tr::R::zero();
                                    cursor.map_times(&storage, |t, d| if t.less_equal(time) { count += d; });
                                    if !count.is_zero() {
                                        let (dout, rout) = output_func(prefix, diff, value, &count);
                                        if !rout.is_zero() {
                                            session.give((dout, time.clone(), rout));
                                        }
                                    }
                                    cursor.step_val(&storage);
                                }
                                cursor.rewind_vals(&storage);
                            }
                            *diff = R::zero();
                        }
                    }

                    prefixes.retain(|ptd| !ptd.2.is_zero());
                }
            }
        }

        // drop fully processed capabilities.
        stash.retain(|_,prefixes| !prefixes.is_empty());

        // advance the consolidation frontier (TODO: wierd lexicographic times!)
        propose_trace.as_mut().map(|trace| trace.advance_by(&input1.frontier().frontier()));

        if input1.frontier().is_empty() && stash.is_empty() {
            propose_trace = None;
        }

    }).as_collection()
}<commit_msg>frontier race, fixes #183<commit_after>use std::collections::HashMap;

use timely::PartialOrder;
use timely::dataflow::Scope;
use timely::dataflow::channels::pact::{Pipeline, Exchange};
use timely::dataflow::operators::Operator;

use timely_sort::Unsigned;

use differential_dataflow::{ExchangeData, Collection, AsCollection, Hashable};
use differential_dataflow::difference::Monoid;
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::arrange::Arranged;
use differential_dataflow::trace::{Cursor, TraceReader, BatchReader};

/// Proposes extensions to a stream of prefixes.
///
/// This method takes a stream of prefixes and for each determines a
/// key with `key_selector` and then proposes all pair af the prefix
/// and values associated with the key in `arrangement`.
pub fn lookup_map<G, D, R, Tr, F, DOut, ROut, S>(
    prefixes: &Collection<G, D, R>,
    arrangement: Arranged<G, Tr>,
    key_selector: F,
    output_func: S,
) -> Collection<G, DOut, ROut>
where
    G: Scope,
    G::Timestamp: Lattice,
    Tr: TraceReader<Time=G::Timestamp>+Clone+'static,
    Tr::Key: Ord+Hashable+Default,
    Tr::Val: Clone,
    Tr::Batch: BatchReader<Tr::Key, Tr::Val, Tr::Time, Tr::R>,
    Tr::Cursor: Cursor<Tr::Key, Tr::Val, Tr::Time, Tr::R>,
    Tr::R: Monoid+ExchangeData,
    F: Fn(&D, &mut Tr::Key)+Clone+'static,
    D: ExchangeData,
    R: ExchangeData+Monoid,
    DOut: Clone+'static,
    ROut: Monoid,
    S: Fn(&D, &R, &Tr::Val, &Tr::R)->(DOut, ROut)+'static,
{
    let propose_stream = arrangement.stream;
    let mut propose_trace = Some(arrangement.trace);

    let mut stash = HashMap::new();
    let logic1 = key_selector.clone();
    let logic2 = key_selector.clone();

    let mut buffer1 = Vec::new();
    let mut buffer2 = Vec::new();

    let mut key: Tr::Key = Default::default();
    let exchange = Exchange::new(move |update: &(D,G::Timestamp,R)| {
        logic1(&update.0, &mut key);
        key.hashed().as_u64()
    });

    let mut key1: Tr::Key = Default::default();
    let mut key2: Tr::Key = Default::default();
    prefixes.inner.binary_frontier(&propose_stream, exchange, Pipeline, "LookupMap", move |_,_| move |input1, input2, output| {

        // drain the first input, stashing requests.
        input1.for_each(|capability, data| {
            data.swap(&mut buffer1);
            stash.entry(capability.retain())
                 .or_insert(Vec::new())
                 .extend(buffer1.drain(..))
        });

        // advance the `distinguish_since` frontier to allow all merges.
        input2.for_each(|_, batches| {
            batches.swap(&mut buffer2);
            for batch in buffer2.drain(..) {
                if let Some(ref mut trace) = propose_trace {
                    trace.distinguish_since(batch.upper());
                }
            }
        });

        if let Some(ref mut trace) = propose_trace {

            for (capability, prefixes) in stash.iter_mut() {

                // defer requests at incomplete times.
                // NOTE: not all updates may be at complete times, but if this test fails then none of them are.
                if !input2.frontier.less_equal(capability.time()) {

                    let mut session = output.session(capability);

                    // sort requests for in-order cursor traversal. could consolidate?
                    prefixes.sort_by(|x,y| {
                        logic2(&x.0, &mut key1);
                        logic2(&y.0, &mut key2);
                        key1.cmp(&key2)
                    });

                    let (mut cursor, storage) = trace.cursor();

                    for &mut (ref prefix, ref time, ref mut diff) in prefixes.iter_mut() {
                        if !input2.frontier.less_equal(time) {
                            logic2(prefix, &mut key1);
                            cursor.seek_key(&storage, &key1);
                            if cursor.get_key(&storage) == Some(&key1) {
                                while let Some(value) = cursor.get_val(&storage) {
                                    let mut count = Tr::R::zero();
                                    cursor.map_times(&storage, |t, d| {
                                        if t.less_equal(time) { count += d; }
                                    });
                                    if !count.is_zero() {
                                        let (dout, rout) = output_func(prefix, diff, value, &count);
                                        if !rout.is_zero() {
                                            session.give((dout, time.clone(), rout));
                                        }
                                    }
                                    cursor.step_val(&storage);
                                }
                                cursor.rewind_vals(&storage);
                            }
                            *diff = R::zero();
                        }
                    }

                    prefixes.retain(|ptd| !ptd.2.is_zero());
                }
            }
        }

        // drop fully processed capabilities.
        stash.retain(|_,prefixes| !prefixes.is_empty());

        // The consolidation frontier depends on both input1 and stash.
        let mut frontier = timely::progress::frontier::Antichain::new();
        for time in input1.frontier().frontier().to_vec() {
            frontier.insert(time);
        }
        for key in stash.keys() {
            frontier.insert(key.time().clone());
        }
        propose_trace.as_mut().map(|trace| trace.advance_by(frontier.elements()));

        if input1.frontier().is_empty() && stash.is_empty() {
            propose_trace = None;
        }

    }).as_collection()
}<|endoftext|>


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

extern crate word_count;

fn check_word_count(s: &str, pairs: &[(&str, u32)]) {
    // The reason for the awkward code in here is to ensure that the failure
    // message for assert_eq! is as informative as possible. A simpler
    // solution would simply check the length of the map, and then
    // check for the presence and value of each key in the given pairs vector.
    let mut m: HashMap<String, u32> = word_count::word_count(s);
    for &(k, v) in pairs.iter() {
        assert_eq!((k, m.remove(&k.to_string()).unwrap_or(0)), (k, v));
    }
    // may fail with a message that clearly shows all extra pairs in the map
    assert_eq!(m.iter().collect::<Vec<(&String, &u32)>>(), vec![]);
}

#[test]
fn test_count_one_word() {
    check_word_count("word", &[("word", 1)]);
}

#[test]
#[ignore]
fn test_count_one_of_each() {
    check_word_count("one of each", &[("one", 1), ("of", 1), ("each", 1)]);
}

#[test]
#[ignore]
fn test_count_multiple_occurrences() {
    check_word_count(
        "one fish two fish red fish blue fish",
        &[("one", 1), ("fish", 4), ("two", 1), ("red", 1), ("blue", 1)],
    );
}

#[test]
#[ignore]
fn cramped_lists() {
    check_word_count(
        "one,two,three",
        &[("one", 1), ("two", 1), ("three", 1)],
    );
}

#[test]
#[ignore]
fn expanded_lists() {
    check_word_count(
        "one\ntwo\nthree",
        &[("one", 1), ("two", 1), ("three", 1)],
    );
}

#[test]
#[ignore]
fn test_ignore_punctuation() {
    check_word_count(
        "car : carpet as java : javascript!!&@$%^&",
        &[
            ("car", 1),
            ("carpet", 1),
            ("as", 1),
            ("java", 1),
            ("javascript", 1),
        ],
    );
}

#[test]
#[ignore]
fn test_include_numbers() {
    check_word_count(
        "testing, 1, 2 testing",
        &[("testing", 2), ("1", 1), ("2", 1)],
    );
}

#[test]
#[ignore]
fn test_normalize_case() {
    check_word_count("go Go GO Stop stop", &[("go", 3), ("stop", 2)]);
}

#[test]
#[ignore]
fn with_apostrophes() {
    check_word_count(
        "First: don't laugh. Then: don't cry.",
        &[
            ("first", 1),
            ("don't", 2),
            ("laugh", 1),
            ("then", 1),
            ("cry", 1),
        ],
    );
}

#[test]
#[ignore]
fn with_quotations() {
    check_word_count(
        "Joe can't tell between 'large' and large.",
        &[
            ("joe", 1),
            ("can't", 1),
            ("tell", 1),
            ("between", 1),
            ("large", 2),
            ("and", 1),
        ],
    );
}
<commit_msg>word-count: test that consecutive whitespaces are not words<commit_after>use std::collections::HashMap;

extern crate word_count;

fn check_word_count(s: &str, pairs: &[(&str, u32)]) {
    // The reason for the awkward code in here is to ensure that the failure
    // message for assert_eq! is as informative as possible. A simpler
    // solution would simply check the length of the map, and then
    // check for the presence and value of each key in the given pairs vector.
    let mut m: HashMap<String, u32> = word_count::word_count(s);
    for &(k, v) in pairs.iter() {
        assert_eq!((k, m.remove(&k.to_string()).unwrap_or(0)), (k, v));
    }
    // may fail with a message that clearly shows all extra pairs in the map
    assert_eq!(m.iter().collect::<Vec<(&String, &u32)>>(), vec![]);
}

#[test]
fn test_count_one_word() {
    check_word_count("word", &[("word", 1)]);
}

#[test]
#[ignore]
fn test_count_one_of_each() {
    check_word_count("one of each", &[("one", 1), ("of", 1), ("each", 1)]);
}

#[test]
#[ignore]
fn test_count_multiple_occurrences() {
    check_word_count(
        "one fish two fish red fish blue fish",
        &[("one", 1), ("fish", 4), ("two", 1), ("red", 1), ("blue", 1)],
    );
}

#[test]
#[ignore]
fn cramped_lists() {
    check_word_count(
        "one,two,three",
        &[("one", 1), ("two", 1), ("three", 1)],
    );
}

#[test]
#[ignore]
fn expanded_lists() {
    check_word_count(
        "one\ntwo\nthree",
        &[("one", 1), ("two", 1), ("three", 1)],
    );
}

#[test]
#[ignore]
fn test_ignore_punctuation() {
    check_word_count(
        "car : carpet as java : javascript!!&@$%^&",
        &[
            ("car", 1),
            ("carpet", 1),
            ("as", 1),
            ("java", 1),
            ("javascript", 1),
        ],
    );
}

#[test]
#[ignore]
fn test_include_numbers() {
    check_word_count(
        "testing, 1, 2 testing",
        &[("testing", 2), ("1", 1), ("2", 1)],
    );
}

#[test]
#[ignore]
fn test_normalize_case() {
    check_word_count("go Go GO Stop stop", &[("go", 3), ("stop", 2)]);
}

#[test]
#[ignore]
fn with_apostrophes() {
    check_word_count(
        "First: don't laugh. Then: don't cry.",
        &[
            ("first", 1),
            ("don't", 2),
            ("laugh", 1),
            ("then", 1),
            ("cry", 1),
        ],
    );
}

#[test]
#[ignore]
fn with_quotations() {
    check_word_count(
        "Joe can't tell between 'large' and large.",
        &[
            ("joe", 1),
            ("can't", 1),
            ("tell", 1),
            ("between", 1),
            ("large", 2),
            ("and", 1),
        ],
    );
}

#[test]
#[ignore]
fn multiple_spaces_not_detected_as_a_word() {
    check_word_count(
        " multiple   whitespaces",
        &[("multiple", 1), ("whitespaces", 1)]
    );
}
<|endoftext|>


<commit_before>use cgmath;
use cgmath::{Point3, EuclideanSpace};
use gl;
use std;
use std::f32;
use yaglw;
use yaglw::gl_context::GLContext;

use common::entity_id;
use common::fnv_map;

use terrain_mesh;
use vertex;

// VRAM bytes
pub const BYTE_BUDGET: usize = 64_000_000;
pub const TUFT_COST: usize = 100;
pub const TUFT_BUDGET: usize = BYTE_BUDGET / TUFT_COST;

/// Struct for loading/unloading/maintaining terrain data in VRAM.
pub struct T<'a> {
  id_to_index: fnv_map::T<entity_id::T, usize>,
  index_to_id: Vec<entity_id::T>,

  gl_array: yaglw::vertex_buffer::ArrayHandle<'a>,
  _instance_vertices: yaglw::vertex_buffer::GLBuffer<'a, vertex::TextureVertex>,
  per_tuft: yaglw::vertex_buffer::GLBuffer<'a, terrain_mesh::Grass>,
}

#[allow(missing_docs)]
pub fn new<'a, 'b:'a>(
  gl: &'a mut GLContext,
  shader: &yaglw::shader::Shader<'a>,
) -> T<'b>
{
  use yaglw::vertex_buffer;

  let gl_array = vertex_buffer::ArrayHandle::new(gl);
  let mut instance_vertices = vertex_buffer::GLBuffer::new(gl, 18);
  let per_tuft = vertex_buffer::GLBuffer::new(gl, TUFT_BUDGET);

  let mut vertices = Vec::new();
  {
    let tangent = cgmath::Vector3::new(0.0, 0.0, 0.5);
    let normal = cgmath::Vector3::new(0.0, 1.0, 0.0);
    let mut quad = |v: &cgmath::Vector3<f32>| {
      let mut tri = |p0, t0, p1, t1, p2, t2| {
        let vert = |p, t| {
          vertex::TextureVertex {
            world_position: p,
            texture_position: t,
          }
        };
        vertices.push(vert(p0, t0));
        vertices.push(vert(p1, t1));
        vertices.push(vert(p2, t2));
      };

      tri(
        Point3::from_vec(-*v / 2.0)          , cgmath::Vector2::new(0.0 , 0.0) ,
        Point3::from_vec( *v / 2.0)          , cgmath::Vector2::new(1.0 , 0.0) ,
        Point3::from_vec( *v / 2.0) + normal , cgmath::Vector2::new(1.0 , 1.0) ,
      );
      tri(
        Point3::from_vec(-*v / 2.0)          , cgmath::Vector2::new(0.0 , 0.0) ,
        Point3::from_vec( *v / 2.0) + normal , cgmath::Vector2::new(1.0 , 1.0) ,
        Point3::from_vec(-*v / 2.0) + normal , cgmath::Vector2::new(0.0 , 1.0) ,
      );
    };

    quad(&tangent);
    quad(&(cgmath::Matrix3::from_axis_angle(normal, cgmath::rad(f32::consts::FRAC_PI_3)) * tangent));
    quad(&(cgmath::Matrix3::from_axis_angle(normal, cgmath::rad(2.0 * f32::consts::FRAC_PI_3)) * tangent));
  }

  unsafe {
    gl::BindVertexArray(gl_array.gl_id);
  }
  shader.use_shader(gl);
  instance_vertices.byte_buffer.bind(gl);
  instance_vertices.push(gl, &vertices);
  let attrib_span =
    vertex_buffer::VertexAttribData::apply(
      &[
        vertex_buffer::VertexAttribData {
          name: "vertex_position",
          size: 3,
          unit: vertex_buffer::GLType::Float,
          divisor: 0,
        },
        vertex_buffer::VertexAttribData {
          name: "texture_position",
          size: 2,
          unit: vertex_buffer::GLType::Float,
          divisor: 0,
        },
      ],
      gl,
      shader,
    );
  assert!(attrib_span == std::mem::size_of::<vertex::TextureVertex>() as u32);

  per_tuft.byte_buffer.bind(gl);
  let attrib_span =
    vertex_buffer::VertexAttribData::apply(
      &[
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col0",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col1",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col2",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col3",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "normal",
          size: 3,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "tex_id",
          size: 3,
          unit: vertex_buffer::GLType::UInt,
          divisor: 1,
        },
      ],
      gl,
      shader,
    );
  assert!(attrib_span == std::mem::size_of::<terrain_mesh::Grass>() as u32);

  T {
    id_to_index: fnv_map::new(),
    index_to_id: Vec::new(),

    gl_array: gl_array,
    _instance_vertices: instance_vertices,
    per_tuft: per_tuft,
  }
}

impl<'a> T<'a> {
  /// Add a series of entites into VRAM.
  pub fn push(
    &mut self,
    gl: &mut GLContext,
    grass: &[terrain_mesh::Grass],
    grass_ids: &[entity_id::T],
  ) {
    self.per_tuft.byte_buffer.bind(gl);
    let success: bool = self.per_tuft.push(gl, grass);
    if !success {
      panic!("Ran out of VRAM for grass");
    }

    for id in grass_ids {
      self.id_to_index.insert(*id, self.index_to_id.len());
      self.index_to_id.push(*id);
    }
  }

  // TODO: Make this take many ids as a parameter, to reduce `bind`s.
  // Note: `id` must be present in the buffers.
  /// Remove some entity from VRAM.
  pub fn swap_remove(&mut self, gl: &mut GLContext, id: entity_id::T) {
    let idx = *self.id_to_index.get(&id).unwrap();
    let swapped_id = self.index_to_id[self.index_to_id.len() - 1];
    self.index_to_id.swap_remove(idx);
    self.id_to_index.remove(&id);

    if id != swapped_id {
      self.id_to_index.insert(swapped_id, idx);
    }

    self.per_tuft.byte_buffer.bind(gl);
    self.per_tuft.swap_remove(gl, idx, 1);
  }

  pub fn draw(&self, _gl: &mut GLContext) {
    unsafe {
      gl::BindVertexArray(self.gl_array.gl_id);
      gl::DrawArraysInstanced(gl::TRIANGLES, 0, 18, self.index_to_id.len() as i32);
    }
  }
}
<commit_msg>grass bugfix<commit_after>use cgmath;
use cgmath::{Point3, EuclideanSpace};
use gl;
use std;
use std::f32;
use yaglw;
use yaglw::gl_context::GLContext;

use common::entity_id;
use common::fnv_map;

use terrain_mesh;
use vertex;

// VRAM bytes
pub const BYTE_BUDGET: usize = 64_000_000;
pub const TUFT_COST: usize = 100;
pub const TUFT_BUDGET: usize = BYTE_BUDGET / TUFT_COST;

/// Struct for loading/unloading/maintaining terrain data in VRAM.
pub struct T<'a> {
  id_to_index: fnv_map::T<entity_id::T, usize>,
  index_to_id: Vec<entity_id::T>,

  gl_array: yaglw::vertex_buffer::ArrayHandle<'a>,
  _instance_vertices: yaglw::vertex_buffer::GLBuffer<'a, vertex::TextureVertex>,
  per_tuft: yaglw::vertex_buffer::GLBuffer<'a, terrain_mesh::Grass>,
}

#[allow(missing_docs)]
pub fn new<'a, 'b:'a>(
  gl: &'a mut GLContext,
  shader: &yaglw::shader::Shader<'a>,
) -> T<'b>
{
  use yaglw::vertex_buffer;

  let gl_array = vertex_buffer::ArrayHandle::new(gl);
  let mut instance_vertices = vertex_buffer::GLBuffer::new(gl, 18);
  let per_tuft = vertex_buffer::GLBuffer::new(gl, TUFT_BUDGET);

  let mut vertices = Vec::new();
  {
    let tangent = cgmath::Vector3::new(0.0, 0.0, 0.5);
    let normal = cgmath::Vector3::new(0.0, 1.0, 0.0);
    let mut quad = |v: &cgmath::Vector3<f32>| {
      let mut tri = |p0, t0, p1, t1, p2, t2| {
        let vert = |p, t| {
          vertex::TextureVertex {
            world_position: p,
            texture_position: t,
          }
        };
        vertices.push(vert(p0, t0));
        vertices.push(vert(p1, t1));
        vertices.push(vert(p2, t2));
      };

      tri(
        Point3::from_vec(-(*v / 2.0))          , cgmath::Vector2::new(0.0 , 0.0) ,
        Point3::from_vec( (*v / 2.0))          , cgmath::Vector2::new(1.0 , 0.0) ,
        Point3::from_vec( (*v / 2.0 + normal)) , cgmath::Vector2::new(1.0 , 1.0) ,
      );
      tri(
        Point3::from_vec(-(*v / 2.0))          , cgmath::Vector2::new(0.0 , 0.0) ,
        Point3::from_vec( (*v / 2.0 + normal)) , cgmath::Vector2::new(1.0 , 1.0) ,
        Point3::from_vec(-(*v / 2.0 + normal)) , cgmath::Vector2::new(0.0 , 1.0) ,
      );
    };

    quad(&tangent);
    quad(&(cgmath::Matrix3::from_axis_angle(normal, cgmath::rad(f32::consts::FRAC_PI_3)) * tangent));
    quad(&(cgmath::Matrix3::from_axis_angle(normal, cgmath::rad(2.0 * f32::consts::FRAC_PI_3)) * tangent));
  }

  unsafe {
    gl::BindVertexArray(gl_array.gl_id);
  }
  shader.use_shader(gl);
  instance_vertices.byte_buffer.bind(gl);
  instance_vertices.push(gl, &vertices);
  let attrib_span =
    vertex_buffer::VertexAttribData::apply(
      &[
        vertex_buffer::VertexAttribData {
          name: "vertex_position",
          size: 3,
          unit: vertex_buffer::GLType::Float,
          divisor: 0,
        },
        vertex_buffer::VertexAttribData {
          name: "texture_position",
          size: 2,
          unit: vertex_buffer::GLType::Float,
          divisor: 0,
        },
      ],
      gl,
      shader,
    );
  assert!(attrib_span == std::mem::size_of::<vertex::TextureVertex>() as u32);

  per_tuft.byte_buffer.bind(gl);
  let attrib_span =
    vertex_buffer::VertexAttribData::apply(
      &[
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col0",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col1",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col2",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "model_matrix_col3",
          size: 4,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "normal",
          size: 3,
          unit: vertex_buffer::GLType::Float,
          divisor: 1,
        },
        vertex_buffer::VertexAttribData {
          name: "tex_id",
          size: 3,
          unit: vertex_buffer::GLType::UInt,
          divisor: 1,
        },
      ],
      gl,
      shader,
    );
  assert!(attrib_span == std::mem::size_of::<terrain_mesh::Grass>() as u32);

  T {
    id_to_index: fnv_map::new(),
    index_to_id: Vec::new(),

    gl_array: gl_array,
    _instance_vertices: instance_vertices,
    per_tuft: per_tuft,
  }
}

impl<'a> T<'a> {
  /// Add a series of entites into VRAM.
  pub fn push(
    &mut self,
    gl: &mut GLContext,
    grass: &[terrain_mesh::Grass],
    grass_ids: &[entity_id::T],
  ) {
    self.per_tuft.byte_buffer.bind(gl);
    let success: bool = self.per_tuft.push(gl, grass);
    if !success {
      panic!("Ran out of VRAM for grass");
    }

    for id in grass_ids {
      self.id_to_index.insert(*id, self.index_to_id.len());
      self.index_to_id.push(*id);
    }
  }

  // TODO: Make this take many ids as a parameter, to reduce `bind`s.
  // Note: `id` must be present in the buffers.
  /// Remove some entity from VRAM.
  pub fn swap_remove(&mut self, gl: &mut GLContext, id: entity_id::T) {
    let idx = *self.id_to_index.get(&id).unwrap();
    let swapped_id = self.index_to_id[self.index_to_id.len() - 1];
    self.index_to_id.swap_remove(idx);
    self.id_to_index.remove(&id);

    if id != swapped_id {
      self.id_to_index.insert(swapped_id, idx);
    }

    self.per_tuft.byte_buffer.bind(gl);
    self.per_tuft.swap_remove(gl, idx, 1);
  }

  pub fn draw(&self, _gl: &mut GLContext) {
    unsafe {
      gl::BindVertexArray(self.gl_array.gl_id);
      gl::DrawArraysInstanced(gl::TRIANGLES, 0, 18, self.index_to_id.len() as i32);
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{utils, Result};
use std::{
    io::{self, Write},
    num::NonZeroUsize,
    panic::{catch_unwind, AssertUnwindSafe},
    path::Path,
    process,
    sync::mpsc::{channel, Sender},
    thread,
};
use structopt::StructOpt;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};

#[derive(Debug, StructOpt)]
#[structopt(about = "Datatest-harness for running data-driven tests")]
struct TestOpts {
    /// The FILTER string is tested against the name of all tests, and only those tests whose names
    /// contain the filter are run.
    filter: Option<String>,
    #[structopt(long = "exact")]
    /// Exactly match filters rather than by substring
    filter_exact: bool,
    #[structopt(long, default_value = "32", env = "RUST_TEST_THREADS")]
    /// Number of threads used for running tests in parallel
    test_threads: NonZeroUsize,
    #[structopt(short = "q", long)]
    /// Output minimal information
    quiet: bool,
    #[structopt(long)]
    /// NO-OP: don't capture stdout/stderr of each task, allow printing directly
    nocapture: bool,
    #[structopt(long)]
    /// List all tests
    list: bool,
    #[structopt(long)]
    /// NO-OP: Run only ignored tests
    ignored: bool,
    #[structopt(long)]
    /// NO-OP: Run ignored and not ignored tests
    include_ignored: bool,
    #[structopt(long)]
    /// NO-OP: Forces tests to run in-process when panic=abort
    force_run_in_process: bool,
    #[structopt(long)]
    /// NO-OP: Excludes tests marked as should_panic
    exclude_should_panic: bool,
    #[structopt(long)]
    /// NO-OP: Run tests and not benchmarks
    test: bool,
    #[structopt(long)]
    /// NO-OP: Run benchmarks instead of tests
    bench: bool,
    #[structopt(long)]
    /// NO-OP: Write logs to the specified file instead of stdout
    logfile: Option<String>,
    #[structopt(long, number_of_values = 1)]
    /// NO-OP: Skip tests whose names contain FILTER (this flag can be used multiple times)
    skip: Vec<String>,
    #[structopt(long)]
    /// NO-OP: Show captured stdo
    show_output: bool,
    #[structopt(long)]
    /// NO-OP: auto|always|never
    ///         Configure coloring of output:
    ///         auto = colorize if stdout is a tty and tests are run
    ///         on serially (default);
    ///         always = always colorize output;
    ///         never = never colorize output;
    color: Option<String>,
    #[structopt(long)]
    /// NO-OP: pretty|terse|json
    ///         Configure formatting of output:
    ///         pretty = Print verbose output;
    ///         terse = Display one character per test;
    ///         json = Output a json document
    format: Option<String>,
    #[structopt(long)]
    /// NO-OP: [plain|colored]
    ///         Show execution time of each test. Awailable values:
    ///         plain = do not colorize the execution time (default);
    ///         colored = colorize output according to the `color`
    ///         parameter value;
    ///         Threshold values for colorized output can be
    ///         configured via
    ///         `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
    ///         and
    ///         `RUST_TEST_TIME_DOCTEST` environment variables.
    ///         Expected format of environment variable is
    ///         `VARIABLE=WARN_TIME,CRITICAL_TIME`.
    ///         Durations must be specified in milliseconds, e.g.
    ///         `500,2000` means that the warn time
    ///         is 0.5 seconds, and the critical time is 2 seconds.
    ///         Not available for --format=terse
    report_time: Option<String>,
    #[structopt(long)]
    /// NO-OP: Treat excess of the test execution time limit as
    ///         error.
    ///         Threshold values for this option can be configured via
    ///         `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
    ///         and
    ///         `RUST_TEST_TIME_DOCTEST` environment variables.
    ///         Expected format of environment variable is
    ///         `VARIABLE=WARN_TIME,CRITICAL_TIME`.
    ///         `CRITICAL_TIME` here means the limit that should not
    ///         be exceeded by test.
    ensure_time: bool,
}

pub fn runner(reqs: &[Requirements]) {
    let options = TestOpts::from_args();

    let tests: Vec<Test> = reqs.iter().flat_map(|req| req.expand()).collect();

    if options.list {
        for test in &tests {
            println!("{}: test", test.name);
        }

        println!();
        println!("{} tests, 0 benchmarks", tests.len());
        return;
    }

    match run_tests(options, tests) {
        Ok(true) => {}
        Ok(false) => process::exit(101),
        Err(e) => {
            eprintln!("error: io error when running tests: {:?}", e);
            process::exit(101);
        }
    }
}

struct Test {
    testfn: Box<dyn Fn() -> Result<()> + Send>,
    name: String,
}

enum TestResult {
    Ok,
    Failed,
    FailedWithMsg(String),
}

fn run_tests(options: TestOpts, tests: Vec<Test>) -> io::Result<bool> {
    let total = tests.len();

    // Filter out tests
    let mut remaining = match &options.filter {
        None => tests,
        Some(filter) => tests
            .into_iter()
            .filter(|test| {
                if options.filter_exact {
                    test.name == filter[..]
                } else {
                    test.name.contains(&filter[..])
                }
            })
            .rev()
            .collect(),
    };

    let filtered_out = total - remaining.len();
    let mut summary = TestSummary::new(total, filtered_out);

    if !options.quiet {
        summary.write_starting_msg()?;
    }

    let (tx, rx) = channel();

    let mut pending = 0;
    while pending > 0 || !remaining.is_empty() {
        while pending < options.test_threads.get() && !remaining.is_empty() {
            let test = remaining.pop().unwrap();
            run_test(test, tx.clone());
            pending += 1;
        }

        let (name, result) = rx.recv().unwrap();
        summary.handle_result(name, result)?;

        pending -= 1;
    }

    // Write Test Summary
    if !options.quiet {
        summary.write_summary()?;
    }

    Ok(summary.success())
}

fn run_test(test: Test, channel: Sender<(String, TestResult)>) {
    let Test { name, testfn } = test;

    let cfg = thread::Builder::new().name(name.clone());
    cfg.spawn(move || {
        let result = match catch_unwind(AssertUnwindSafe(|| testfn())) {
            Ok(Ok(())) => TestResult::Ok,
            Ok(Err(e)) => TestResult::FailedWithMsg(format!("{:?}", e)),
            Err(_) => TestResult::Failed,
        };

        channel.send((name, result)).unwrap();
    })
    .unwrap();
}

struct TestSummary {
    stdout: StandardStream,
    total: usize,
    filtered_out: usize,
    passed: usize,
    failed: Vec<String>,
}

impl TestSummary {
    fn new(total: usize, filtered_out: usize) -> Self {
        Self {
            stdout: StandardStream::stdout(ColorChoice::Auto),
            total,
            filtered_out,
            passed: 0,
            failed: Vec::new(),
        }
    }

    fn handle_result(&mut self, name: String, result: TestResult) -> io::Result<()> {
        write!(self.stdout, "test {} ... ", name)?;
        match result {
            TestResult::Ok => {
                self.passed += 1;
                self.write_ok()?;
            }
            TestResult::Failed => {
                self.failed.push(name);
                self.write_failed()?;
            }
            TestResult::FailedWithMsg(msg) => {
                self.failed.push(name);
                self.write_failed()?;
                writeln!(self.stdout)?;

                write!(self.stdout, "Error: {}", msg)?;
            }
        }
        writeln!(self.stdout)?;
        Ok(())
    }

    fn write_ok(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
        write!(self.stdout, "ok")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_failed(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
        write!(self.stdout, "FAILED")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_starting_msg(&mut self) -> io::Result<()> {
        writeln!(self.stdout)?;
        writeln!(
            self.stdout,
            "running {} tests",
            self.total - self.filtered_out
        )?;
        Ok(())
    }

    fn write_summary(&mut self) -> io::Result<()> {
        // Print out the failing tests
        if !self.failed.is_empty() {
            writeln!(self.stdout)?;
            writeln!(self.stdout, "failures:")?;
            for name in &self.failed {
                writeln!(self.stdout, "    {}", name)?;
            }
        }

        writeln!(self.stdout)?;
        write!(self.stdout, "test result: ")?;
        if self.failed.is_empty() {
            self.write_ok()?;
        } else {
            self.write_failed()?;
        }
        writeln!(
            self.stdout,
            ". {} passed; {} failed; {} filtered out",
            self.passed,
            self.failed.len(),
            self.filtered_out
        )?;
        writeln!(self.stdout)?;
        Ok(())
    }

    fn success(&self) -> bool {
        self.failed.is_empty()
    }
}

pub struct Requirements {
    test: fn(&Path) -> Result<()>,
    test_name: String,
    root: String,
    pattern: String,
}

impl Requirements {
    pub fn new(
        test: fn(&Path) -> Result<()>,
        test_name: String,
        root: String,
        pattern: String,
    ) -> Self {
        Self {
            test,
            test_name,
            root,
            pattern,
        }
    }

    /// Generate standard test descriptors ([`test::TestDescAndFn`]) from the descriptor of
    /// `#[datatest::files(..)]`.
    ///
    /// Scans all files in a given directory, finds matching ones and generates a test descriptor
    /// for each of them.
    fn expand(&self) -> Vec<Test> {
        let root = Path::new(&self.root).to_path_buf();

        let re = regex::Regex::new(&self.pattern)
            .unwrap_or_else(|_| panic!("invalid regular expression: '{}'", self.pattern));

        let tests: Vec<_> = utils::iterate_directory(&root)
            .filter_map(|path| {
                let input_path = path.to_string_lossy();
                if re.is_match(&input_path) {
                    let testfn = self.test;
                    let name = utils::derive_test_name(&root, &path, &self.test_name);
                    let testfn = Box::new(move || (testfn)(&path));

                    Some(Test { testfn, name })
                } else {
                    None
                }
            })
            .collect();

        // We want to avoid silent fails due to typos in regexp!
        if tests.is_empty() {
            panic!(
                "no test cases found for test '{}'. Scanned directory: '{}' with pattern '{}'",
                self.test_name, self.root, self.pattern,
            );
        }

        tests
    }
}
<commit_msg>[test] explicitly and only state that these are no-op args/flags.<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{utils, Result};
use std::{
    io::{self, Write},
    num::NonZeroUsize,
    panic::{catch_unwind, AssertUnwindSafe},
    path::Path,
    process,
    sync::mpsc::{channel, Sender},
    thread,
};
use structopt::StructOpt;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};

#[derive(Debug, StructOpt)]
#[structopt(about = "Datatest-harness for running data-driven tests")]
struct TestOpts {
    /// The FILTER string is tested against the name of all tests, and only those tests whose names
    /// contain the filter are run.
    filter: Option<String>,
    #[structopt(long = "exact")]
    /// Exactly match filters rather than by substring
    filter_exact: bool,
    #[structopt(long, default_value = "32", env = "RUST_TEST_THREADS")]
    /// Number of threads used for running tests in parallel
    test_threads: NonZeroUsize,
    #[structopt(short = "q", long)]
    /// Output minimal information
    quiet: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    nocapture: bool,
    #[structopt(long)]
    /// List all tests
    list: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    ignored: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    include_ignored: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    force_run_in_process: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    exclude_should_panic: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    test: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    bench: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    logfile: Option<String>,
    #[structopt(long, number_of_values = 1)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    skip: Vec<String>,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    show_output: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    color: Option<String>,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    format: Option<String>,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    report_time: Option<String>,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    ensure_time: bool,
}

pub fn runner(reqs: &[Requirements]) {
    let options = TestOpts::from_args();

    let tests: Vec<Test> = reqs.iter().flat_map(|req| req.expand()).collect();

    if options.list {
        for test in &tests {
            println!("{}: test", test.name);
        }

        println!();
        println!("{} tests, 0 benchmarks", tests.len());
        return;
    }

    match run_tests(options, tests) {
        Ok(true) => {}
        Ok(false) => process::exit(101),
        Err(e) => {
            eprintln!("error: io error when running tests: {:?}", e);
            process::exit(101);
        }
    }
}

struct Test {
    testfn: Box<dyn Fn() -> Result<()> + Send>,
    name: String,
}

enum TestResult {
    Ok,
    Failed,
    FailedWithMsg(String),
}

fn run_tests(options: TestOpts, tests: Vec<Test>) -> io::Result<bool> {
    let total = tests.len();

    // Filter out tests
    let mut remaining = match &options.filter {
        None => tests,
        Some(filter) => tests
            .into_iter()
            .filter(|test| {
                if options.filter_exact {
                    test.name == filter[..]
                } else {
                    test.name.contains(&filter[..])
                }
            })
            .rev()
            .collect(),
    };

    let filtered_out = total - remaining.len();
    let mut summary = TestSummary::new(total, filtered_out);

    if !options.quiet {
        summary.write_starting_msg()?;
    }

    let (tx, rx) = channel();

    let mut pending = 0;
    while pending > 0 || !remaining.is_empty() {
        while pending < options.test_threads.get() && !remaining.is_empty() {
            let test = remaining.pop().unwrap();
            run_test(test, tx.clone());
            pending += 1;
        }

        let (name, result) = rx.recv().unwrap();
        summary.handle_result(name, result)?;

        pending -= 1;
    }

    // Write Test Summary
    if !options.quiet {
        summary.write_summary()?;
    }

    Ok(summary.success())
}

fn run_test(test: Test, channel: Sender<(String, TestResult)>) {
    let Test { name, testfn } = test;

    let cfg = thread::Builder::new().name(name.clone());
    cfg.spawn(move || {
        let result = match catch_unwind(AssertUnwindSafe(|| testfn())) {
            Ok(Ok(())) => TestResult::Ok,
            Ok(Err(e)) => TestResult::FailedWithMsg(format!("{:?}", e)),
            Err(_) => TestResult::Failed,
        };

        channel.send((name, result)).unwrap();
    })
    .unwrap();
}

struct TestSummary {
    stdout: StandardStream,
    total: usize,
    filtered_out: usize,
    passed: usize,
    failed: Vec<String>,
}

impl TestSummary {
    fn new(total: usize, filtered_out: usize) -> Self {
        Self {
            stdout: StandardStream::stdout(ColorChoice::Auto),
            total,
            filtered_out,
            passed: 0,
            failed: Vec::new(),
        }
    }

    fn handle_result(&mut self, name: String, result: TestResult) -> io::Result<()> {
        write!(self.stdout, "test {} ... ", name)?;
        match result {
            TestResult::Ok => {
                self.passed += 1;
                self.write_ok()?;
            }
            TestResult::Failed => {
                self.failed.push(name);
                self.write_failed()?;
            }
            TestResult::FailedWithMsg(msg) => {
                self.failed.push(name);
                self.write_failed()?;
                writeln!(self.stdout)?;

                write!(self.stdout, "Error: {}", msg)?;
            }
        }
        writeln!(self.stdout)?;
        Ok(())
    }

    fn write_ok(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
        write!(self.stdout, "ok")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_failed(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
        write!(self.stdout, "FAILED")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_starting_msg(&mut self) -> io::Result<()> {
        writeln!(self.stdout)?;
        writeln!(
            self.stdout,
            "running {} tests",
            self.total - self.filtered_out
        )?;
        Ok(())
    }

    fn write_summary(&mut self) -> io::Result<()> {
        // Print out the failing tests
        if !self.failed.is_empty() {
            writeln!(self.stdout)?;
            writeln!(self.stdout, "failures:")?;
            for name in &self.failed {
                writeln!(self.stdout, "    {}", name)?;
            }
        }

        writeln!(self.stdout)?;
        write!(self.stdout, "test result: ")?;
        if self.failed.is_empty() {
            self.write_ok()?;
        } else {
            self.write_failed()?;
        }
        writeln!(
            self.stdout,
            ". {} passed; {} failed; {} filtered out",
            self.passed,
            self.failed.len(),
            self.filtered_out
        )?;
        writeln!(self.stdout)?;
        Ok(())
    }

    fn success(&self) -> bool {
        self.failed.is_empty()
    }
}

pub struct Requirements {
    test: fn(&Path) -> Result<()>,
    test_name: String,
    root: String,
    pattern: String,
}

impl Requirements {
    pub fn new(
        test: fn(&Path) -> Result<()>,
        test_name: String,
        root: String,
        pattern: String,
    ) -> Self {
        Self {
            test,
            test_name,
            root,
            pattern,
        }
    }

    /// Generate standard test descriptors ([`test::TestDescAndFn`]) from the descriptor of
    /// `#[datatest::files(..)]`.
    ///
    /// Scans all files in a given directory, finds matching ones and generates a test descriptor
    /// for each of them.
    fn expand(&self) -> Vec<Test> {
        let root = Path::new(&self.root).to_path_buf();

        let re = regex::Regex::new(&self.pattern)
            .unwrap_or_else(|_| panic!("invalid regular expression: '{}'", self.pattern));

        let tests: Vec<_> = utils::iterate_directory(&root)
            .filter_map(|path| {
                let input_path = path.to_string_lossy();
                if re.is_match(&input_path) {
                    let testfn = self.test;
                    let name = utils::derive_test_name(&root, &path, &self.test_name);
                    let testfn = Box::new(move || (testfn)(&path));

                    Some(Test { testfn, name })
                } else {
                    None
                }
            })
            .collect();

        // We want to avoid silent fails due to typos in regexp!
        if tests.is_empty() {
            panic!(
                "no test cases found for test '{}'. Scanned directory: '{}' with pattern '{}'",
                self.test_name, self.root, self.pattern,
            );
        }

        tests
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate iron;
extern crate http;
extern crate time;

use std::io::net::ip::Ipv4Addr;
use iron::{Iron, Handler, BeforeMiddleware, IronError,
           Request, Response, ChainBuilder, Chain,
           IronResult, Error};
use iron::status;

struct ErrorHandler;
struct ErrorProducer;

impl Handler for ErrorHandler {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: IronError) -> (Response, IronResult<()>) {
        (Response::with(status::InternalServerError, "Internal Server Error."), Err(err))
    }

}

impl BeforeMiddleware for ErrorProducer {
    fn before(&self, _: &mut Request) -> IronResult<()> {
        Err("Error".to_string().erase())
    }
}

fn main() {
    // Handler is attached here.
    let mut chain = ChainBuilder::new(ErrorHandler);

    // Link our error maker.
    chain.link_before(ErrorProducer);

    Iron::new(chain).listen(Ipv4Addr(127, 0, 0, 1), 3000);
    println!("On 3000");
}

<commit_msg>(fix) Error::erase was removed due to new trait object safety rules.<commit_after>#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate iron;
extern crate http;
extern crate time;

use std::io::net::ip::Ipv4Addr;
use iron::{Iron, Handler, BeforeMiddleware, IronError,
           Request, Response, ChainBuilder, Chain,
           IronResult};
use iron::status;

struct ErrorHandler;
struct ErrorProducer;

impl Handler for ErrorHandler {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: IronError) -> (Response, IronResult<()>) {
        (Response::with(status::InternalServerError, "Internal Server Error."), Err(err))
    }

}

impl BeforeMiddleware for ErrorProducer {
    fn before(&self, _: &mut Request) -> IronResult<()> {
        Err(box "Error".to_string() as IronError)
    }
}

fn main() {
    // Handler is attached here.
    let mut chain = ChainBuilder::new(ErrorHandler);

    // Link our error maker.
    chain.link_before(ErrorProducer);

    Iron::new(chain).listen(Ipv4Addr(127, 0, 0, 1), 3000);
    println!("On 3000");
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;
#[macro_use]
extern crate clap;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::optim;
use torchrs::optim::OptimVal;
use torchrs::nn;
use torchrs::nn::{InitModuleStruct, GetFieldStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};
use torchrs::tensor;

use clap::{Arg, App};
#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let mut args = NetArgs::default();
    let matches = App::new("Torch.rs MNIST Example")
        .version("0.1")
        .author("Some Guy")
        .about("recognize handwritten digits")
        .arg(Arg::with_name("batch-size").takes_value(true))
        .arg(Arg::with_name("test-batch-size").takes_value(true))
        .arg(Arg::with_name("epochs").takes_value(true))
        .arg(Arg::with_name("lr").takes_value(true))
        .arg(Arg::with_name("momentum").takes_value(true))
        .arg(Arg::with_name("no-cuda").takes_value(false))
        .arg(Arg::with_name("seed").takes_value(true))
        .arg(Arg::with_name("log-interval").takes_value(true))
        .get_matches();
    let (b_size, tb_size, epochs, lr, momentum, seed, log_int) =
        (value_t!(matches.value_of("batch-size"), usize).ok(),
         value_t!(matches.value_of("test-batch-size"), usize).ok(),
         value_t!(matches.value_of("epochs"), u32).ok(),
         value_t!(matches.value_of("lr"), f32).ok(),
         value_t!(matches.value_of("momentum"), f32).ok(),
         value_t!(matches.value_of("seed"), usize).ok(),
         value_t!(matches.value_of("log-interval"), usize).ok());
    if let Some(b_size) = b_size {
        args.batch_size = b_size
    }
    if let Some(tb_size) = tb_size {
        args.test_batch_size = tb_size
    }
    if let Some(epochs) = epochs {
        args.epochs = epochs
    }
    if let Some(lr) = lr {
        args.lr = lr
    }
    if let Some(momentum) = momentum {
        args.momentum = momentum
    }
    if let Some(seed) = seed {
        args.seed = seed
    }
    if let Some(log_int) = log_int {
        args.log_interval = log_int
    }
    //XXX CUDA?
    args
}

#[derive(ModParse)]
struct Net<T: tensor::NumLimits<T> + 'static> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: tensor::NumLimits<T> + 'static> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl<T: tensor::NumLimits<T>> ModIntf<T> for Net<T> {
    fn forward(&mut self, args: &mut Variable<T>) -> Variable<T> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        x = F::relu(&F::max_pool2d(&F::dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                   (2, 2),
                                   &pool_val));
        x = x.view(&[-1, 320]);
        x = F::relu(&self.fc1.f(&mut x));
        x = F::dropout(&x, &dropout_val);
        x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
}

fn train<'a>(model: &mut Net<f32>,
             args: &NetArgs,
             train_loader: &D::BatchLoader<f32, i64>,
             epoch: u32,
             optimizer: &mut optim::OptIntf<f32>) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad(model);
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step(model);
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (mut data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(&mut data);
        test_loss += F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum() as u32;
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    // no data loaders yet so demonstrate with Vec placeholder

    let train_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::<f32>::build("../data").done(None),
                           D::DataLoaderArgs::default());

    let test_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::<f32>::build("../data").done(None),
                           D::DataLoaderArgs::default());
    let args = parse_args();
    let mut model = Net::new();
    let mut optimizer = optim::SGD::new(map_opt!{"lr" => args.lr, "momentum" => args.momentum});
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<commit_msg>remove now unneed 'static markers<commit_after>#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;
#[macro_use]
extern crate clap;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::optim;
use torchrs::optim::OptimVal;
use torchrs::nn;
use torchrs::nn::{InitModuleStruct, GetFieldStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};
use torchrs::tensor;

use clap::{Arg, App};
#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let mut args = NetArgs::default();
    let matches = App::new("Torch.rs MNIST Example")
        .version("0.1")
        .author("Some Guy")
        .about("recognize handwritten digits")
        .arg(Arg::with_name("batch-size").takes_value(true))
        .arg(Arg::with_name("test-batch-size").takes_value(true))
        .arg(Arg::with_name("epochs").takes_value(true))
        .arg(Arg::with_name("lr").takes_value(true))
        .arg(Arg::with_name("momentum").takes_value(true))
        .arg(Arg::with_name("no-cuda").takes_value(false))
        .arg(Arg::with_name("seed").takes_value(true))
        .arg(Arg::with_name("log-interval").takes_value(true))
        .get_matches();
    let (b_size, tb_size, epochs, lr, momentum, seed, log_int) =
        (value_t!(matches.value_of("batch-size"), usize).ok(),
         value_t!(matches.value_of("test-batch-size"), usize).ok(),
         value_t!(matches.value_of("epochs"), u32).ok(),
         value_t!(matches.value_of("lr"), f32).ok(),
         value_t!(matches.value_of("momentum"), f32).ok(),
         value_t!(matches.value_of("seed"), usize).ok(),
         value_t!(matches.value_of("log-interval"), usize).ok());
    if let Some(b_size) = b_size {
        args.batch_size = b_size
    }
    if let Some(tb_size) = tb_size {
        args.test_batch_size = tb_size
    }
    if let Some(epochs) = epochs {
        args.epochs = epochs
    }
    if let Some(lr) = lr {
        args.lr = lr
    }
    if let Some(momentum) = momentum {
        args.momentum = momentum
    }
    if let Some(seed) = seed {
        args.seed = seed
    }
    if let Some(log_int) = log_int {
        args.log_interval = log_int
    }
    //XXX CUDA?
    args
}

#[derive(ModParse)]
struct Net<T: tensor::NumLimits<T>> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: tensor::NumLimits<T>> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl<T: tensor::NumLimits<T>> ModIntf<T> for Net<T> {
    fn forward(&mut self, args: &mut Variable<T>) -> Variable<T> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        x = F::relu(&F::max_pool2d(&F::dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                   (2, 2),
                                   &pool_val));
        x = x.view(&[-1, 320]);
        x = F::relu(&self.fc1.f(&mut x));
        x = F::dropout(&x, &dropout_val);
        x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
}

fn train<'a>(model: &mut Net<f32>,
             args: &NetArgs,
             train_loader: &D::BatchLoader<f32, i64>,
             epoch: u32,
             optimizer: &mut optim::OptIntf<f32>) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad(model);
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step(model);
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (mut data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(&mut data);
        test_loss += F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum() as u32;
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    // no data loaders yet so demonstrate with Vec placeholder

    let train_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::<f32>::build("../data").done(None),
                           D::DataLoaderArgs::default());

    let test_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::<f32>::build("../data").done(None),
                           D::DataLoaderArgs::default());
    let args = parse_args();
    let mut model = Net::new();
    let mut optimizer = optim::SGD::new(map_opt!{"lr" => args.lr, "momentum" => args.momentum});
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<|endoftext|>


<commit_before>#![feature(step_by)]

extern crate quickcheck;

use quickcheck::quickcheck;

fn sieve(n: usize) -> Vec<usize> {
    if n <= 1 {
        return vec!()
    }

    let mut marked: Vec<_> = (0..n+1).map(|_| false).collect();
    marked[0] = true;
    marked[1] = true;
    for p in 2..n {
        for i in (2*p..n).step_by(p) { // whoops!
            marked[i] = true;
        }
    }
    let mut primes = vec!();
    for (i, &m) in marked.iter().enumerate() {
        if !m { primes.push(i) }
    }
    primes
}

fn is_prime(n: usize) -> bool {
    n != 0 && n != 1 && (2..).take_while(|i| i * i <= n).all(|i| n % i != 0)
}

fn prop_all_prime(n: usize) -> bool {
    sieve(n).iter().all(|&i| is_prime(i))
}

fn prop_prime_iff_in_the_sieve(n: usize) -> bool {
    (0..(n + 1)).filter(|&i| is_prime(i)).collect() == sieve(n)
}

fn main() {
    quickcheck(prop_all_prime as fn(usize) -> bool);
    quickcheck(prop_prime_iff_in_the_sieve as fn(usize) -> bool);
}
<commit_msg>rustup<commit_after>#![feature(step_by)]

extern crate quickcheck;

use quickcheck::quickcheck;

fn sieve(n: usize) -> Vec<usize> {
    if n <= 1 {
        return vec!()
    }

    let mut marked: Vec<_> = (0..n+1).map(|_| false).collect();
    marked[0] = true;
    marked[1] = true;
    for p in 2..n {
        for i in (2*p..n).step_by(p) { // whoops!
            marked[i] = true;
        }
    }
    let mut primes = vec!();
    for (i, &m) in marked.iter().enumerate() {
        if !m { primes.push(i) }
    }
    primes
}

fn is_prime(n: usize) -> bool {
    n != 0 && n != 1 && (2..).take_while(|i| i * i <= n).all(|i| n % i != 0)
}

fn prop_all_prime(n: usize) -> bool {
    sieve(n).iter().all(|&i| is_prime(i))
}

fn prop_prime_iff_in_the_sieve(n: usize) -> bool {
    (0..(n + 1)).filter(|&i| is_prime(i)).collect::<Vec<_>>() == sieve(n)
}

fn main() {
    quickcheck(prop_all_prime as fn(usize) -> bool);
    quickcheck(prop_prime_iff_in_the_sieve as fn(usize) -> bool);
}
<|endoftext|>


<commit_before>generate_error_imports!();

generate_error_types!(InteractionError, InteractionErrorKind,
    Unknown => "Unknown Error"
);

<commit_msg>libimaginteraction: use generate_error_module!() macro and reexport generated types<commit_after>generate_error_module!(
    generate_error_types!(InteractionError, InteractionErrorKind,
        Unknown => "Unknown Error"
    );
);

pub use self::error::InteractionError;
pub use self::error::InteractionErrorKind;

<|endoftext|>