<commit_before>//! The master module provides the Master struct which instructs Workers which
//! portions of the image they should render and collects their results to combine
//! into the final image.

use std::path::PathBuf;
use std::io::prelude::*;
use std::collections::HashMap;
use std::net::ToSocketAddrs;
use std::iter;

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use image;
use mio::tcp::{TcpStream, Shutdown};
use mio::*;

use film::Image;
use exec::Config;
use exec::distrib::{worker, Instructions, Frame};
use sampler::BlockQueue;

/// Stores distributed rendering status. The frame is either InProgress and contains
/// partially rendered results from the workers who've reported the frame or is Completed
/// and has been saved out to disk.
#[derive(Debug)]
enum DistributedFrame {
    InProgress {
        // Which frame number this is
        frame: usize,
        // The number of workers who have reported results for this
        // frame so far
        num_reporting: usize,
        render: Image,
    },
    Completed,
}

impl DistributedFrame {
    pub fn start(frame_num: usize, img_dim: (usize, usize)) -> DistributedFrame {
        DistributedFrame::InProgress { frame: frame_num, num_reporting: 0, render: Image::new(img_dim) }
    }
}

/// Buffer for collecting results from a worker asynchronously. The buffer is filled
/// as we get readable events from the workers until it reaches the expected size.
/// After this the Frame is decoded and accumulated in the appropriate DistributedFrame
#[derive(Clone, Debug)]
struct WorkerBuffer {
    pub buf: Vec<u8>,
    pub expected_size: usize,
    pub currently_read: usize,
}

impl WorkerBuffer {
    pub fn new() -> WorkerBuffer {
        WorkerBuffer { buf: Vec::new(), expected_size: 8, currently_read: 0 }
    }
}

/// The Master organizes the set of Worker processes and instructions them what parts
/// of the scene to render. As workers report results the master collects them and
/// saves out the PNG once all workers have reported the frame.
pub struct Master {
    /// Hostnames of the workers to send work too
    workers: Vec<String>,
    connections: Vec<TcpStream>,
    /// Temporary buffers to store worker results in as they're
    /// read in over TCP
    worker_buffers: Vec<WorkerBuffer>,
    config: Config,
    /// List of the frames we're collecting or have completed
    frames: HashMap<usize, DistributedFrame>,
    img_dim: (usize, usize),
    /// Number of 8x8 blocks we're assigning per worker
    blocks_per_worker: usize,
    /// Remainder of blocks that will be tacked on to the last
    /// worker's assignment
    blocks_remainder: usize,
}

impl Master {
    /// Create a new master that will contact the worker nodes passed and
    /// send instructions on what parts of the scene to start rendering
    pub fn start_workers(workers: Vec<String>, config: Config, img_dim: (usize, usize))
                         -> (Master, EventLoop<Master>) {
        // Figure out how many blocks we have for this image and assign them to our workers
        let queue = BlockQueue::new((img_dim.0 as u32, img_dim.1 as u32), (8, 8), (0, 0));
        let blocks_per_worker = queue.len() / workers.len();
        let blocks_remainder = queue.len() % workers.len();

        let mut event_loop = EventLoop::<Master>::new().unwrap();
        let mut connections = Vec::new();

        // Connect to each worker and add them to the event loop
        for (i, host) in workers.iter().enumerate() {
            let addr = (&host[..], worker::PORT).to_socket_addrs().unwrap().next().unwrap();
            match TcpStream::connect(&addr) {
                Ok(stream) => {
                    // Each worker is identified in the event loop by their index in the vec
                    match event_loop.register(&stream, Token(i), EventSet::all(), PollOpt::level()){
                        Err(e) => println!("Error registering stream from {}: {}", host, e),
                        Ok(_) => {},
                    }
                    connections.push(stream);
                },
                Err(e) => println!("Failed to contact worker {}: {:?}", host, e),
            }
        }
        let worker_buffers: Vec<_> = iter::repeat(WorkerBuffer::new()).take(workers.len()).collect();
        let master = Master { workers: workers, connections: connections,
                              worker_buffers: worker_buffers, config: config,
                              frames: HashMap::new(),
                              img_dim: img_dim,
                              blocks_per_worker: blocks_per_worker,
                              blocks_remainder: blocks_remainder };
        (master, event_loop)
    }
    /// Read a result frame from a worker and save it into the list of frames we're collecting from
    /// all workers. Will save out the final render if all workers have reported results for this
    /// frame.
    fn save_results(&mut self, frame: Frame) {
        let frame_num = frame.frame as usize;
        let img_dim = self.img_dim;
        // Find the frame being reported and create it if we haven't received parts of this frame yet
        let mut df = self.frames.entry(frame_num).or_insert_with(
                        || DistributedFrame::start(frame_num, img_dim));

        let mut finished = false;
        match df {
            &mut DistributedFrame::InProgress { frame: _, ref mut num_reporting, ref mut render } => {
                // Collect results from the worker and see if we've finished the frame and can save
                // it out
                render.add_blocks(frame.block_size, &frame.blocks, &frame.pixels);
                *num_reporting += 1;
                if *num_reporting == self.workers.len() {
                    let out_file = match self.config.out_path.extension() {
                        Some(_) => self.config.out_path.clone(),
                        None => self.config.out_path.join(
                            PathBuf::from(format!("frame{:05}.png", frame_num))),
                    };
                    let img = render.get_srgb8();
                    let dim = render.dimensions();
                    match image::save_buffer(&out_file.as_path(), &img[..], dim.0 as u32,
                    dim.1 as u32, image::RGB(8)) {
                        Ok(_) => {},
                        Err(e) => println!("Error saving image, {}", e),
                    };
                    println!("Frame {}: rendered to '{}'\n--------------------",
                             frame_num, out_file.display());
                    finished = true;
                }
            },
            &mut DistributedFrame::Completed => println!("Worker reporting on completed frame {}?", frame_num),
        }
        // This is a bit awkward, since we borrow df in the match we can't mark it finished in there
        if finished {
            *df = DistributedFrame::Completed;
        }
    }
    /// Read results from a worker and accumulate this data in its worker buffer. Returns true if
    /// we've read the data being sent and can decode the buffer
    fn read_worker_buffer(&mut self, worker: usize) -> bool {
        let mut buf = &mut self.worker_buffers[worker];
        // If we haven't read the size of data being sent, read that now
        if buf.currently_read < 8 {
            // First 8 bytes are a u64 specifying the number of bytes being sent
            buf.buf.extend(iter::repeat(0u8).take(8));
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
            if buf.currently_read == buf.expected_size {
                // How many bytes we expect to get from the worker for a frame
                buf.expected_size = decode(&buf.buf[..]).unwrap();
                // Extend the Vec so we've got enough room for the remaning bytes, minus the 8 for the
                // encoded size header
                buf.buf.extend(iter::repeat(0u8).take(buf.expected_size - 8));
            }
        }
        // If we've finished reading the size header we can now start reading the frame data
        if buf.currently_read >= 8 {
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
        }
        buf.currently_read == buf.expected_size
    }
}

impl Handler for Master {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Master>, token: Token, event: EventSet) {
        let worker = token.as_usize();
        if event.is_error() {
            println!("Error connecting too {}", self.workers[worker]);
            match self.connections[worker].shutdown(Shutdown::Both) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // If the worker has terminated, shutdown the read end of the connection
        if event.is_hup() {
            match self.connections[worker].shutdown(Shutdown::Both) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // A worker is ready to receive instructions from us
        if event.is_writable() {
            let b_start = worker * self.blocks_per_worker;
            let b_count =
                if worker == self.workers.len() - 1 {
                    self.blocks_per_worker + self.blocks_remainder
                } else {
                    self.blocks_per_worker
                };
            let instr = Instructions::new(&self.config.scene_file,
                                          (self.config.frame_info.start, self.config.frame_info.end),
                                          b_start, b_count);
            // Encode and send our instructions to the worker
            let bytes = encode(&instr, SizeLimit::Infinite).unwrap();
            match self.connections[worker].write_all(&bytes[..]) {
                Err(e) => println!("Failed to send instructions to {}: {:?}", self.workers[worker], e),
                Ok(_) => {},
            }
            // Register that we no longer care about writable events on this connection
            event_loop.reregister(&self.connections[worker], token,
                                  EventSet::readable() | EventSet::error() | EventSet::hup(),
                                  PollOpt::level()).expect("Re-registering failed");
        }
        // Some results are available from a worker
        if event.is_readable() {
            // Read results from the worker, if we've accumulated all the data being sent
            // decode and accumulate the frame
            if self.read_worker_buffer(worker) {
                let frame: Frame = decode(&self.worker_buffers[worker].buf[..]).unwrap();
                self.save_results(frame);
                // Clean up the worker buffer for the next frame
                self.worker_buffers[worker].buf.clear();
                self.worker_buffers[worker].expected_size = 8;
                self.worker_buffers[worker].currently_read = 0;
            }
        }
        // After getting results from the worker we check if we've completed all our frames
        // and exit if so
        let all_complete = self.frames.values().fold(true,
                                |all, v| {
                                    match v {
                                        &DistributedFrame::Completed => true && all,
                                        _ => false,
                                    }
                                });
        // The frame start/end range is inclusive, so we must add 1 here
        let num_frames = self.config.frame_info.end - self.config.frame_info.start + 1;
        if self.frames.len() == num_frames && all_complete {
            event_loop.shutdown();
        }
    }
}

<commit_msg>DistributedFrame doesn't need to store the frame number<commit_after>//! The master module provides the Master struct which instructs Workers which
//! portions of the image they should render and collects their results to combine
//! into the final image.

use std::path::PathBuf;
use std::io::prelude::*;
use std::collections::HashMap;
use std::net::ToSocketAddrs;
use std::iter;

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use image;
use mio::tcp::{TcpStream, Shutdown};
use mio::*;

use film::Image;
use exec::Config;
use exec::distrib::{worker, Instructions, Frame};
use sampler::BlockQueue;

/// Stores distributed rendering status. The frame is either InProgress and contains
/// partially rendered results from the workers who've reported the frame or is Completed
/// and has been saved out to disk.
#[derive(Debug)]
enum DistributedFrame {
    InProgress {
        // The number of workers who have reported results for this
        // frame so far
        num_reporting: usize,
        render: Image,
    },
    Completed,
}

impl DistributedFrame {
    pub fn start(img_dim: (usize, usize)) -> DistributedFrame {
        DistributedFrame::InProgress { num_reporting: 0, render: Image::new(img_dim) }
    }
}

/// Buffer for collecting results from a worker asynchronously. The buffer is filled
/// as we get readable events from the workers until it reaches the expected size.
/// After this the Frame is decoded and accumulated in the appropriate DistributedFrame
#[derive(Clone, Debug)]
struct WorkerBuffer {
    pub buf: Vec<u8>,
    pub expected_size: usize,
    pub currently_read: usize,
}

impl WorkerBuffer {
    pub fn new() -> WorkerBuffer {
        WorkerBuffer { buf: Vec::new(), expected_size: 8, currently_read: 0 }
    }
}

/// The Master organizes the set of Worker processes and instructions them what parts
/// of the scene to render. As workers report results the master collects them and
/// saves out the PNG once all workers have reported the frame.
pub struct Master {
    /// Hostnames of the workers to send work too
    workers: Vec<String>,
    connections: Vec<TcpStream>,
    /// Temporary buffers to store worker results in as they're
    /// read in over TCP
    worker_buffers: Vec<WorkerBuffer>,
    config: Config,
    /// List of the frames we're collecting or have completed
    frames: HashMap<usize, DistributedFrame>,
    img_dim: (usize, usize),
    /// Number of 8x8 blocks we're assigning per worker
    blocks_per_worker: usize,
    /// Remainder of blocks that will be tacked on to the last
    /// worker's assignment
    blocks_remainder: usize,
}

impl Master {
    /// Create a new master that will contact the worker nodes passed and
    /// send instructions on what parts of the scene to start rendering
    pub fn start_workers(workers: Vec<String>, config: Config, img_dim: (usize, usize))
                         -> (Master, EventLoop<Master>) {
        // Figure out how many blocks we have for this image and assign them to our workers
        let queue = BlockQueue::new((img_dim.0 as u32, img_dim.1 as u32), (8, 8), (0, 0));
        let blocks_per_worker = queue.len() / workers.len();
        let blocks_remainder = queue.len() % workers.len();

        let mut event_loop = EventLoop::<Master>::new().unwrap();
        let mut connections = Vec::new();

        // Connect to each worker and add them to the event loop
        for (i, host) in workers.iter().enumerate() {
            let addr = (&host[..], worker::PORT).to_socket_addrs().unwrap().next().unwrap();
            match TcpStream::connect(&addr) {
                Ok(stream) => {
                    // Each worker is identified in the event loop by their index in the vec
                    match event_loop.register(&stream, Token(i), EventSet::all(), PollOpt::level()){
                        Err(e) => println!("Error registering stream from {}: {}", host, e),
                        Ok(_) => {},
                    }
                    connections.push(stream);
                },
                Err(e) => println!("Failed to contact worker {}: {:?}", host, e),
            }
        }
        let worker_buffers: Vec<_> = iter::repeat(WorkerBuffer::new()).take(workers.len()).collect();
        let master = Master { workers: workers, connections: connections,
                              worker_buffers: worker_buffers, config: config,
                              frames: HashMap::new(),
                              img_dim: img_dim,
                              blocks_per_worker: blocks_per_worker,
                              blocks_remainder: blocks_remainder };
        (master, event_loop)
    }
    /// Read a result frame from a worker and save it into the list of frames we're collecting from
    /// all workers. Will save out the final render if all workers have reported results for this
    /// frame.
    fn save_results(&mut self, frame: Frame) {
        let frame_num = frame.frame as usize;
        let img_dim = self.img_dim;
        // Find the frame being reported and create it if we haven't received parts of this frame yet
        let mut df = self.frames.entry(frame_num).or_insert_with(|| DistributedFrame::start(img_dim));

        let mut finished = false;
        match df {
            &mut DistributedFrame::InProgress { ref mut num_reporting, ref mut render } => {
                // Collect results from the worker and see if we've finished the frame and can save
                // it out
                render.add_blocks(frame.block_size, &frame.blocks, &frame.pixels);
                *num_reporting += 1;
                if *num_reporting == self.workers.len() {
                    let out_file = match self.config.out_path.extension() {
                        Some(_) => self.config.out_path.clone(),
                        None => self.config.out_path.join(
                            PathBuf::from(format!("frame{:05}.png", frame_num))),
                    };
                    let img = render.get_srgb8();
                    let dim = render.dimensions();
                    match image::save_buffer(&out_file.as_path(), &img[..], dim.0 as u32,
                    dim.1 as u32, image::RGB(8)) {
                        Ok(_) => {},
                        Err(e) => println!("Error saving image, {}", e),
                    };
                    println!("Frame {}: rendered to '{}'\n--------------------",
                             frame_num, out_file.display());
                    finished = true;
                }
            },
            &mut DistributedFrame::Completed => println!("Worker reporting on completed frame {}?", frame_num),
        }
        // This is a bit awkward, since we borrow df in the match we can't mark it finished in there
        if finished {
            *df = DistributedFrame::Completed;
        }
    }
    /// Read results from a worker and accumulate this data in its worker buffer. Returns true if
    /// we've read the data being sent and can decode the buffer
    fn read_worker_buffer(&mut self, worker: usize) -> bool {
        let mut buf = &mut self.worker_buffers[worker];
        // If we haven't read the size of data being sent, read that now
        if buf.currently_read < 8 {
            // First 8 bytes are a u64 specifying the number of bytes being sent
            buf.buf.extend(iter::repeat(0u8).take(8));
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
            if buf.currently_read == buf.expected_size {
                // How many bytes we expect to get from the worker for a frame
                buf.expected_size = decode(&buf.buf[..]).unwrap();
                // Extend the Vec so we've got enough room for the remaning bytes, minus the 8 for the
                // encoded size header
                buf.buf.extend(iter::repeat(0u8).take(buf.expected_size - 8));
            }
        }
        // If we've finished reading the size header we can now start reading the frame data
        if buf.currently_read >= 8 {
            match self.connections[worker].read(&mut buf.buf[buf.currently_read..]) {
                Ok(n) => buf.currently_read += n,
                Err(e) => println!("Error reading results from worker {}: {}", self.workers[worker], e),
            }
        }
        buf.currently_read == buf.expected_size
    }
}

impl Handler for Master {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Master>, token: Token, event: EventSet) {
        let worker = token.as_usize();
        if event.is_error() {
            println!("Error connecting too {}", self.workers[worker]);
            match self.connections[worker].shutdown(Shutdown::Both) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // If the worker has terminated, shutdown the read end of the connection
        if event.is_hup() {
            match self.connections[worker].shutdown(Shutdown::Both) {
                Err(e) => println!("Error shutting down worker {}: {}", worker, e),
                Ok(_) => {},
            }
            // Remove the connection from the event loop
            match event_loop.deregister(&self.connections[worker]) {
                Err(e) => println!("Error deregistering worker {}: {}", worker, e),
                Ok(_) => {},
            }
        }
        // A worker is ready to receive instructions from us
        if event.is_writable() {
            let b_start = worker * self.blocks_per_worker;
            let b_count =
                if worker == self.workers.len() - 1 {
                    self.blocks_per_worker + self.blocks_remainder
                } else {
                    self.blocks_per_worker
                };
            let instr = Instructions::new(&self.config.scene_file,
                                          (self.config.frame_info.start, self.config.frame_info.end),
                                          b_start, b_count);
            // Encode and send our instructions to the worker
            let bytes = encode(&instr, SizeLimit::Infinite).unwrap();
            match self.connections[worker].write_all(&bytes[..]) {
                Err(e) => println!("Failed to send instructions to {}: {:?}", self.workers[worker], e),
                Ok(_) => {},
            }
            // Register that we no longer care about writable events on this connection
            event_loop.reregister(&self.connections[worker], token,
                                  EventSet::readable() | EventSet::error() | EventSet::hup(),
                                  PollOpt::level()).expect("Re-registering failed");
        }
        // Some results are available from a worker
        if event.is_readable() {
            // Read results from the worker, if we've accumulated all the data being sent
            // decode and accumulate the frame
            if self.read_worker_buffer(worker) {
                let frame: Frame = decode(&self.worker_buffers[worker].buf[..]).unwrap();
                self.save_results(frame);
                // Clean up the worker buffer for the next frame
                self.worker_buffers[worker].buf.clear();
                self.worker_buffers[worker].expected_size = 8;
                self.worker_buffers[worker].currently_read = 0;
            }
        }
        // After getting results from the worker we check if we've completed all our frames
        // and exit if so
        let all_complete = self.frames.values().fold(true,
                                |all, v| {
                                    match v {
                                        &DistributedFrame::Completed => true && all,
                                        _ => false,
                                    }
                                });
        // The frame start/end range is inclusive, so we must add 1 here
        let num_frames = self.config.frame_info.end - self.config.frame_info.start + 1;
        if self.frames.len() == num_frames && all_complete {
            event_loop.shutdown();
        }
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate exonum;
extern crate exonum_harness;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

mod service {
    extern crate bodyparser;
    extern crate iron;
    extern crate router;

    use exonum::blockchain::{Blockchain, ApiContext, Service, Transaction};
    use exonum::messages::{RawTransaction, FromRaw, Message};
    use exonum::node::{ApiSender, TransactionSend};
    use exonum::storage::{Fork, Snapshot, Entry};
    use exonum::crypto::{PublicKey, Hash};
    use exonum::encoding;
    use exonum::api::{Api, ApiError};
    use self::iron::Handler;
    use self::iron::prelude::*;
    use self::router::Router;
    use serde_json;

    const SERVICE_ID: u16 = 1;
    const TX_INCREMENT_ID: u16 = 1;

    // "correct horse battery staple" brainwallet pubkey in Ed25519 with SHA-256 digest
    pub const ADMIN_KEY: &'static str = "506f27b1b4c2403f2602d663a059b026\
                                         2afd6a5bcda95a08dd96a4614a89f1b0";

    // // // // Schema // // // //

    struct CounterSchema<T> {
        view: T,
    }

    impl<T: AsRef<Snapshot>> CounterSchema<T> {
        fn new(view: T) -> Self {
            CounterSchema { view }
        }

        fn entry(&self) -> Entry<&Snapshot, u64> {
            Entry::new(vec![1], self.view.as_ref())
        }

        fn count(&self) -> Option<u64> {
            self.entry().get()
        }
    }

    impl<'a> CounterSchema<&'a mut Fork> {
        fn entry_mut(&mut self) -> Entry<&mut Fork, u64> {
            Entry::new(vec![1], self.view)
        }

        fn inc_count(&mut self, inc: u64) -> u64 {
            let count = self.count().unwrap_or(0) + inc;
            self.entry_mut().set(count);
            count
        }

        fn set_count(&mut self, count: u64) {
            self.entry_mut().set(count);
        }
    }

    // // // // Transactions // // // //

    message! {
        struct TxIncrement {
            const TYPE = SERVICE_ID;
            const ID = TX_INCREMENT_ID;
            const SIZE = 40;

            field author: &PublicKey [0 => 32]
            field by: u64 [32 => 40]
        }
    }

    impl Transaction for TxIncrement {
        fn verify(&self) -> bool {
            self.verify_signature(self.author())
        }

        fn execute(&self, fork: &mut Fork) {
            let mut schema = CounterSchema::new(fork);
            schema.inc_count(self.by());
        }
    }

    message! {
        struct TxReset {
            const TYPE = SERVICE_ID;
            const ID = TX_INCREMENT_ID;
            const SIZE = 32;

            field author: &PublicKey [0 => 32]
        }
    }

    impl TxReset {
        pub fn verify_author(&self) -> bool {
            use exonum::crypto::HexValue;
            *self.author() == PublicKey::from_hex(ADMIN_KEY).unwrap()
        }
    }

    impl Transaction for TxReset {
        fn verify(&self) -> bool {
            self.verify_author() && self.verify_signature(self.author())
        }

        fn execute(&self, fork: &mut Fork) {
            let mut schema = CounterSchema::new(fork);
            schema.set_count(0);
        }
    }

    // // // // API // // // //

    #[derive(Serialize, Deserialize)]
    pub struct TransactionResponse {
        pub tx_hash: Hash,
    }

    #[derive(Clone)]
    struct CounterApi {
        channel: ApiSender,
        blockchain: Blockchain,
    }

    impl CounterApi {
        fn increment(&self, req: &mut Request) -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TxIncrement>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = Box::new(transaction);
                    let tx_hash = transaction.hash();
                    self.channel.send(transaction).map_err(ApiError::from)?;
                    let json = TransactionResponse { tx_hash };
                    self.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        }

        fn count(&self) -> Option<u64> {
            let view = self.blockchain.snapshot();
            let schema = CounterSchema::new(&view);
            schema.count()
        }

        fn get_count(&self, _: &mut Request) -> IronResult<Response> {
            let count = self.count().unwrap_or(0);
            self.ok_response(&serde_json::to_value(count).unwrap())
        }

        fn reset(&self, req: &mut Request) -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TxReset>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = Box::new(transaction);
                    let tx_hash = transaction.hash();
                    self.channel.send(transaction).map_err(ApiError::from)?;
                    let json = TransactionResponse { tx_hash };
                    self.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        }

        fn wire_private(&self, router: &mut Router) {
            let self_ = self.clone();
            let reset = move |req: &mut Request| self_.reset(req);
            router.post("/reset", reset, "reset");
        }
    }

    impl Api for CounterApi {
        fn wire(&self, router: &mut Router) {
            let self_ = self.clone();
            let increment = move |req: &mut Request| self_.increment(req);
            router.post("/count", increment, "increment");

            let self_ = self.clone();
            let get_count = move |req: &mut Request| self_.get_count(req);
            router.get("/count", get_count, "get_count");
        }
    }

    // // // // Service // // // //

    pub struct CounterService;

    impl Service for CounterService {
        fn service_name(&self) -> &'static str {
            "counter"
        }

        fn service_id(&self) -> u16 {
            SERVICE_ID
        }

        /// Implement a method to deserialize transactions coming to the node.
        fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
            let trans: Box<Transaction> = match raw.message_type() {
                TX_INCREMENT_ID => Box::new(TxIncrement::from_raw(raw)?),
                _ => {
                    return Err(encoding::Error::IncorrectMessageType {
                        message_type: raw.message_type(),
                    });
                }
            };
            Ok(trans)
        }

        /// Create a REST `Handler` to process web requests to the node.
        fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
            let mut router = Router::new();
            let api = CounterApi {
                channel: ctx.node_channel().clone(),
                blockchain: ctx.blockchain().clone(),
            };
            api.wire(&mut router);
            Some(Box::new(router))
        }

        fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
            let mut router = Router::new();
            let api = CounterApi {
                channel: ctx.node_channel().clone(),
                blockchain: ctx.blockchain().clone(),
            };
            api.wire_private(&mut router);
            Some(Box::new(router))
        }
    }
}

use exonum::blockchain::Service;
use exonum::crypto::{self, HexValue, PublicKey};
use exonum::helpers::Height;
use exonum::messages::Message;
use exonum_harness::{TestHarness, HarnessApi};
use service::{ADMIN_KEY, CounterService, TxIncrement, TxReset, TransactionResponse};

fn inc_count(api: &HarnessApi, by: u64) -> TxIncrement {
    let (pubkey, key) = crypto::gen_keypair();
    // Create a presigned transaction
    let tx = TxIncrement::new(&pubkey, by, &key);

    let tx_info: TransactionResponse = api.post("counter", "count", &tx);
    assert_eq!(tx_info.tx_hash, tx.hash());
    tx
}

#[test]
fn test_inc_count() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();
    inc_count(&api, 5);

    harness.create_block();

    // Check that the user indeed is persisted by the service
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 5);
}

#[test]
fn test_inc_count_with_multiple_transactions() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();

    for _ in 0..100 {
        inc_count(&api, 1);
        inc_count(&api, 2);
        inc_count(&api, 3);
        inc_count(&api, 4);

        harness.create_block();
    }

    assert_eq!(harness.state().height(), Height(101));
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 1_000);
}

#[test]
fn test_inc_count_with_manual_tx_control() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();
    let tx_a = inc_count(&api, 5);
    let tx_b = inc_count(&api, 3);

    // Empty block
    harness.create_block_with_transactions(&[]);
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 0);

    harness.create_block_with_transactions(&[tx_b.hash()]);
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 3);

    harness.create_block_with_transactions(&[tx_a.hash()]);
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 8);
}

#[test]
fn test_private_api() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();
    inc_count(&api, 5);
    inc_count(&api, 3);

    harness.create_block();
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 8);

    let (pubkey, key) = crypto::gen_keypair_from_seed(&crypto::Seed::from_slice(
        &crypto::hash(b"correct horse battery staple")[..],
    ).unwrap());
    assert_eq!(pubkey, PublicKey::from_hex(ADMIN_KEY).unwrap());

    let tx = TxReset::new(&pubkey, &key);
    let tx_info: TransactionResponse = api.post_private("counter", "reset", &tx);
    assert_eq!(tx_info.tx_hash, tx.hash());

    harness.create_block();
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 0);
}
<commit_msg>Add tests for transaction probing<commit_after>#[macro_use]
extern crate exonum;
extern crate exonum_harness;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

mod service {
    extern crate bodyparser;
    extern crate iron;
    extern crate router;

    use exonum::blockchain::{Blockchain, ApiContext, Service, Transaction};
    use exonum::messages::{RawTransaction, FromRaw, Message};
    use exonum::node::{ApiSender, TransactionSend};
    use exonum::storage::{Fork, Snapshot, Entry};
    use exonum::crypto::{PublicKey, Hash};
    use exonum::encoding;
    use exonum::api::{Api, ApiError};
    use self::iron::Handler;
    use self::iron::prelude::*;
    use self::router::Router;
    use serde_json;

    const SERVICE_ID: u16 = 1;
    const TX_INCREMENT_ID: u16 = 1;

    // "correct horse battery staple" brainwallet pubkey in Ed25519 with SHA-256 digest
    pub const ADMIN_KEY: &'static str = "506f27b1b4c2403f2602d663a059b026\
                                         2afd6a5bcda95a08dd96a4614a89f1b0";

    // // // // Schema // // // //

    pub struct CounterSchema<T> {
        view: T,
    }

    impl<T: AsRef<Snapshot>> CounterSchema<T> {
        pub fn new(view: T) -> Self {
            CounterSchema { view }
        }

        fn entry(&self) -> Entry<&Snapshot, u64> {
            Entry::new(vec![1], self.view.as_ref())
        }

        pub fn count(&self) -> Option<u64> {
            self.entry().get()
        }
    }

    impl<'a> CounterSchema<&'a mut Fork> {
        fn entry_mut(&mut self) -> Entry<&mut Fork, u64> {
            Entry::new(vec![1], self.view)
        }

        fn inc_count(&mut self, inc: u64) -> u64 {
            let count = self.count().unwrap_or(0) + inc;
            self.entry_mut().set(count);
            count
        }

        fn set_count(&mut self, count: u64) {
            self.entry_mut().set(count);
        }
    }

    // // // // Transactions // // // //

    message! {
        struct TxIncrement {
            const TYPE = SERVICE_ID;
            const ID = TX_INCREMENT_ID;
            const SIZE = 40;

            field author: &PublicKey [0 => 32]
            field by: u64 [32 => 40]
        }
    }

    impl Transaction for TxIncrement {
        fn verify(&self) -> bool {
            self.verify_signature(self.author())
        }

        fn execute(&self, fork: &mut Fork) {
            let mut schema = CounterSchema::new(fork);
            schema.inc_count(self.by());
        }
    }

    message! {
        struct TxReset {
            const TYPE = SERVICE_ID;
            const ID = TX_INCREMENT_ID;
            const SIZE = 32;

            field author: &PublicKey [0 => 32]
        }
    }

    impl TxReset {
        pub fn verify_author(&self) -> bool {
            use exonum::crypto::HexValue;
            *self.author() == PublicKey::from_hex(ADMIN_KEY).unwrap()
        }
    }

    impl Transaction for TxReset {
        fn verify(&self) -> bool {
            self.verify_author() && self.verify_signature(self.author())
        }

        fn execute(&self, fork: &mut Fork) {
            let mut schema = CounterSchema::new(fork);
            schema.set_count(0);
        }
    }

    // // // // API // // // //

    #[derive(Serialize, Deserialize)]
    pub struct TransactionResponse {
        pub tx_hash: Hash,
    }

    #[derive(Clone)]
    struct CounterApi {
        channel: ApiSender,
        blockchain: Blockchain,
    }

    impl CounterApi {
        fn increment(&self, req: &mut Request) -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TxIncrement>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = Box::new(transaction);
                    let tx_hash = transaction.hash();
                    self.channel.send(transaction).map_err(ApiError::from)?;
                    let json = TransactionResponse { tx_hash };
                    self.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        }

        fn count(&self) -> Option<u64> {
            let view = self.blockchain.snapshot();
            let schema = CounterSchema::new(&view);
            schema.count()
        }

        fn get_count(&self, _: &mut Request) -> IronResult<Response> {
            let count = self.count().unwrap_or(0);
            self.ok_response(&serde_json::to_value(count).unwrap())
        }

        fn reset(&self, req: &mut Request) -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TxReset>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = Box::new(transaction);
                    let tx_hash = transaction.hash();
                    self.channel.send(transaction).map_err(ApiError::from)?;
                    let json = TransactionResponse { tx_hash };
                    self.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        }

        fn wire_private(&self, router: &mut Router) {
            let self_ = self.clone();
            let reset = move |req: &mut Request| self_.reset(req);
            router.post("/reset", reset, "reset");
        }
    }

    impl Api for CounterApi {
        fn wire(&self, router: &mut Router) {
            let self_ = self.clone();
            let increment = move |req: &mut Request| self_.increment(req);
            router.post("/count", increment, "increment");

            let self_ = self.clone();
            let get_count = move |req: &mut Request| self_.get_count(req);
            router.get("/count", get_count, "get_count");
        }
    }

    // // // // Service // // // //

    pub struct CounterService;

    impl Service for CounterService {
        fn service_name(&self) -> &'static str {
            "counter"
        }

        fn service_id(&self) -> u16 {
            SERVICE_ID
        }

        /// Implement a method to deserialize transactions coming to the node.
        fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
            let trans: Box<Transaction> = match raw.message_type() {
                TX_INCREMENT_ID => Box::new(TxIncrement::from_raw(raw)?),
                _ => {
                    return Err(encoding::Error::IncorrectMessageType {
                        message_type: raw.message_type(),
                    });
                }
            };
            Ok(trans)
        }

        /// Create a REST `Handler` to process web requests to the node.
        fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
            let mut router = Router::new();
            let api = CounterApi {
                channel: ctx.node_channel().clone(),
                blockchain: ctx.blockchain().clone(),
            };
            api.wire(&mut router);
            Some(Box::new(router))
        }

        fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
            let mut router = Router::new();
            let api = CounterApi {
                channel: ctx.node_channel().clone(),
                blockchain: ctx.blockchain().clone(),
            };
            api.wire_private(&mut router);
            Some(Box::new(router))
        }
    }
}

use exonum::blockchain::Service;
use exonum::crypto::{self, HexValue, PublicKey};
use exonum::helpers::Height;
use exonum::messages::Message;
use exonum_harness::{TestHarness, HarnessApi};
use service::{ADMIN_KEY, CounterService, TxIncrement, TxReset, TransactionResponse, CounterSchema};

fn inc_count(api: &HarnessApi, by: u64) -> TxIncrement {
    let (pubkey, key) = crypto::gen_keypair();
    // Create a presigned transaction
    let tx = TxIncrement::new(&pubkey, by, &key);

    let tx_info: TransactionResponse = api.post("counter", "count", &tx);
    assert_eq!(tx_info.tx_hash, tx.hash());
    tx
}

#[test]
fn test_inc_count() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();
    inc_count(&api, 5);

    harness.create_block();

    // Check that the user indeed is persisted by the service
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 5);
}

#[test]
fn test_inc_count_with_multiple_transactions() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();

    for _ in 0..100 {
        inc_count(&api, 1);
        inc_count(&api, 2);
        inc_count(&api, 3);
        inc_count(&api, 4);

        harness.create_block();
    }

    assert_eq!(harness.state().height(), Height(101));
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 1_000);
}

#[test]
fn test_inc_count_with_manual_tx_control() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();
    let tx_a = inc_count(&api, 5);
    let tx_b = inc_count(&api, 3);

    // Empty block
    harness.create_block_with_transactions(&[]);
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 0);

    harness.create_block_with_transactions(&[tx_b.hash()]);
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 3);

    harness.create_block_with_transactions(&[tx_a.hash()]);
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 8);
}

#[test]
fn test_private_api() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();
    inc_count(&api, 5);
    inc_count(&api, 3);

    harness.create_block();
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 8);

    let (pubkey, key) = crypto::gen_keypair_from_seed(&crypto::Seed::from_slice(
        &crypto::hash(b"correct horse battery staple")[..],
    ).unwrap());
    assert_eq!(pubkey, PublicKey::from_hex(ADMIN_KEY).unwrap());

    let tx = TxReset::new(&pubkey, &key);
    let tx_info: TransactionResponse = api.post_private("counter", "reset", &tx);
    assert_eq!(tx_info.tx_hash, tx.hash());

    harness.create_block();
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 0);
}

#[test]
fn test_probe() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();

    let tx = {
        let (pubkey, key) = crypto::gen_keypair();
        TxIncrement::new(&pubkey, 5, &key)
    };

    let snapshot = harness.probe(tx.clone());
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(5));
    // Verify that the patch has not been applied to the blockchain
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 0);

    let other_tx = {
        let (pubkey, key) = crypto::gen_keypair();
        TxIncrement::new(&pubkey, 3, &key)
    };

    let snapshot = harness.probe_all(vec![Box::new(tx.clone()), Box::new(other_tx.clone())]);
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(8));

    // Posting a transaction is not enough to change the blockchain!
    let _: TransactionResponse = api.post("counter", "count", &tx);
    let snapshot = harness.probe(other_tx.clone());
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(3));

    harness.create_block();
    let snapshot = harness.probe(other_tx.clone());
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(8));
}

#[test]
fn test_duplicate_tx() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();

    let tx = inc_count(&api, 5);
    harness.create_block();
    let _: TransactionResponse = api.post("counter", "count", &tx);
    let _: TransactionResponse = api.post("counter", "count", &tx);
    harness.create_block();
    let counter: u64 = api.get("counter", "count");
    assert_eq!(counter, 5);
}

#[test]
#[should_panic(expected = "Duplicate transactions in probe")]
fn test_probe_duplicate_tx_panic() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let harness = TestHarness::with_services(services);

    let tx = {
        let (pubkey, key) = crypto::gen_keypair();
        TxIncrement::new(&pubkey, 6, &key)
    };
    let snapshot = harness.probe_all(vec![Box::new(tx.clone()), Box::new(tx.clone())]);
    drop(snapshot);
}

#[test]
fn test_probe_advanced() {
    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();

    let tx = {
        let (pubkey, key) = crypto::gen_keypair();
        TxIncrement::new(&pubkey, 6, &key)
    };
    let other_tx = {
        let (pubkey, key) = crypto::gen_keypair();
        TxIncrement::new(&pubkey, 10, &key)
    };
    let admin_tx = {
        let (pubkey, key) = crypto::gen_keypair_from_seed(&crypto::Seed::from_slice(
            &crypto::hash(b"correct horse battery staple")[..],
        ).unwrap());
        assert_eq!(pubkey, PublicKey::from_hex(ADMIN_KEY).unwrap());

        TxReset::new(&pubkey, &key)
    };

    let snapshot = harness.probe(tx.clone());
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(6));
    // Check that data is not persisted
    let snapshot = harness.snapshot();
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), None);

    // Check dependency of the resulting snapshot on tx ordering
    let snapshot = harness.probe_all(vec![Box::new(tx.clone()), Box::new(admin_tx.clone())]);
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(0));
    let snapshot = harness.probe_all(vec![Box::new(admin_tx.clone()), Box::new(tx.clone())]);
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(6));
    // Check that data is (still) not persisted
    let snapshot = harness.snapshot();
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), None);

    api.send(other_tx);
    harness.create_block();
    let snapshot = harness.snapshot();
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(10));

    let snapshot = harness.probe(tx.clone());
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(16));
    // Check that data is not persisted
    let snapshot = harness.snapshot();
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(10));

    // Check dependency of the resulting snapshot on tx ordering
    let snapshot = harness.probe_all(vec![Box::new(tx.clone()), Box::new(admin_tx.clone())]);
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(0));
    let snapshot = harness.probe_all(vec![Box::new(admin_tx.clone()), Box::new(tx.clone())]);
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(6));
    // Check that data is (still) not persisted
    let snapshot = harness.snapshot();
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(10));
}

#[test]
fn test_probe_duplicate_tx() {
    //! Checks that committed transactions do not change the blockchain state when probed.

    let services: Vec<Box<Service>> = vec![Box::new(CounterService)];
    let mut harness = TestHarness::with_services(services);
    let api = harness.api();
    let tx = inc_count(&api, 5);

    let snapshot = harness.probe(tx.clone());
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(5));

    harness.create_block();

    let snapshot = harness.probe(tx.clone());
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(5));

    // Check the mixed case, when some probed transactions are committed and some are not
    let other_tx = inc_count(&api, 7);
    let snapshot = harness.probe_all(vec![Box::new(tx), Box::new(other_tx)]);
    let schema = CounterSchema::new(&snapshot);
    assert_eq!(schema.count(), Some(12));
}
<|endoftext|>


<commit_before>use common::util::*;
#[cfg(not(windows))]
use std::fs::set_permissions;

static TEST_EXISTING_FILE:           &str = "existing_file.txt";
static TEST_HELLO_WORLD_SOURCE:      &str = "hello_world.txt";
static TEST_HELLO_WORLD_DEST:        &str = "copy_of_hello_world.txt";
static TEST_HOW_ARE_YOU_SOURCE:      &str = "how_are_you.txt";
static TEST_HOW_ARE_YOU_DEST:        &str = "hello_dir/how_are_you.txt";
static TEST_COPY_TO_FOLDER:          &str = "hello_dir/";
static TEST_COPY_TO_FOLDER_FILE:     &str = "hello_dir/hello_world.txt";
static TEST_COPY_FROM_FOLDER:        &str = "hello_dir_with_file/";
static TEST_COPY_FROM_FOLDER_FILE:   &str = "hello_dir_with_file/hello_world.txt";
static TEST_COPY_TO_FOLDER_NEW:      &str = "hello_dir_new/";
static TEST_COPY_TO_FOLDER_NEW_FILE: &str = "hello_dir_new/hello_world.txt";

#[test]
fn test_cp_cp() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Invoke our binary to make the copy.
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
                     .arg(TEST_HELLO_WORLD_DEST)
                     .run();

    // Check that the exit code represents a successful copy.
    let exit_success = result.success;
    assert!(exit_success);

    // Check the content of the destination file that was copied.
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_duplicate_files() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(result.success);
    assert!(result.stderr.contains("specified more than once"));
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_multiple_files_target_is_file() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_EXISTING_FILE)
        .run();

    assert!(!result.success);
    assert!(result.stderr.contains("not a directory"));
}

#[test]
fn test_cp_directory_not_recursive() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_COPY_TO_FOLDER)
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(!result.success);
    assert!(result.stderr.contains("omitting directory"));
}

#[test]
fn test_cp_multiple_files() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
    assert_eq!(at.read(TEST_HOW_ARE_YOU_DEST), "How are you?\n");
}

#[test]
fn test_cp_recurse() {
    let (at, mut ucmd) = at_and_ucmd!();

    let result = ucmd
        .arg("-r")
        .arg(TEST_COPY_FROM_FOLDER)
        .arg(TEST_COPY_TO_FOLDER_NEW)
        .run();

    assert!(result.success);
    // Check the content of the destination file that was copied.
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_NEW_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs_t() {
    let (at, mut ucmd) = at_and_ucmd!();

    //using -t option
    let result_to_dir_t = ucmd
        .arg("-t")
        .arg(TEST_COPY_TO_FOLDER)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .run();
    assert!(result_to_dir_t.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    //using -t option
    let result_to_dir = scene.ucmd()
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();
    assert!(result_to_dir.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");

    let result_from_dir = scene.ucmd()
        .arg(TEST_COPY_FROM_FOLDER_FILE)
        .arg(TEST_HELLO_WORLD_DEST)
        .run();
    assert!(result_from_dir.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_arg_target_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("-t")
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_arg_no_target_directory() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("-v")
        .arg("-T")
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(!result.success);
    assert!(result.stderr.contains("cannot overwrite directory"));
}

#[test]
fn test_cp_arg_interactive() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .arg("-i")
        .pipe_in("N\n")
        .run();

    assert!(result.success);
    assert!(result.stderr.contains("Not overwriting"));
}

#[test]
#[cfg(target_os="unix")]
fn test_cp_arg_link() {
    use std::os::linux::fs::MetadataExt;

    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--link")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(result.success);
    assert_eq!(at.metadata(TEST_HELLO_WORLD_SOURCE).st_nlink(), 2);
}

#[test]
fn test_cp_arg_symlink() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--symbolic-link")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(result.success);
    assert!(at.is_symlink(TEST_HELLO_WORLD_DEST));
}

#[test]
fn test_cp_arg_no_clobber() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--no-clobber")
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HOW_ARE_YOU_SOURCE), "How are you?\n");
    assert!(result.stderr.contains("Not overwriting"));
}

#[test]
#[cfg(not(windows))]
fn test_cp_arg_force() {
    let (at, mut ucmd) = at_and_ucmd!();

    // create dest without write permissions
    let mut permissions = at.make_file(TEST_HELLO_WORLD_DEST).metadata().unwrap().permissions();
    permissions.set_readonly(true);
    set_permissions(at.plus(TEST_HELLO_WORLD_DEST), permissions).unwrap();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--force")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    println!("{:?}", result.stderr);
    println!("{:?}", result.stdout);

    assert!(result.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

/// TODO: write a better test that differentiates --remove-destination
/// from --force. Also this test currently doesn't work on
/// Windows. This test originally checked file timestamps, which
/// proved to be unreliable per target / CI platform
#[test]
#[cfg(not(windows))]
fn test_cp_arg_remove_destination() {
    let (at, mut ucmd) = at_and_ucmd!();

    // create dest without write permissions
    let mut permissions = at.make_file(TEST_HELLO_WORLD_DEST).metadata().unwrap().permissions();
    permissions.set_readonly(true);
    set_permissions(at.plus(TEST_HELLO_WORLD_DEST), permissions).unwrap();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--remove-destination")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_arg_backup() {
    let (at, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--backup")
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HOW_ARE_YOU_SOURCE), "Hello, World!\n");
    assert_eq!(at.read(&*format!("{}~", TEST_HOW_ARE_YOU_SOURCE)), "How are you?\n");
}

#[test]
fn test_cp_arg_suffix() {
    let (at, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--suffix")
        .arg(".bak")
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HOW_ARE_YOU_SOURCE), "Hello, World!\n");
    assert_eq!(at.read(&*format!("{}.bak", TEST_HOW_ARE_YOU_SOURCE)), "How are you?\n");
}
<commit_msg>cp: add test for "`cp` always creates backup"<commit_after>use common::util::*;
#[cfg(not(windows))]
use std::fs::set_permissions;

static TEST_EXISTING_FILE:           &str = "existing_file.txt";
static TEST_HELLO_WORLD_SOURCE:      &str = "hello_world.txt";
static TEST_HELLO_WORLD_DEST:        &str = "copy_of_hello_world.txt";
static TEST_HOW_ARE_YOU_SOURCE:      &str = "how_are_you.txt";
static TEST_HOW_ARE_YOU_DEST:        &str = "hello_dir/how_are_you.txt";
static TEST_COPY_TO_FOLDER:          &str = "hello_dir/";
static TEST_COPY_TO_FOLDER_FILE:     &str = "hello_dir/hello_world.txt";
static TEST_COPY_FROM_FOLDER:        &str = "hello_dir_with_file/";
static TEST_COPY_FROM_FOLDER_FILE:   &str = "hello_dir_with_file/hello_world.txt";
static TEST_COPY_TO_FOLDER_NEW:      &str = "hello_dir_new/";
static TEST_COPY_TO_FOLDER_NEW_FILE: &str = "hello_dir_new/hello_world.txt";

#[test]
fn test_cp_cp() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Invoke our binary to make the copy.
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
                     .arg(TEST_HELLO_WORLD_DEST)
                     .run();

    // Check that the exit code represents a successful copy.
    let exit_success = result.success;
    assert!(exit_success);

    // Check the content of the destination file that was copied.
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_existing_target() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_EXISTING_FILE)
        .run();

    assert!(result.success);

    // Check the content of the destination file
    assert_eq!(at.read(TEST_EXISTING_FILE), "Hello, World!\n");

    // No backup should have been created
    assert!(!at.file_exists(&*format!("{}~", TEST_EXISTING_FILE)));
}

#[test]
fn test_cp_duplicate_files() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(result.success);
    assert!(result.stderr.contains("specified more than once"));
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_multiple_files_target_is_file() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_EXISTING_FILE)
        .run();

    assert!(!result.success);
    assert!(result.stderr.contains("not a directory"));
}

#[test]
fn test_cp_directory_not_recursive() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_COPY_TO_FOLDER)
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(!result.success);
    assert!(result.stderr.contains("omitting directory"));
}

#[test]
fn test_cp_multiple_files() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
    assert_eq!(at.read(TEST_HOW_ARE_YOU_DEST), "How are you?\n");
}

#[test]
fn test_cp_recurse() {
    let (at, mut ucmd) = at_and_ucmd!();

    let result = ucmd
        .arg("-r")
        .arg(TEST_COPY_FROM_FOLDER)
        .arg(TEST_COPY_TO_FOLDER_NEW)
        .run();

    assert!(result.success);
    // Check the content of the destination file that was copied.
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_NEW_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs_t() {
    let (at, mut ucmd) = at_and_ucmd!();

    //using -t option
    let result_to_dir_t = ucmd
        .arg("-t")
        .arg(TEST_COPY_TO_FOLDER)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .run();
    assert!(result_to_dir_t.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    //using -t option
    let result_to_dir = scene.ucmd()
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();
    assert!(result_to_dir.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");

    let result_from_dir = scene.ucmd()
        .arg(TEST_COPY_FROM_FOLDER_FILE)
        .arg(TEST_HELLO_WORLD_DEST)
        .run();
    assert!(result_from_dir.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_arg_target_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("-t")
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_arg_no_target_directory() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("-v")
        .arg("-T")
        .arg(TEST_COPY_TO_FOLDER)
        .run();

    assert!(!result.success);
    assert!(result.stderr.contains("cannot overwrite directory"));
}

#[test]
fn test_cp_arg_interactive() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .arg("-i")
        .pipe_in("N\n")
        .run();

    assert!(result.success);
    assert!(result.stderr.contains("Not overwriting"));
}

#[test]
#[cfg(target_os="unix")]
fn test_cp_arg_link() {
    use std::os::linux::fs::MetadataExt;

    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--link")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(result.success);
    assert_eq!(at.metadata(TEST_HELLO_WORLD_SOURCE).st_nlink(), 2);
}

#[test]
fn test_cp_arg_symlink() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--symbolic-link")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(result.success);
    assert!(at.is_symlink(TEST_HELLO_WORLD_DEST));
}

#[test]
fn test_cp_arg_no_clobber() {
    let (at, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--no-clobber")
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HOW_ARE_YOU_SOURCE), "How are you?\n");
    assert!(result.stderr.contains("Not overwriting"));
}

#[test]
#[cfg(not(windows))]
fn test_cp_arg_force() {
    let (at, mut ucmd) = at_and_ucmd!();

    // create dest without write permissions
    let mut permissions = at.make_file(TEST_HELLO_WORLD_DEST).metadata().unwrap().permissions();
    permissions.set_readonly(true);
    set_permissions(at.plus(TEST_HELLO_WORLD_DEST), permissions).unwrap();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--force")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    println!("{:?}", result.stderr);
    println!("{:?}", result.stdout);

    assert!(result.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

/// TODO: write a better test that differentiates --remove-destination
/// from --force. Also this test currently doesn't work on
/// Windows. This test originally checked file timestamps, which
/// proved to be unreliable per target / CI platform
#[test]
#[cfg(not(windows))]
fn test_cp_arg_remove_destination() {
    let (at, mut ucmd) = at_and_ucmd!();

    // create dest without write permissions
    let mut permissions = at.make_file(TEST_HELLO_WORLD_DEST).metadata().unwrap().permissions();
    permissions.set_readonly(true);
    set_permissions(at.plus(TEST_HELLO_WORLD_DEST), permissions).unwrap();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--remove-destination")
        .arg(TEST_HELLO_WORLD_DEST)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_arg_backup() {
    let (at, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--backup")
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HOW_ARE_YOU_SOURCE), "Hello, World!\n");
    assert_eq!(at.read(&*format!("{}~", TEST_HOW_ARE_YOU_SOURCE)), "How are you?\n");
}

#[test]
fn test_cp_arg_suffix() {
    let (at, mut ucmd) = at_and_ucmd!();

    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
        .arg("--suffix")
        .arg(".bak")
        .arg(TEST_HOW_ARE_YOU_SOURCE)
        .run();

    assert!(result.success);
    assert_eq!(at.read(TEST_HOW_ARE_YOU_SOURCE), "Hello, World!\n");
    assert_eq!(at.read(&*format!("{}.bak", TEST_HOW_ARE_YOU_SOURCE)), "How are you?\n");
}
<|endoftext|>


<commit_before>
use ffi;
use super::util::FFTW_MUTEX;
use super::{c32, c64};

use num_traits::Zero;
use std::slice::{from_raw_parts, from_raw_parts_mut};
use std::os::raw::c_void;
use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};

pub struct RawVec<T> {
    n: usize,
    data: *mut T,
}

pub trait AlignedAllocable {
    unsafe fn alloc(n: usize) -> *mut Self;
}

impl AlignedAllocable for f64 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftw_alloc_real(n) }
}

impl AlignedAllocable for f32 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftwf_alloc_real(n) }
}

impl AlignedAllocable for c64 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftw_alloc_complex(n) }
}

impl AlignedAllocable for c32 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftwf_alloc_complex(n) }
}

impl<T> RawVec<T> {
    pub fn as_slice(&self) -> &[T] { unsafe { from_raw_parts(self.data, self.n) } }
    pub fn as_mut_slice(&mut self) -> &mut [T] { unsafe { from_raw_parts_mut(self.data, self.n) } }

    pub fn as_ptr(&self) -> *const T { self.data }
    pub fn as_mut_ptr(&mut self) -> *mut T { self.data }

    pub fn len(&self) -> usize { self.n }

    pub fn iter<'a>(&'a self) -> Iter<'a, T> { self.as_slice().iter() }
    pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> { self.as_mut_slice().iter_mut() }
}

impl<T> Drop for RawVec<T> {
    fn drop(&mut self) {
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        unsafe { ffi::fftw_free(self.data as *mut c_void) };
        drop(lock);
    }
}

impl<T> RawVec<T>
    where T: Zero + AlignedAllocable
{
    pub fn new(n: usize) -> Self {
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let ptr = unsafe { T::alloc(n) };
        drop(lock);
        let mut vec = RawVec { n: n, data: ptr };
        for v in vec.iter_mut() {
            *v = T::zero();
        }
        vec
    }
}

impl<T> Index<isize> for RawVec<T> {
    type Output = T;
    fn index(&self, index: isize) -> &Self::Output { unsafe { &*self.data.offset(index) } }
}

impl<T> IndexMut<isize> for RawVec<T> {
    fn index_mut(&mut self, index: isize) -> &mut Self::Output {
        unsafe { &mut *self.data.offset(index) }
    }
}
<commit_msg>Use usize for index of RawVec<commit_after>
use ffi;
use super::util::FFTW_MUTEX;
use super::{c32, c64};

use num_traits::Zero;
use std::slice::{from_raw_parts, from_raw_parts_mut};
use std::os::raw::c_void;
use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};

pub struct RawVec<T> {
    n: usize,
    data: *mut T,
}

pub trait AlignedAllocable {
    unsafe fn alloc(n: usize) -> *mut Self;
}

impl AlignedAllocable for f64 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftw_alloc_real(n) }
}

impl AlignedAllocable for f32 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftwf_alloc_real(n) }
}

impl AlignedAllocable for c64 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftw_alloc_complex(n) }
}

impl AlignedAllocable for c32 {
    unsafe fn alloc(n: usize) -> *mut Self { ffi::fftwf_alloc_complex(n) }
}

impl<T> RawVec<T> {
    pub fn as_slice(&self) -> &[T] { unsafe { from_raw_parts(self.data, self.n) } }
    pub fn as_mut_slice(&mut self) -> &mut [T] { unsafe { from_raw_parts_mut(self.data, self.n) } }

    pub fn as_ptr(&self) -> *const T { self.data }
    pub fn as_mut_ptr(&mut self) -> *mut T { self.data }

    pub fn len(&self) -> usize { self.n }

    pub fn iter<'a>(&'a self) -> Iter<'a, T> { self.as_slice().iter() }
    pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> { self.as_mut_slice().iter_mut() }
}

impl<T> Drop for RawVec<T> {
    fn drop(&mut self) {
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        unsafe { ffi::fftw_free(self.data as *mut c_void) };
        drop(lock);
    }
}

impl<T> RawVec<T>
    where T: Zero + AlignedAllocable
{
    pub fn new(n: usize) -> Self {
        let lock = FFTW_MUTEX.lock().expect("Cannot get lock");
        let ptr = unsafe { T::alloc(n) };
        drop(lock);
        let mut vec = RawVec { n: n, data: ptr };
        for v in vec.iter_mut() {
            *v = T::zero();
        }
        vec
    }
}

impl<T> Index<usize> for RawVec<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output { unsafe { &*self.data.offset(index) } }
}

impl<T> IndexMut<usize> for RawVec<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        unsafe { &mut *self.data.offset(index) }
    }
}
<|endoftext|>


<commit_before>//! The loader module
//!
//! Provides the Loader struct which is used to read data into
//! DataTables.

use std::io;
use std::io::prelude::*;
use std::io::{BufReader, Error, ErrorKind};
use std::fs::File;
use datatable::*;

/// Loader struct
///
/// Used to load and process data files into tables.
pub struct Loader<'a> {
    /// True if there are headers present in the file
    pub has_header: bool,
    file: &'a str,
    /// The delimiter character
    pub delimiter: char,
}

impl<'a> Loader<'a> {

    /// Constructs a new Loader.
    pub fn new(has_header: bool, file: &str, delimiter: char) -> Loader {
        Loader {
            has_header: has_header,
            file: file,
            delimiter: delimiter,
        }
    }

    /// Load the file from the loader with given delimiter.
    ///
    /// Pretty rudimentary with poor error handling.
    ///
    /// # Panics
    ///
    /// - The input data is not a float.
    ///
    /// # Failures
    ///
    /// - The input data is malformed (missing data, non-uniform rows etc.)
    pub fn load_file(self) -> Result<DataTable, io::Error> {
        let f = try!(File::open(self.file));
        let reader = BufReader::new(f);

        let mut table = DataTable::empty();

        let mut lines = reader.lines();

        if self.has_header {
            if let Some(line) = lines.next() {
                let line = try!(line);
                let values = line.split(self.delimiter);

                for val in values {
                    let mut column = DataColumn::empty();
                    column.name = Some(val.to_owned());
                    table.data_cols.push(column);
                }
            }
        }
        else {
            if let Some(line) = lines.next() {
                let line = try!(line);
                let values = line.split(self.delimiter);

                for val in values {
                    let mut column = DataColumn::empty();
                    column.push(val);

                    table.data_cols.push(column);
                }
            }
        }

        for line in lines {
            let line = try!(line);
            let values = line.split(self.delimiter);

            let mut idx = 0usize;

            for (i, val) in values.enumerate() {
                idx = i;
                if idx > table.cols() {
                    return Err(Error::new(ErrorKind::InvalidInput, "Malformed data format."));
                }

                table.data_cols[idx].push(val);
            }

            if idx != table.cols()-1 {
                return Err(Error::new(ErrorKind::InvalidInput, "Malformed data format."));
            }
        }

        table.shrink_to_fit();
        Ok(table)
    }
}

/// Load the specified file to a DataTable.
///
/// # Examples
///
/// ```no_run
/// use rusty_data::loader::load_file;
///
/// let table = load_file("path/to/file.data");
/// ```
pub fn load_file(file: &str) -> DataTable {
    let loader = Loader {
        has_header: false,
        file: file,
        delimiter: ',',
    };

    loader.load_file().unwrap()

}
<commit_msg>Default options and rustfmt.<commit_after>//! The loader module
//!
//! Provides the Loader struct which is used to read data into
//! DataTables.

use std::io;
use std::io::prelude::*;
use std::io::{BufReader, Error, ErrorKind};
use std::fs::File;
use datatable::*;

/// Loader struct
///
/// Used to load and process data files into tables.
pub struct Loader<'a> {
    /// True if there are headers present in the file
    pub has_header: bool,
    file: &'a str,
    /// The delimiter character
    pub delimiter: char,
}

impl<'a> Loader<'a> {
    /// Constructs a new Loader.
    pub fn new(has_header: bool, file: &str, delimiter: char) -> Loader {
        Loader {
            has_header: has_header,
            file: file,
            delimiter: delimiter,
        }
    }

    /// Creates a loader with default settings from a file string.
    ///
    /// The default settings are as follows:
    ///
    /// - has_header : false
    /// - delimiter : ','
    pub fn from_file_string(file_string: &str) -> Loader {
        Loader {
            has_header: false,
            file: file_string,
            delimiter: ',',
        }
    }

    /// Load the file from the loader with given delimiter.
    ///
    /// Pretty rudimentary with poor error handling.
    ///
    /// # Panics
    ///
    /// - The input data is not a float.
    ///
    /// # Failures
    ///
    /// - The input data is malformed (missing data, non-uniform rows etc.)
    pub fn load_file(self) -> Result<DataTable, io::Error> {
        let f = try!(File::open(self.file));
        let reader = BufReader::new(f);

        let mut table = DataTable::empty();

        let mut lines = reader.lines();

        if self.has_header {
            if let Some(line) = lines.next() {
                let line = try!(line);
                let values = line.split(self.delimiter);

                for val in values {
                    let mut column = DataColumn::empty();
                    column.name = Some(val.to_owned());
                    table.data_cols.push(column);
                }
            }
        } else {
            if let Some(line) = lines.next() {
                let line = try!(line);
                let values = line.split(self.delimiter);

                for val in values {
                    let mut column = DataColumn::empty();
                    column.push(val);

                    table.data_cols.push(column);
                }
            }
        }

        for line in lines {
            let line = try!(line);
            let values = line.split(self.delimiter);

            let mut idx = 0usize;

            for (i, val) in values.enumerate() {
                idx = i;
                if idx > table.cols() {
                    return Err(Error::new(ErrorKind::InvalidInput, "Malformed data format."));
                }

                table.data_cols[idx].push(val);
            }

            if idx != table.cols() - 1 {
                return Err(Error::new(ErrorKind::InvalidInput, "Malformed data format."));
            }
        }

        table.shrink_to_fit();
        Ok(table)
    }
}

/// Load the specified file to a DataTable.
///
/// # Examples
///
/// ```no_run
/// use rusty_data::loader::load_file;
///
/// let table = load_file("path/to/file.data");
/// ```
pub fn load_file(file: &str) -> DataTable {
    let loader = Loader {
        has_header: false,
        file: file,
        delimiter: ',',
    };

    loader.load_file().unwrap()

}
<|endoftext|>